blob: 223c3d9cc69efa1af38e6dee6c45ffc0f3733c55 [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>
Paul Gortmaker65a77212011-07-15 13:13:37 -040044#include <linux/module.h>
Takashi Iwai763f3562005-06-03 11:25:34 +020045#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 */
Rusty Russella67ff6a2011-12-15 13:49:36 +103064static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
Takashi Iwai763f3562005-06-03 11:25:34 +020065
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
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300394#define HDSPM_version0 (1<<0) /* not really defined but I guess */
Takashi Iwai763f3562005-06-03 11:25:34 +0200395#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
Andre Schramm56bde0f2013-01-09 14:40:18 +0100444#define HDSPM_AES32_wcSync 0x0100000
Remy Bruno3cee5a62006-10-16 12:46:32 +0200445#define HDSPM_AES32_wcFreq_bit 22
Adrian Knoth0dca1792011-01-26 19:32:14 +0100446/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function
Remy Bruno3cee5a62006-10-16 12:46:32 +0200447 HDSPM_bit2freq */
448#define HDSPM_AES32_syncref_bit 16
449/* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */
450
451#define HDSPM_AES32_AUTOSYNC_FROM_WORD 0
452#define HDSPM_AES32_AUTOSYNC_FROM_AES1 1
453#define HDSPM_AES32_AUTOSYNC_FROM_AES2 2
454#define HDSPM_AES32_AUTOSYNC_FROM_AES3 3
455#define HDSPM_AES32_AUTOSYNC_FROM_AES4 4
456#define HDSPM_AES32_AUTOSYNC_FROM_AES5 5
457#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6
458#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7
459#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8
Remy Bruno65345992007-08-31 12:21:08 +0200460#define HDSPM_AES32_AUTOSYNC_FROM_NONE 9
Remy Bruno3cee5a62006-10-16 12:46:32 +0200461
462/* status2 */
463/* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */
464#define HDSPM_LockAES 0x80
465#define HDSPM_LockAES1 0x80
466#define HDSPM_LockAES2 0x40
467#define HDSPM_LockAES3 0x20
468#define HDSPM_LockAES4 0x10
469#define HDSPM_LockAES5 0x8
470#define HDSPM_LockAES6 0x4
471#define HDSPM_LockAES7 0x2
472#define HDSPM_LockAES8 0x1
473/*
474 Timecode
475 After windows driver sources, bits 4*i to 4*i+3 give the input frequency on
476 AES i+1
477 bits 3210
478 0001 32kHz
479 0010 44.1kHz
480 0011 48kHz
481 0100 64kHz
482 0101 88.2kHz
483 0110 96kHz
484 0111 128kHz
485 1000 176.4kHz
486 1001 192kHz
487 NB: Timecode register doesn't seem to work on AES32 card revision 230
488*/
489
Takashi Iwai763f3562005-06-03 11:25:34 +0200490/* Mixer Values */
491#define UNITY_GAIN 32768 /* = 65536/2 */
492#define MINUS_INFINITY_GAIN 0
493
Takashi Iwai763f3562005-06-03 11:25:34 +0200494/* Number of channels for different Speed Modes */
495#define MADI_SS_CHANNELS 64
496#define MADI_DS_CHANNELS 32
497#define MADI_QS_CHANNELS 16
498
Adrian Knoth0dca1792011-01-26 19:32:14 +0100499#define RAYDAT_SS_CHANNELS 36
500#define RAYDAT_DS_CHANNELS 20
501#define RAYDAT_QS_CHANNELS 12
502
503#define AIO_IN_SS_CHANNELS 14
504#define AIO_IN_DS_CHANNELS 10
505#define AIO_IN_QS_CHANNELS 8
506#define AIO_OUT_SS_CHANNELS 16
507#define AIO_OUT_DS_CHANNELS 12
508#define AIO_OUT_QS_CHANNELS 10
509
Adrian Knothd2d10a22011-02-28 15:14:47 +0100510#define AES32_CHANNELS 16
511
Takashi Iwai763f3562005-06-03 11:25:34 +0200512/* the size of a substream (1 mono data stream) */
513#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024)
514#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
515
516/* the size of the area we need to allocate for DMA transfers. the
517 size is the same regardless of the number of channels, and
Adrian Knoth0dca1792011-01-26 19:32:14 +0100518 also the latency to use.
Takashi Iwai763f3562005-06-03 11:25:34 +0200519 for one direction !!!
520*/
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100521#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
Takashi Iwai763f3562005-06-03 11:25:34 +0200522#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
523
Adrian Knoth0dca1792011-01-26 19:32:14 +0100524#define HDSPM_RAYDAT_REV 211
525#define HDSPM_AIO_REV 212
526#define HDSPM_MADIFACE_REV 213
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
Takashi Iwai286bed02011-06-30 12:45:36 +0200894 signed char *channel_map_in;
895 signed char *channel_map_out;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100896
Takashi Iwai286bed02011-06-30 12:45:36 +0200897 signed char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs;
898 signed char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100899
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];
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300935 /* full mixer accessible 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
Adrian Knoth7d53a632012-01-04 14:31:16 +0100945 unsigned int serial;
946
Jaroslav Kysela730a5862011-01-27 13:03:15 +0100947 struct hdspm_peak_rms peak_rms;
Takashi Iwai763f3562005-06-03 11:25:34 +0200948};
949
Takashi Iwai763f3562005-06-03 11:25:34 +0200950
Alexey Dobriyancebe41d2010-02-06 00:21:03 +0200951static DEFINE_PCI_DEVICE_TABLE(snd_hdspm_ids) = {
Takashi Iwai763f3562005-06-03 11:25:34 +0200952 {
953 .vendor = PCI_VENDOR_ID_XILINX,
954 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
955 .subvendor = PCI_ANY_ID,
956 .subdevice = PCI_ANY_ID,
957 .class = 0,
958 .class_mask = 0,
959 .driver_data = 0},
960 {0,}
961};
962
963MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
964
965/* prototypes */
Bill Pembertone23e7a12012-12-06 12:35:10 -0500966static int snd_hdspm_create_alsa_devices(struct snd_card *card,
967 struct hdspm *hdspm);
968static int snd_hdspm_create_pcm(struct snd_card *card,
969 struct hdspm *hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +0200970
Adrian Knoth0dca1792011-01-26 19:32:14 +0100971static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
972static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
973static int hdspm_autosync_ref(struct hdspm *hdspm);
974static int snd_hdspm_set_defaults(struct hdspm *hdspm);
Adrian Knoth21a164d2012-10-19 17:42:23 +0200975static int hdspm_system_clock_mode(struct hdspm *hdspm);
Adrian Knoth0dca1792011-01-26 19:32:14 +0100976static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +0200977 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +0200978 unsigned int reg, int channels);
979
Remy Bruno3cee5a62006-10-16 12:46:32 +0200980static inline int HDSPM_bit2freq(int n)
981{
Denys Vlasenko62cef822008-04-14 13:04:18 +0200982 static const int bit2freq_tab[] = {
983 0, 32000, 44100, 48000, 64000, 88200,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200984 96000, 128000, 176400, 192000 };
985 if (n < 1 || n > 9)
986 return 0;
987 return bit2freq_tab[n];
988}
989
Adrian Knoth0dca1792011-01-26 19:32:14 +0100990/* Write/read to/from HDSPM with Adresses in Bytes
Takashi Iwai763f3562005-06-03 11:25:34 +0200991 not words but only 32Bit writes are allowed */
992
Takashi Iwai98274f02005-11-17 14:52:34 +0100993static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
Takashi Iwai763f3562005-06-03 11:25:34 +0200994 unsigned int val)
995{
996 writel(val, hdspm->iobase + reg);
997}
998
Takashi Iwai98274f02005-11-17 14:52:34 +0100999static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
Takashi Iwai763f3562005-06-03 11:25:34 +02001000{
1001 return readl(hdspm->iobase + reg);
1002}
1003
Adrian Knoth0dca1792011-01-26 19:32:14 +01001004/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
1005 mixer is write only on hardware so we have to cache him for read
Takashi Iwai763f3562005-06-03 11:25:34 +02001006 each fader is a u32, but uses only the first 16 bit */
1007
Takashi Iwai98274f02005-11-17 14:52:34 +01001008static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001009 unsigned int in)
1010{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001011 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001012 return 0;
1013
1014 return hdspm->mixer->ch[chan].in[in];
1015}
1016
Takashi Iwai98274f02005-11-17 14:52:34 +01001017static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001018 unsigned int pb)
1019{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001020 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001021 return 0;
1022 return hdspm->mixer->ch[chan].pb[pb];
1023}
1024
Denys Vlasenko62cef822008-04-14 13:04:18 +02001025static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001026 unsigned int in, unsigned short data)
1027{
1028 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
1029 return -1;
1030
1031 hdspm_write(hdspm,
1032 HDSPM_MADI_mixerBase +
1033 ((in + 128 * chan) * sizeof(u32)),
1034 (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
1035 return 0;
1036}
1037
Denys Vlasenko62cef822008-04-14 13:04:18 +02001038static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001039 unsigned int pb, unsigned short data)
1040{
1041 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
1042 return -1;
1043
1044 hdspm_write(hdspm,
1045 HDSPM_MADI_mixerBase +
1046 ((64 + pb + 128 * chan) * sizeof(u32)),
1047 (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
1048 return 0;
1049}
1050
1051
1052/* enable DMA for specific channels, now available for DSP-MADI */
Takashi Iwai98274f02005-11-17 14:52:34 +01001053static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001054{
1055 hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
1056}
1057
Takashi Iwai98274f02005-11-17 14:52:34 +01001058static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001059{
1060 hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
1061}
1062
1063/* check if same process is writing and reading */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001064static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001065{
1066 unsigned long flags;
1067 int ret = 1;
1068
1069 spin_lock_irqsave(&hdspm->lock, flags);
1070 if ((hdspm->playback_pid != hdspm->capture_pid) &&
1071 (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
1072 ret = 0;
1073 }
1074 spin_unlock_irqrestore(&hdspm->lock, flags);
1075 return ret;
1076}
1077
1078/* check for external sample rate */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001079static int hdspm_external_sample_rate(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001080{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001081 unsigned int status, status2, timecode;
1082 int syncref, rate = 0, rate_bits;
Takashi Iwai763f3562005-06-03 11:25:34 +02001083
Adrian Knoth0dca1792011-01-26 19:32:14 +01001084 switch (hdspm->io_type) {
1085 case AES32:
1086 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1087 status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01001088 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001089
1090 syncref = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001091
Remy Bruno3cee5a62006-10-16 12:46:32 +02001092 if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD &&
1093 status & HDSPM_AES32_wcLock)
Adrian Knoth0dca1792011-01-26 19:32:14 +01001094 return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF);
1095
Remy Bruno3cee5a62006-10-16 12:46:32 +02001096 if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001097 syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
1098 status2 & (HDSPM_LockAES >>
1099 (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1)))
1100 return HDSPM_bit2freq((timecode >> (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF);
Remy Bruno3cee5a62006-10-16 12:46:32 +02001101 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001102 break;
1103
1104 case MADIface:
1105 status = hdspm_read(hdspm, HDSPM_statusRegister);
1106
1107 if (!(status & HDSPM_madiLock)) {
1108 rate = 0; /* no lock */
1109 } else {
1110 switch (status & (HDSPM_status1_freqMask)) {
1111 case HDSPM_status1_F_0*1:
1112 rate = 32000; break;
1113 case HDSPM_status1_F_0*2:
1114 rate = 44100; break;
1115 case HDSPM_status1_F_0*3:
1116 rate = 48000; break;
1117 case HDSPM_status1_F_0*4:
1118 rate = 64000; break;
1119 case HDSPM_status1_F_0*5:
1120 rate = 88200; break;
1121 case HDSPM_status1_F_0*6:
1122 rate = 96000; break;
1123 case HDSPM_status1_F_0*7:
1124 rate = 128000; break;
1125 case HDSPM_status1_F_0*8:
1126 rate = 176400; break;
1127 case HDSPM_status1_F_0*9:
1128 rate = 192000; break;
1129 default:
1130 rate = 0; break;
1131 }
1132 }
1133
1134 break;
1135
1136 case MADI:
1137 case AIO:
1138 case RayDAT:
1139 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1140 status = hdspm_read(hdspm, HDSPM_statusRegister);
1141 rate = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02001142
Remy Bruno3cee5a62006-10-16 12:46:32 +02001143 /* if wordclock has synced freq and wordclock is valid */
1144 if ((status2 & HDSPM_wcLock) != 0 &&
Adrian Knothfedf1532011-06-12 17:26:18 +02001145 (status2 & HDSPM_SelSyncRef0) == 0) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02001146
1147 rate_bits = status2 & HDSPM_wcFreqMask;
1148
Adrian Knoth0dca1792011-01-26 19:32:14 +01001149
Remy Bruno3cee5a62006-10-16 12:46:32 +02001150 switch (rate_bits) {
1151 case HDSPM_wcFreq32:
1152 rate = 32000;
1153 break;
1154 case HDSPM_wcFreq44_1:
1155 rate = 44100;
1156 break;
1157 case HDSPM_wcFreq48:
1158 rate = 48000;
1159 break;
1160 case HDSPM_wcFreq64:
1161 rate = 64000;
1162 break;
1163 case HDSPM_wcFreq88_2:
1164 rate = 88200;
1165 break;
1166 case HDSPM_wcFreq96:
1167 rate = 96000;
1168 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001169 default:
1170 rate = 0;
1171 break;
1172 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001173 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001174
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001175 /* if rate detected and Syncref is Word than have it,
1176 * word has priority to MADI
1177 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001178 if (rate != 0 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001179 (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
Remy Bruno3cee5a62006-10-16 12:46:32 +02001180 return rate;
1181
Adrian Knoth0dca1792011-01-26 19:32:14 +01001182 /* maybe a madi input (which is taken if sel sync is madi) */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001183 if (status & HDSPM_madiLock) {
1184 rate_bits = status & HDSPM_madiFreqMask;
1185
1186 switch (rate_bits) {
1187 case HDSPM_madiFreq32:
1188 rate = 32000;
1189 break;
1190 case HDSPM_madiFreq44_1:
1191 rate = 44100;
1192 break;
1193 case HDSPM_madiFreq48:
1194 rate = 48000;
1195 break;
1196 case HDSPM_madiFreq64:
1197 rate = 64000;
1198 break;
1199 case HDSPM_madiFreq88_2:
1200 rate = 88200;
1201 break;
1202 case HDSPM_madiFreq96:
1203 rate = 96000;
1204 break;
1205 case HDSPM_madiFreq128:
1206 rate = 128000;
1207 break;
1208 case HDSPM_madiFreq176_4:
1209 rate = 176400;
1210 break;
1211 case HDSPM_madiFreq192:
1212 rate = 192000;
1213 break;
1214 default:
1215 rate = 0;
1216 break;
1217 }
Adrian Knothd12c51d2011-07-29 03:11:03 +02001218
1219 /* QS and DS rates normally can not be detected
1220 * automatically by the card. Only exception is MADI
1221 * in 96k frame mode.
1222 *
1223 * So if we read SS values (32 .. 48k), check for
1224 * user-provided DS/QS bits in the control register
1225 * and multiply the base frequency accordingly.
1226 */
1227 if (rate <= 48000) {
1228 if (hdspm->control_register & HDSPM_QuadSpeed)
1229 rate *= 4;
1230 else if (hdspm->control_register &
1231 HDSPM_DoubleSpeed)
1232 rate *= 2;
1233 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02001234 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001235 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001236 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001237
1238 return rate;
Takashi Iwai763f3562005-06-03 11:25:34 +02001239}
1240
Adrian Knoth7cb155f2011-08-15 00:22:53 +02001241/* return latency in samples per period */
1242static int hdspm_get_latency(struct hdspm *hdspm)
1243{
1244 int n;
1245
1246 n = hdspm_decode_latency(hdspm->control_register);
1247
1248 /* Special case for new RME cards with 32 samples period size.
1249 * The three latency bits in the control register
1250 * (HDSP_LatencyMask) encode latency values of 64 samples as
1251 * 0, 128 samples as 1 ... 4096 samples as 6. For old cards, 7
1252 * denotes 8192 samples, but on new cards like RayDAT or AIO,
1253 * it corresponds to 32 samples.
1254 */
1255 if ((7 == n) && (RayDAT == hdspm->io_type || AIO == hdspm->io_type))
1256 n = -1;
1257
1258 return 1 << (n + 6);
1259}
1260
Takashi Iwai763f3562005-06-03 11:25:34 +02001261/* Latency function */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001262static inline void hdspm_compute_period_size(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001263{
Adrian Knoth7cb155f2011-08-15 00:22:53 +02001264 hdspm->period_bytes = 4 * hdspm_get_latency(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001265}
1266
Adrian Knoth0dca1792011-01-26 19:32:14 +01001267
1268static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001269{
1270 int position;
1271
1272 position = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth483cee72011-02-23 11:43:09 +01001273
1274 switch (hdspm->io_type) {
1275 case RayDAT:
1276 case AIO:
1277 position &= HDSPM_BufferPositionMask;
1278 position /= 4; /* Bytes per sample */
1279 break;
1280 default:
1281 position = (position & HDSPM_BufferID) ?
1282 (hdspm->period_bytes / 4) : 0;
1283 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001284
1285 return position;
1286}
1287
1288
Takashi Iwai98274f02005-11-17 14:52:34 +01001289static inline void hdspm_start_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001290{
1291 s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
1292 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1293}
1294
Takashi Iwai98274f02005-11-17 14:52:34 +01001295static inline void hdspm_stop_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001296{
1297 s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
1298 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1299}
1300
1301/* should I silence all or only opened ones ? doit all for first even is 4MB*/
Denys Vlasenko62cef822008-04-14 13:04:18 +02001302static void hdspm_silence_playback(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001303{
1304 int i;
1305 int n = hdspm->period_bytes;
1306 void *buf = hdspm->playback_buffer;
1307
Remy Bruno3cee5a62006-10-16 12:46:32 +02001308 if (buf == NULL)
1309 return;
Takashi Iwai763f3562005-06-03 11:25:34 +02001310
1311 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
1312 memset(buf, 0, n);
1313 buf += HDSPM_CHANNEL_BUFFER_BYTES;
1314 }
1315}
1316
Adrian Knoth0dca1792011-01-26 19:32:14 +01001317static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames)
Takashi Iwai763f3562005-06-03 11:25:34 +02001318{
1319 int n;
1320
1321 spin_lock_irq(&s->lock);
1322
Adrian Knoth2e610272011-08-15 00:22:54 +02001323 if (32 == frames) {
1324 /* Special case for new RME cards like RayDAT/AIO which
1325 * support period sizes of 32 samples. Since latency is
1326 * encoded in the three bits of HDSP_LatencyMask, we can only
1327 * have values from 0 .. 7. While 0 still means 64 samples and
1328 * 6 represents 4096 samples on all cards, 7 represents 8192
1329 * on older cards and 32 samples on new cards.
1330 *
1331 * In other words, period size in samples is calculated by
1332 * 2^(n+6) with n ranging from 0 .. 7.
1333 */
1334 n = 7;
1335 } else {
1336 frames >>= 7;
1337 n = 0;
1338 while (frames) {
1339 n++;
1340 frames >>= 1;
1341 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001342 }
Adrian Knoth2e610272011-08-15 00:22:54 +02001343
Takashi Iwai763f3562005-06-03 11:25:34 +02001344 s->control_register &= ~HDSPM_LatencyMask;
1345 s->control_register |= hdspm_encode_latency(n);
1346
1347 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1348
1349 hdspm_compute_period_size(s);
1350
1351 spin_unlock_irq(&s->lock);
1352
1353 return 0;
1354}
1355
Adrian Knoth0dca1792011-01-26 19:32:14 +01001356static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period)
1357{
1358 u64 freq_const;
1359
1360 if (period == 0)
1361 return 0;
1362
1363 switch (hdspm->io_type) {
1364 case MADI:
1365 case AES32:
1366 freq_const = 110069313433624ULL;
1367 break;
1368 case RayDAT:
1369 case AIO:
1370 freq_const = 104857600000000ULL;
1371 break;
1372 case MADIface:
1373 freq_const = 131072000000000ULL;
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001374 break;
1375 default:
1376 snd_BUG();
1377 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001378 }
1379
1380 return div_u64(freq_const, period);
1381}
1382
1383
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001384static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
1385{
1386 u64 n;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001387
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001388 if (rate >= 112000)
1389 rate /= 4;
1390 else if (rate >= 56000)
1391 rate /= 2;
1392
Adrian Knoth0dca1792011-01-26 19:32:14 +01001393 switch (hdspm->io_type) {
1394 case MADIface:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001395 n = 131072000000000ULL; /* 125 MHz */
1396 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001397 case MADI:
1398 case AES32:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001399 n = 110069313433624ULL; /* 105 MHz */
1400 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001401 case RayDAT:
1402 case AIO:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001403 n = 104857600000000ULL; /* 100 MHz */
1404 break;
1405 default:
1406 snd_BUG();
1407 return;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001408 }
1409
Takashi Iwai3f7440a2009-06-05 17:40:04 +02001410 n = div_u64(n, rate);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001411 /* n should be less than 2^32 for being written to FREQ register */
Takashi Iwaida3cec32008-08-08 17:12:14 +02001412 snd_BUG_ON(n >> 32);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001413 hdspm_write(hdspm, HDSPM_freqReg, (u32)n);
1414}
Takashi Iwai763f3562005-06-03 11:25:34 +02001415
1416/* dummy set rate lets see what happens */
Takashi Iwai98274f02005-11-17 14:52:34 +01001417static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
Takashi Iwai763f3562005-06-03 11:25:34 +02001418{
Takashi Iwai763f3562005-06-03 11:25:34 +02001419 int current_rate;
1420 int rate_bits;
1421 int not_set = 0;
Remy Bruno65345992007-08-31 12:21:08 +02001422 int current_speed, target_speed;
Takashi Iwai763f3562005-06-03 11:25:34 +02001423
1424 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
1425 it (e.g. during module initialization).
1426 */
1427
1428 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
1429
Adrian Knoth0dca1792011-01-26 19:32:14 +01001430 /* SLAVE --- */
Takashi Iwai763f3562005-06-03 11:25:34 +02001431 if (called_internally) {
1432
Adrian Knoth0dca1792011-01-26 19:32:14 +01001433 /* request from ctl or card initialization
1434 just make a warning an remember setting
1435 for future master mode switching */
1436
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001437 snd_printk(KERN_WARNING "HDSPM: "
1438 "Warning: device is not running "
1439 "as a clock master.\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001440 not_set = 1;
1441 } else {
1442
1443 /* hw_param request while in AutoSync mode */
1444 int external_freq =
1445 hdspm_external_sample_rate(hdspm);
1446
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001447 if (hdspm_autosync_ref(hdspm) ==
1448 HDSPM_AUTOSYNC_FROM_NONE) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001449
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001450 snd_printk(KERN_WARNING "HDSPM: "
1451 "Detected no Externel Sync \n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001452 not_set = 1;
1453
1454 } else if (rate != external_freq) {
1455
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001456 snd_printk(KERN_WARNING "HDSPM: "
1457 "Warning: No AutoSync source for "
1458 "requested rate\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001459 not_set = 1;
1460 }
1461 }
1462 }
1463
1464 current_rate = hdspm->system_sample_rate;
1465
1466 /* Changing between Singe, Double and Quad speed is not
1467 allowed if any substreams are open. This is because such a change
1468 causes a shift in the location of the DMA buffers and a reduction
1469 in the number of available buffers.
1470
1471 Note that a similar but essentially insoluble problem exists for
1472 externally-driven rate changes. All we can do is to flag rate
Adrian Knoth0dca1792011-01-26 19:32:14 +01001473 changes in the read/write routines.
Takashi Iwai763f3562005-06-03 11:25:34 +02001474 */
1475
Remy Bruno65345992007-08-31 12:21:08 +02001476 if (current_rate <= 48000)
1477 current_speed = HDSPM_SPEED_SINGLE;
1478 else if (current_rate <= 96000)
1479 current_speed = HDSPM_SPEED_DOUBLE;
1480 else
1481 current_speed = HDSPM_SPEED_QUAD;
1482
1483 if (rate <= 48000)
1484 target_speed = HDSPM_SPEED_SINGLE;
1485 else if (rate <= 96000)
1486 target_speed = HDSPM_SPEED_DOUBLE;
1487 else
1488 target_speed = HDSPM_SPEED_QUAD;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001489
Takashi Iwai763f3562005-06-03 11:25:34 +02001490 switch (rate) {
1491 case 32000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001492 rate_bits = HDSPM_Frequency32KHz;
1493 break;
1494 case 44100:
Takashi Iwai763f3562005-06-03 11:25:34 +02001495 rate_bits = HDSPM_Frequency44_1KHz;
1496 break;
1497 case 48000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001498 rate_bits = HDSPM_Frequency48KHz;
1499 break;
1500 case 64000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001501 rate_bits = HDSPM_Frequency64KHz;
1502 break;
1503 case 88200:
Takashi Iwai763f3562005-06-03 11:25:34 +02001504 rate_bits = HDSPM_Frequency88_2KHz;
1505 break;
1506 case 96000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001507 rate_bits = HDSPM_Frequency96KHz;
1508 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001509 case 128000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001510 rate_bits = HDSPM_Frequency128KHz;
1511 break;
1512 case 176400:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001513 rate_bits = HDSPM_Frequency176_4KHz;
1514 break;
1515 case 192000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001516 rate_bits = HDSPM_Frequency192KHz;
1517 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001518 default:
1519 return -EINVAL;
1520 }
1521
Remy Bruno65345992007-08-31 12:21:08 +02001522 if (current_speed != target_speed
Takashi Iwai763f3562005-06-03 11:25:34 +02001523 && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
1524 snd_printk
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001525 (KERN_ERR "HDSPM: "
Remy Bruno65345992007-08-31 12:21:08 +02001526 "cannot change from %s speed to %s speed mode "
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001527 "(capture PID = %d, playback PID = %d)\n",
Remy Bruno65345992007-08-31 12:21:08 +02001528 hdspm_speed_names[current_speed],
1529 hdspm_speed_names[target_speed],
Takashi Iwai763f3562005-06-03 11:25:34 +02001530 hdspm->capture_pid, hdspm->playback_pid);
1531 return -EBUSY;
1532 }
1533
1534 hdspm->control_register &= ~HDSPM_FrequencyMask;
1535 hdspm->control_register |= rate_bits;
1536 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1537
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001538 /* For AES32, need to set DDS value in FREQ register
1539 For MADI, also apparently */
1540 hdspm_set_dds_value(hdspm, rate);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001541
1542 if (AES32 == hdspm->io_type && rate != current_rate)
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001543 hdspm_write(hdspm, HDSPM_eeprom_wr, 0);
Takashi Iwai763f3562005-06-03 11:25:34 +02001544
1545 hdspm->system_sample_rate = rate;
1546
Adrian Knoth0dca1792011-01-26 19:32:14 +01001547 if (rate <= 48000) {
1548 hdspm->channel_map_in = hdspm->channel_map_in_ss;
1549 hdspm->channel_map_out = hdspm->channel_map_out_ss;
1550 hdspm->max_channels_in = hdspm->ss_in_channels;
1551 hdspm->max_channels_out = hdspm->ss_out_channels;
1552 hdspm->port_names_in = hdspm->port_names_in_ss;
1553 hdspm->port_names_out = hdspm->port_names_out_ss;
1554 } else if (rate <= 96000) {
1555 hdspm->channel_map_in = hdspm->channel_map_in_ds;
1556 hdspm->channel_map_out = hdspm->channel_map_out_ds;
1557 hdspm->max_channels_in = hdspm->ds_in_channels;
1558 hdspm->max_channels_out = hdspm->ds_out_channels;
1559 hdspm->port_names_in = hdspm->port_names_in_ds;
1560 hdspm->port_names_out = hdspm->port_names_out_ds;
1561 } else {
1562 hdspm->channel_map_in = hdspm->channel_map_in_qs;
1563 hdspm->channel_map_out = hdspm->channel_map_out_qs;
1564 hdspm->max_channels_in = hdspm->qs_in_channels;
1565 hdspm->max_channels_out = hdspm->qs_out_channels;
1566 hdspm->port_names_in = hdspm->port_names_in_qs;
1567 hdspm->port_names_out = hdspm->port_names_out_qs;
1568 }
1569
Takashi Iwai763f3562005-06-03 11:25:34 +02001570 if (not_set != 0)
1571 return -1;
1572
1573 return 0;
1574}
1575
1576/* mainly for init to 0 on load */
Takashi Iwai98274f02005-11-17 14:52:34 +01001577static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
Takashi Iwai763f3562005-06-03 11:25:34 +02001578{
1579 int i, j;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001580 unsigned int gain;
1581
1582 if (sgain > UNITY_GAIN)
1583 gain = UNITY_GAIN;
1584 else if (sgain < 0)
1585 gain = 0;
1586 else
1587 gain = sgain;
Takashi Iwai763f3562005-06-03 11:25:34 +02001588
1589 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
1590 for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
1591 hdspm_write_in_gain(hdspm, i, j, gain);
1592 hdspm_write_pb_gain(hdspm, i, j, gain);
1593 }
1594}
1595
1596/*----------------------------------------------------------------------------
1597 MIDI
1598 ----------------------------------------------------------------------------*/
1599
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001600static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm,
1601 int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001602{
1603 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001604 return hdspm_read(hdspm, hdspm->midi[id].dataIn);
Takashi Iwai763f3562005-06-03 11:25:34 +02001605}
1606
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001607static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
1608 int val)
Takashi Iwai763f3562005-06-03 11:25:34 +02001609{
1610 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001611 return hdspm_write(hdspm, hdspm->midi[id].dataOut, val);
Takashi Iwai763f3562005-06-03 11:25:34 +02001612}
1613
Takashi Iwai98274f02005-11-17 14:52:34 +01001614static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001615{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001616 return hdspm_read(hdspm, hdspm->midi[id].statusIn) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001617}
1618
Takashi Iwai98274f02005-11-17 14:52:34 +01001619static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001620{
1621 int fifo_bytes_used;
1622
Adrian Knoth0dca1792011-01-26 19:32:14 +01001623 fifo_bytes_used = hdspm_read(hdspm, hdspm->midi[id].statusOut) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001624
1625 if (fifo_bytes_used < 128)
1626 return 128 - fifo_bytes_used;
1627 else
1628 return 0;
1629}
1630
Denys Vlasenko62cef822008-04-14 13:04:18 +02001631static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001632{
1633 while (snd_hdspm_midi_input_available (hdspm, id))
1634 snd_hdspm_midi_read_byte (hdspm, id);
1635}
1636
Takashi Iwai98274f02005-11-17 14:52:34 +01001637static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001638{
1639 unsigned long flags;
1640 int n_pending;
1641 int to_write;
1642 int i;
1643 unsigned char buf[128];
1644
1645 /* Output is not interrupt driven */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001646
Takashi Iwai763f3562005-06-03 11:25:34 +02001647 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001648 if (hmidi->output &&
1649 !snd_rawmidi_transmit_empty (hmidi->output)) {
1650 n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm,
1651 hmidi->id);
1652 if (n_pending > 0) {
1653 if (n_pending > (int)sizeof (buf))
1654 n_pending = sizeof (buf);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001655
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001656 to_write = snd_rawmidi_transmit (hmidi->output, buf,
1657 n_pending);
1658 if (to_write > 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001659 for (i = 0; i < to_write; ++i)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001660 snd_hdspm_midi_write_byte (hmidi->hdspm,
1661 hmidi->id,
1662 buf[i]);
Takashi Iwai763f3562005-06-03 11:25:34 +02001663 }
1664 }
1665 }
1666 spin_unlock_irqrestore (&hmidi->lock, flags);
1667 return 0;
1668}
1669
Takashi Iwai98274f02005-11-17 14:52:34 +01001670static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001671{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001672 unsigned char buf[128]; /* this buffer is designed to match the MIDI
1673 * input FIFO size
1674 */
Takashi Iwai763f3562005-06-03 11:25:34 +02001675 unsigned long flags;
1676 int n_pending;
1677 int i;
1678
1679 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001680 n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id);
1681 if (n_pending > 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001682 if (hmidi->input) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001683 if (n_pending > (int)sizeof (buf))
Takashi Iwai763f3562005-06-03 11:25:34 +02001684 n_pending = sizeof (buf);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001685 for (i = 0; i < n_pending; ++i)
1686 buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm,
1687 hmidi->id);
1688 if (n_pending)
1689 snd_rawmidi_receive (hmidi->input, buf,
1690 n_pending);
Takashi Iwai763f3562005-06-03 11:25:34 +02001691 } else {
1692 /* flush the MIDI input FIFO */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001693 while (n_pending--)
1694 snd_hdspm_midi_read_byte (hmidi->hdspm,
1695 hmidi->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02001696 }
1697 }
1698 hmidi->pending = 0;
Adrian Knothc0da0012011-06-12 17:26:17 +02001699 spin_unlock_irqrestore(&hmidi->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001700
Adrian Knothc0da0012011-06-12 17:26:17 +02001701 spin_lock_irqsave(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001702 hmidi->hdspm->control_register |= hmidi->ie;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001703 hdspm_write(hmidi->hdspm, HDSPM_controlRegister,
1704 hmidi->hdspm->control_register);
Adrian Knothc0da0012011-06-12 17:26:17 +02001705 spin_unlock_irqrestore(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001706
Takashi Iwai763f3562005-06-03 11:25:34 +02001707 return snd_hdspm_midi_output_write (hmidi);
1708}
1709
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001710static void
1711snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001712{
Takashi Iwai98274f02005-11-17 14:52:34 +01001713 struct hdspm *hdspm;
1714 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001715 unsigned long flags;
Takashi Iwai763f3562005-06-03 11:25:34 +02001716
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001717 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001718 hdspm = hmidi->hdspm;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001719
Takashi Iwai763f3562005-06-03 11:25:34 +02001720 spin_lock_irqsave (&hdspm->lock, flags);
1721 if (up) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001722 if (!(hdspm->control_register & hmidi->ie)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001723 snd_hdspm_flush_midi_input (hdspm, hmidi->id);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001724 hdspm->control_register |= hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001725 }
1726 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001727 hdspm->control_register &= ~hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001728 }
1729
1730 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1731 spin_unlock_irqrestore (&hdspm->lock, flags);
1732}
1733
1734static void snd_hdspm_midi_output_timer(unsigned long data)
1735{
Takashi Iwai98274f02005-11-17 14:52:34 +01001736 struct hdspm_midi *hmidi = (struct hdspm_midi *) data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001737 unsigned long flags;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001738
Takashi Iwai763f3562005-06-03 11:25:34 +02001739 snd_hdspm_midi_output_write(hmidi);
1740 spin_lock_irqsave (&hmidi->lock, flags);
1741
1742 /* this does not bump hmidi->istimer, because the
1743 kernel automatically removed the timer when it
1744 expired, and we are now adding it back, thus
Adrian Knoth0dca1792011-01-26 19:32:14 +01001745 leaving istimer wherever it was set before.
Takashi Iwai763f3562005-06-03 11:25:34 +02001746 */
1747
1748 if (hmidi->istimer) {
1749 hmidi->timer.expires = 1 + jiffies;
1750 add_timer(&hmidi->timer);
1751 }
1752
1753 spin_unlock_irqrestore (&hmidi->lock, flags);
1754}
1755
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001756static void
1757snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001758{
Takashi Iwai98274f02005-11-17 14:52:34 +01001759 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001760 unsigned long flags;
1761
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001762 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001763 spin_lock_irqsave (&hmidi->lock, flags);
1764 if (up) {
1765 if (!hmidi->istimer) {
1766 init_timer(&hmidi->timer);
1767 hmidi->timer.function = snd_hdspm_midi_output_timer;
1768 hmidi->timer.data = (unsigned long) hmidi;
1769 hmidi->timer.expires = 1 + jiffies;
1770 add_timer(&hmidi->timer);
1771 hmidi->istimer++;
1772 }
1773 } else {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001774 if (hmidi->istimer && --hmidi->istimer <= 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02001775 del_timer (&hmidi->timer);
Takashi Iwai763f3562005-06-03 11:25:34 +02001776 }
1777 spin_unlock_irqrestore (&hmidi->lock, flags);
1778 if (up)
1779 snd_hdspm_midi_output_write(hmidi);
1780}
1781
Takashi Iwai98274f02005-11-17 14:52:34 +01001782static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001783{
Takashi Iwai98274f02005-11-17 14:52:34 +01001784 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001785
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001786 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001787 spin_lock_irq (&hmidi->lock);
1788 snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
1789 hmidi->input = substream;
1790 spin_unlock_irq (&hmidi->lock);
1791
1792 return 0;
1793}
1794
Takashi Iwai98274f02005-11-17 14:52:34 +01001795static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001796{
Takashi Iwai98274f02005-11-17 14:52:34 +01001797 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001798
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001799 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001800 spin_lock_irq (&hmidi->lock);
1801 hmidi->output = substream;
1802 spin_unlock_irq (&hmidi->lock);
1803
1804 return 0;
1805}
1806
Takashi Iwai98274f02005-11-17 14:52:34 +01001807static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001808{
Takashi Iwai98274f02005-11-17 14:52:34 +01001809 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001810
1811 snd_hdspm_midi_input_trigger (substream, 0);
1812
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001813 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001814 spin_lock_irq (&hmidi->lock);
1815 hmidi->input = NULL;
1816 spin_unlock_irq (&hmidi->lock);
1817
1818 return 0;
1819}
1820
Takashi Iwai98274f02005-11-17 14:52:34 +01001821static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001822{
Takashi Iwai98274f02005-11-17 14:52:34 +01001823 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001824
1825 snd_hdspm_midi_output_trigger (substream, 0);
1826
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001827 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001828 spin_lock_irq (&hmidi->lock);
1829 hmidi->output = NULL;
1830 spin_unlock_irq (&hmidi->lock);
1831
1832 return 0;
1833}
1834
Takashi Iwai98274f02005-11-17 14:52:34 +01001835static struct snd_rawmidi_ops snd_hdspm_midi_output =
Takashi Iwai763f3562005-06-03 11:25:34 +02001836{
1837 .open = snd_hdspm_midi_output_open,
1838 .close = snd_hdspm_midi_output_close,
1839 .trigger = snd_hdspm_midi_output_trigger,
1840};
1841
Takashi Iwai98274f02005-11-17 14:52:34 +01001842static struct snd_rawmidi_ops snd_hdspm_midi_input =
Takashi Iwai763f3562005-06-03 11:25:34 +02001843{
1844 .open = snd_hdspm_midi_input_open,
1845 .close = snd_hdspm_midi_input_close,
1846 .trigger = snd_hdspm_midi_input_trigger,
1847};
1848
Bill Pembertone23e7a12012-12-06 12:35:10 -05001849static int snd_hdspm_create_midi(struct snd_card *card,
1850 struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001851{
1852 int err;
1853 char buf[32];
1854
1855 hdspm->midi[id].id = id;
Takashi Iwai763f3562005-06-03 11:25:34 +02001856 hdspm->midi[id].hdspm = hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +02001857 spin_lock_init (&hdspm->midi[id].lock);
1858
Adrian Knoth0dca1792011-01-26 19:32:14 +01001859 if (0 == id) {
1860 if (MADIface == hdspm->io_type) {
1861 /* MIDI-over-MADI on HDSPe MADIface */
1862 hdspm->midi[0].dataIn = HDSPM_midiDataIn2;
1863 hdspm->midi[0].statusIn = HDSPM_midiStatusIn2;
1864 hdspm->midi[0].dataOut = HDSPM_midiDataOut2;
1865 hdspm->midi[0].statusOut = HDSPM_midiStatusOut2;
1866 hdspm->midi[0].ie = HDSPM_Midi2InterruptEnable;
1867 hdspm->midi[0].irq = HDSPM_midi2IRQPending;
1868 } else {
1869 hdspm->midi[0].dataIn = HDSPM_midiDataIn0;
1870 hdspm->midi[0].statusIn = HDSPM_midiStatusIn0;
1871 hdspm->midi[0].dataOut = HDSPM_midiDataOut0;
1872 hdspm->midi[0].statusOut = HDSPM_midiStatusOut0;
1873 hdspm->midi[0].ie = HDSPM_Midi0InterruptEnable;
1874 hdspm->midi[0].irq = HDSPM_midi0IRQPending;
1875 }
1876 } else if (1 == id) {
1877 hdspm->midi[1].dataIn = HDSPM_midiDataIn1;
1878 hdspm->midi[1].statusIn = HDSPM_midiStatusIn1;
1879 hdspm->midi[1].dataOut = HDSPM_midiDataOut1;
1880 hdspm->midi[1].statusOut = HDSPM_midiStatusOut1;
1881 hdspm->midi[1].ie = HDSPM_Midi1InterruptEnable;
1882 hdspm->midi[1].irq = HDSPM_midi1IRQPending;
1883 } else if ((2 == id) && (MADI == hdspm->io_type)) {
1884 /* MIDI-over-MADI on HDSPe MADI */
1885 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1886 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1887 hdspm->midi[2].dataOut = HDSPM_midiDataOut2;
1888 hdspm->midi[2].statusOut = HDSPM_midiStatusOut2;
1889 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1890 hdspm->midi[2].irq = HDSPM_midi2IRQPending;
1891 } else if (2 == id) {
1892 /* TCO MTC, read only */
1893 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1894 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1895 hdspm->midi[2].dataOut = -1;
1896 hdspm->midi[2].statusOut = -1;
1897 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1898 hdspm->midi[2].irq = HDSPM_midi2IRQPendingAES;
1899 } else if (3 == id) {
1900 /* TCO MTC on HDSPe MADI */
1901 hdspm->midi[3].dataIn = HDSPM_midiDataIn3;
1902 hdspm->midi[3].statusIn = HDSPM_midiStatusIn3;
1903 hdspm->midi[3].dataOut = -1;
1904 hdspm->midi[3].statusOut = -1;
1905 hdspm->midi[3].ie = HDSPM_Midi3InterruptEnable;
1906 hdspm->midi[3].irq = HDSPM_midi3IRQPending;
1907 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001908
Adrian Knoth0dca1792011-01-26 19:32:14 +01001909 if ((id < 2) || ((2 == id) && ((MADI == hdspm->io_type) ||
1910 (MADIface == hdspm->io_type)))) {
1911 if ((id == 0) && (MADIface == hdspm->io_type)) {
1912 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1913 } else if ((id == 2) && (MADI == hdspm->io_type)) {
1914 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1915 } else {
1916 sprintf(buf, "%s MIDI %d", card->shortname, id+1);
1917 }
1918 err = snd_rawmidi_new(card, buf, id, 1, 1,
1919 &hdspm->midi[id].rmidi);
1920 if (err < 0)
1921 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02001922
Adrian Knoth0dca1792011-01-26 19:32:14 +01001923 sprintf(hdspm->midi[id].rmidi->name, "%s MIDI %d",
1924 card->id, id+1);
1925 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
Takashi Iwai763f3562005-06-03 11:25:34 +02001926
Adrian Knoth0dca1792011-01-26 19:32:14 +01001927 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1928 SNDRV_RAWMIDI_STREAM_OUTPUT,
1929 &snd_hdspm_midi_output);
1930 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1931 SNDRV_RAWMIDI_STREAM_INPUT,
1932 &snd_hdspm_midi_input);
1933
1934 hdspm->midi[id].rmidi->info_flags |=
1935 SNDRV_RAWMIDI_INFO_OUTPUT |
1936 SNDRV_RAWMIDI_INFO_INPUT |
1937 SNDRV_RAWMIDI_INFO_DUPLEX;
1938 } else {
1939 /* TCO MTC, read only */
1940 sprintf(buf, "%s MTC %d", card->shortname, id+1);
1941 err = snd_rawmidi_new(card, buf, id, 1, 1,
1942 &hdspm->midi[id].rmidi);
1943 if (err < 0)
1944 return err;
1945
1946 sprintf(hdspm->midi[id].rmidi->name,
1947 "%s MTC %d", card->id, id+1);
1948 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
1949
1950 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1951 SNDRV_RAWMIDI_STREAM_INPUT,
1952 &snd_hdspm_midi_input);
1953
1954 hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
1955 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001956
1957 return 0;
1958}
1959
1960
1961static void hdspm_midi_tasklet(unsigned long arg)
1962{
Takashi Iwai98274f02005-11-17 14:52:34 +01001963 struct hdspm *hdspm = (struct hdspm *)arg;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001964 int i = 0;
1965
1966 while (i < hdspm->midiPorts) {
1967 if (hdspm->midi[i].pending)
1968 snd_hdspm_midi_input_read(&hdspm->midi[i]);
1969
1970 i++;
1971 }
1972}
Takashi Iwai763f3562005-06-03 11:25:34 +02001973
1974
1975/*-----------------------------------------------------------------------------
1976 Status Interface
1977 ----------------------------------------------------------------------------*/
1978
1979/* get the system sample rate which is set */
1980
Adrian Knoth0dca1792011-01-26 19:32:14 +01001981
1982/**
1983 * Calculate the real sample rate from the
1984 * current DDS value.
1985 **/
1986static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
1987{
1988 unsigned int period, rate;
1989
1990 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
1991 rate = hdspm_calc_dds_value(hdspm, period);
1992
Adrian Knotha97bda72012-05-30 14:23:18 +02001993 if (rate > 207000) {
Adrian Knoth21a164d2012-10-19 17:42:23 +02001994 /* Unreasonable high sample rate as seen on PCI MADI cards. */
1995 if (0 == hdspm_system_clock_mode(hdspm)) {
1996 /* master mode, return internal sample rate */
1997 rate = hdspm->system_sample_rate;
1998 } else {
1999 /* slave mode, return external sample rate */
2000 rate = hdspm_external_sample_rate(hdspm);
2001 }
Adrian Knotha97bda72012-05-30 14:23:18 +02002002 }
2003
Adrian Knoth0dca1792011-01-26 19:32:14 +01002004 return rate;
2005}
2006
2007
Takashi Iwai763f3562005-06-03 11:25:34 +02002008#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02002009{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2010 .name = xname, \
2011 .index = xindex, \
2012 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2013 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2014 .info = snd_hdspm_info_system_sample_rate, \
2015 .put = snd_hdspm_put_system_sample_rate, \
2016 .get = snd_hdspm_get_system_sample_rate \
Takashi Iwai763f3562005-06-03 11:25:34 +02002017}
2018
Takashi Iwai98274f02005-11-17 14:52:34 +01002019static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
2020 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002021{
2022 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2023 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002024 uinfo->value.integer.min = 27000;
2025 uinfo->value.integer.max = 207000;
2026 uinfo->value.integer.step = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002027 return 0;
2028}
2029
Adrian Knoth0dca1792011-01-26 19:32:14 +01002030
Takashi Iwai98274f02005-11-17 14:52:34 +01002031static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
2032 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002033 ucontrol)
2034{
Takashi Iwai98274f02005-11-17 14:52:34 +01002035 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002036
Adrian Knoth0dca1792011-01-26 19:32:14 +01002037 ucontrol->value.integer.value[0] = hdspm_get_system_sample_rate(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002038 return 0;
2039}
2040
Adrian Knoth41285a92012-10-19 17:42:22 +02002041static int snd_hdspm_put_system_sample_rate(struct snd_kcontrol *kcontrol,
2042 struct snd_ctl_elem_value *
2043 ucontrol)
2044{
2045 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2046
2047 hdspm_set_dds_value(hdspm, ucontrol->value.enumerated.item[0]);
2048 return 0;
2049}
2050
Adrian Knoth0dca1792011-01-26 19:32:14 +01002051
2052/**
2053 * Returns the WordClock sample rate class for the given card.
2054 **/
2055static int hdspm_get_wc_sample_rate(struct hdspm *hdspm)
2056{
2057 int status;
2058
2059 switch (hdspm->io_type) {
2060 case RayDAT:
2061 case AIO:
2062 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2063 return (status >> 16) & 0xF;
2064 break;
2065 default:
2066 break;
2067 }
2068
2069
2070 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002071}
2072
Adrian Knoth0dca1792011-01-26 19:32:14 +01002073
2074/**
2075 * Returns the TCO sample rate class for the given card.
2076 **/
2077static int hdspm_get_tco_sample_rate(struct hdspm *hdspm)
2078{
2079 int status;
2080
2081 if (hdspm->tco) {
2082 switch (hdspm->io_type) {
2083 case RayDAT:
2084 case AIO:
2085 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2086 return (status >> 20) & 0xF;
2087 break;
2088 default:
2089 break;
2090 }
2091 }
2092
2093 return 0;
2094}
2095
2096
2097/**
2098 * Returns the SYNC_IN sample rate class for the given card.
2099 **/
2100static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm)
2101{
2102 int status;
2103
2104 if (hdspm->tco) {
2105 switch (hdspm->io_type) {
2106 case RayDAT:
2107 case AIO:
2108 status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2109 return (status >> 12) & 0xF;
2110 break;
2111 default:
2112 break;
2113 }
2114 }
2115
2116 return 0;
2117}
2118
2119
2120/**
2121 * Returns the sample rate class for input source <idx> for
2122 * 'new style' cards like the AIO and RayDAT.
2123 **/
2124static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
2125{
2126 int status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2127
2128 return (status >> (idx*4)) & 0xF;
2129}
2130
2131
2132
2133#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
2134{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2135 .name = xname, \
2136 .private_value = xindex, \
2137 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2138 .info = snd_hdspm_info_autosync_sample_rate, \
2139 .get = snd_hdspm_get_autosync_sample_rate \
2140}
2141
2142
Takashi Iwai98274f02005-11-17 14:52:34 +01002143static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2144 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002145{
Takashi Iwai763f3562005-06-03 11:25:34 +02002146 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2147 uinfo->count = 1;
2148 uinfo->value.enumerated.items = 10;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002149
Takashi Iwai763f3562005-06-03 11:25:34 +02002150 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
Adrian Knoth0dca1792011-01-26 19:32:14 +01002151 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002152 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002153 texts_freq[uinfo->value.enumerated.item]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002154 return 0;
2155}
2156
Adrian Knoth0dca1792011-01-26 19:32:14 +01002157
Takashi Iwai98274f02005-11-17 14:52:34 +01002158static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2159 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002160 ucontrol)
2161{
Takashi Iwai98274f02005-11-17 14:52:34 +01002162 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002163
Adrian Knoth0dca1792011-01-26 19:32:14 +01002164 switch (hdspm->io_type) {
2165 case RayDAT:
2166 switch (kcontrol->private_value) {
2167 case 0:
2168 ucontrol->value.enumerated.item[0] =
2169 hdspm_get_wc_sample_rate(hdspm);
2170 break;
2171 case 7:
2172 ucontrol->value.enumerated.item[0] =
2173 hdspm_get_tco_sample_rate(hdspm);
2174 break;
2175 case 8:
2176 ucontrol->value.enumerated.item[0] =
2177 hdspm_get_sync_in_sample_rate(hdspm);
2178 break;
2179 default:
2180 ucontrol->value.enumerated.item[0] =
2181 hdspm_get_s1_sample_rate(hdspm,
2182 kcontrol->private_value-1);
2183 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002184 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002185
Adrian Knoth0dca1792011-01-26 19:32:14 +01002186 case AIO:
2187 switch (kcontrol->private_value) {
2188 case 0: /* WC */
2189 ucontrol->value.enumerated.item[0] =
2190 hdspm_get_wc_sample_rate(hdspm);
2191 break;
2192 case 4: /* TCO */
2193 ucontrol->value.enumerated.item[0] =
2194 hdspm_get_tco_sample_rate(hdspm);
2195 break;
2196 case 5: /* SYNC_IN */
2197 ucontrol->value.enumerated.item[0] =
2198 hdspm_get_sync_in_sample_rate(hdspm);
2199 break;
2200 default:
2201 ucontrol->value.enumerated.item[0] =
2202 hdspm_get_s1_sample_rate(hdspm,
2203 ucontrol->id.index-1);
2204 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002205 break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002206
2207 case AES32:
2208
2209 switch (kcontrol->private_value) {
2210 case 0: /* WC */
2211 ucontrol->value.enumerated.item[0] =
2212 hdspm_get_wc_sample_rate(hdspm);
2213 break;
2214 case 9: /* TCO */
2215 ucontrol->value.enumerated.item[0] =
2216 hdspm_get_tco_sample_rate(hdspm);
2217 break;
2218 case 10: /* SYNC_IN */
2219 ucontrol->value.enumerated.item[0] =
2220 hdspm_get_sync_in_sample_rate(hdspm);
2221 break;
2222 default: /* AES1 to AES8 */
2223 ucontrol->value.enumerated.item[0] =
2224 hdspm_get_s1_sample_rate(hdspm,
2225 kcontrol->private_value-1);
2226 break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002227 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002228 break;
Adrian Knothb8812c52012-10-19 17:42:26 +02002229
2230 case MADI:
2231 case MADIface:
2232 {
2233 int rate = hdspm_external_sample_rate(hdspm);
2234 int i, selected_rate = 0;
2235 for (i = 1; i < 10; i++)
2236 if (HDSPM_bit2freq(i) == rate) {
2237 selected_rate = i;
2238 break;
2239 }
2240 ucontrol->value.enumerated.item[0] = selected_rate;
2241 }
2242 break;
2243
Takashi Iwai763f3562005-06-03 11:25:34 +02002244 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002245 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002246 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002247
Takashi Iwai763f3562005-06-03 11:25:34 +02002248 return 0;
2249}
2250
Adrian Knoth0dca1792011-01-26 19:32:14 +01002251
Takashi Iwai763f3562005-06-03 11:25:34 +02002252#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002253{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2254 .name = xname, \
2255 .index = xindex, \
2256 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2257 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2258 .info = snd_hdspm_info_system_clock_mode, \
2259 .get = snd_hdspm_get_system_clock_mode, \
2260 .put = snd_hdspm_put_system_clock_mode, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002261}
2262
2263
Adrian Knoth0dca1792011-01-26 19:32:14 +01002264/**
2265 * Returns the system clock mode for the given card.
2266 * @returns 0 - master, 1 - slave
2267 **/
2268static int hdspm_system_clock_mode(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002269{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002270 switch (hdspm->io_type) {
2271 case AIO:
2272 case RayDAT:
2273 if (hdspm->settings_register & HDSPM_c0Master)
2274 return 0;
2275 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002276
Adrian Knoth0dca1792011-01-26 19:32:14 +01002277 default:
2278 if (hdspm->control_register & HDSPM_ClockModeMaster)
2279 return 0;
2280 }
2281
Takashi Iwai763f3562005-06-03 11:25:34 +02002282 return 1;
2283}
2284
Adrian Knoth0dca1792011-01-26 19:32:14 +01002285
2286/**
2287 * Sets the system clock mode.
2288 * @param mode 0 - master, 1 - slave
2289 **/
2290static void hdspm_set_system_clock_mode(struct hdspm *hdspm, int mode)
2291{
2292 switch (hdspm->io_type) {
2293 case AIO:
2294 case RayDAT:
2295 if (0 == mode)
2296 hdspm->settings_register |= HDSPM_c0Master;
2297 else
2298 hdspm->settings_register &= ~HDSPM_c0Master;
2299
2300 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2301 break;
2302
2303 default:
2304 if (0 == mode)
2305 hdspm->control_register |= HDSPM_ClockModeMaster;
2306 else
2307 hdspm->control_register &= ~HDSPM_ClockModeMaster;
2308
2309 hdspm_write(hdspm, HDSPM_controlRegister,
2310 hdspm->control_register);
2311 }
2312}
2313
2314
Takashi Iwai98274f02005-11-17 14:52:34 +01002315static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
2316 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002317{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002318 static char *texts[] = { "Master", "AutoSync" };
Takashi Iwai763f3562005-06-03 11:25:34 +02002319
2320 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2321 uinfo->count = 1;
2322 uinfo->value.enumerated.items = 2;
2323 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2324 uinfo->value.enumerated.item =
2325 uinfo->value.enumerated.items - 1;
2326 strcpy(uinfo->value.enumerated.name,
2327 texts[uinfo->value.enumerated.item]);
2328 return 0;
2329}
2330
Takashi Iwai98274f02005-11-17 14:52:34 +01002331static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
2332 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002333{
Takashi Iwai98274f02005-11-17 14:52:34 +01002334 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002335
Adrian Knoth0dca1792011-01-26 19:32:14 +01002336 ucontrol->value.enumerated.item[0] = hdspm_system_clock_mode(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002337 return 0;
2338}
2339
Adrian Knoth0dca1792011-01-26 19:32:14 +01002340static int snd_hdspm_put_system_clock_mode(struct snd_kcontrol *kcontrol,
2341 struct snd_ctl_elem_value *ucontrol)
2342{
2343 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2344 int val;
2345
2346 if (!snd_hdspm_use_is_exclusive(hdspm))
2347 return -EBUSY;
2348
2349 val = ucontrol->value.enumerated.item[0];
2350 if (val < 0)
2351 val = 0;
2352 else if (val > 1)
2353 val = 1;
2354
2355 hdspm_set_system_clock_mode(hdspm, val);
2356
2357 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002358}
2359
Adrian Knoth0dca1792011-01-26 19:32:14 +01002360
2361#define HDSPM_INTERNAL_CLOCK(xname, xindex) \
2362{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2363 .name = xname, \
2364 .index = xindex, \
2365 .info = snd_hdspm_info_clock_source, \
2366 .get = snd_hdspm_get_clock_source, \
2367 .put = snd_hdspm_put_clock_source \
2368}
2369
2370
Takashi Iwai98274f02005-11-17 14:52:34 +01002371static int hdspm_clock_source(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002372{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002373 switch (hdspm->system_sample_rate) {
2374 case 32000: return 0;
2375 case 44100: return 1;
2376 case 48000: return 2;
2377 case 64000: return 3;
2378 case 88200: return 4;
2379 case 96000: return 5;
2380 case 128000: return 6;
2381 case 176400: return 7;
2382 case 192000: return 8;
Takashi Iwai763f3562005-06-03 11:25:34 +02002383 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002384
2385 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002386}
2387
Takashi Iwai98274f02005-11-17 14:52:34 +01002388static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
Takashi Iwai763f3562005-06-03 11:25:34 +02002389{
2390 int rate;
2391 switch (mode) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002392 case 0:
2393 rate = 32000; break;
2394 case 1:
2395 rate = 44100; break;
2396 case 2:
2397 rate = 48000; break;
2398 case 3:
2399 rate = 64000; break;
2400 case 4:
2401 rate = 88200; break;
2402 case 5:
2403 rate = 96000; break;
2404 case 6:
2405 rate = 128000; break;
2406 case 7:
2407 rate = 176400; break;
2408 case 8:
2409 rate = 192000; break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002410 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002411 rate = 48000;
Takashi Iwai763f3562005-06-03 11:25:34 +02002412 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002413 hdspm_set_rate(hdspm, rate, 1);
2414 return 0;
2415}
2416
Takashi Iwai98274f02005-11-17 14:52:34 +01002417static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
2418 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002419{
Takashi Iwai763f3562005-06-03 11:25:34 +02002420 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2421 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002422 uinfo->value.enumerated.items = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002423
2424 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2425 uinfo->value.enumerated.item =
2426 uinfo->value.enumerated.items - 1;
2427
2428 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002429 texts_freq[uinfo->value.enumerated.item+1]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002430
2431 return 0;
2432}
2433
Takashi Iwai98274f02005-11-17 14:52:34 +01002434static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
2435 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002436{
Takashi Iwai98274f02005-11-17 14:52:34 +01002437 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002438
2439 ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
2440 return 0;
2441}
2442
Takashi Iwai98274f02005-11-17 14:52:34 +01002443static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
2444 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002445{
Takashi Iwai98274f02005-11-17 14:52:34 +01002446 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002447 int change;
2448 int val;
2449
2450 if (!snd_hdspm_use_is_exclusive(hdspm))
2451 return -EBUSY;
2452 val = ucontrol->value.enumerated.item[0];
2453 if (val < 0)
2454 val = 0;
Remy Bruno65345992007-08-31 12:21:08 +02002455 if (val > 9)
2456 val = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002457 spin_lock_irq(&hdspm->lock);
2458 if (val != hdspm_clock_source(hdspm))
2459 change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
2460 else
2461 change = 0;
2462 spin_unlock_irq(&hdspm->lock);
2463 return change;
2464}
2465
Adrian Knoth0dca1792011-01-26 19:32:14 +01002466
Takashi Iwai763f3562005-06-03 11:25:34 +02002467#define HDSPM_PREF_SYNC_REF(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02002468{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002469 .name = xname, \
2470 .index = xindex, \
2471 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2472 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2473 .info = snd_hdspm_info_pref_sync_ref, \
2474 .get = snd_hdspm_get_pref_sync_ref, \
2475 .put = snd_hdspm_put_pref_sync_ref \
Takashi Iwai763f3562005-06-03 11:25:34 +02002476}
2477
Adrian Knoth0dca1792011-01-26 19:32:14 +01002478
2479/**
2480 * Returns the current preferred sync reference setting.
2481 * The semantics of the return value are depending on the
2482 * card, please see the comments for clarification.
2483 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002484static int hdspm_pref_sync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002485{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002486 switch (hdspm->io_type) {
2487 case AES32:
Remy Bruno3cee5a62006-10-16 12:46:32 +02002488 switch (hdspm->control_register & HDSPM_SyncRefMask) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002489 case 0: return 0; /* WC */
2490 case HDSPM_SyncRef0: return 1; /* AES 1 */
2491 case HDSPM_SyncRef1: return 2; /* AES 2 */
2492 case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; /* AES 3 */
2493 case HDSPM_SyncRef2: return 4; /* AES 4 */
2494 case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; /* AES 5 */
2495 case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; /* AES 6 */
2496 case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0:
2497 return 7; /* AES 7 */
2498 case HDSPM_SyncRef3: return 8; /* AES 8 */
2499 case HDSPM_SyncRef3+HDSPM_SyncRef0: return 9; /* TCO */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002500 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002501 break;
2502
2503 case MADI:
2504 case MADIface:
2505 if (hdspm->tco) {
2506 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2507 case 0: return 0; /* WC */
2508 case HDSPM_SyncRef0: return 1; /* MADI */
2509 case HDSPM_SyncRef1: return 2; /* TCO */
2510 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2511 return 3; /* SYNC_IN */
2512 }
2513 } else {
2514 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2515 case 0: return 0; /* WC */
2516 case HDSPM_SyncRef0: return 1; /* MADI */
2517 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2518 return 2; /* SYNC_IN */
2519 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02002520 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002521 break;
2522
2523 case RayDAT:
2524 if (hdspm->tco) {
2525 switch ((hdspm->settings_register &
2526 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2527 case 0: return 0; /* WC */
2528 case 3: return 1; /* ADAT 1 */
2529 case 4: return 2; /* ADAT 2 */
2530 case 5: return 3; /* ADAT 3 */
2531 case 6: return 4; /* ADAT 4 */
2532 case 1: return 5; /* AES */
2533 case 2: return 6; /* SPDIF */
2534 case 9: return 7; /* TCO */
2535 case 10: return 8; /* SYNC_IN */
2536 }
2537 } else {
2538 switch ((hdspm->settings_register &
2539 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2540 case 0: return 0; /* WC */
2541 case 3: return 1; /* ADAT 1 */
2542 case 4: return 2; /* ADAT 2 */
2543 case 5: return 3; /* ADAT 3 */
2544 case 6: return 4; /* ADAT 4 */
2545 case 1: return 5; /* AES */
2546 case 2: return 6; /* SPDIF */
2547 case 10: return 7; /* SYNC_IN */
2548 }
2549 }
2550
2551 break;
2552
2553 case AIO:
2554 if (hdspm->tco) {
2555 switch ((hdspm->settings_register &
2556 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2557 case 0: return 0; /* WC */
2558 case 3: return 1; /* ADAT */
2559 case 1: return 2; /* AES */
2560 case 2: return 3; /* SPDIF */
2561 case 9: return 4; /* TCO */
2562 case 10: return 5; /* SYNC_IN */
2563 }
2564 } else {
2565 switch ((hdspm->settings_register &
2566 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2567 case 0: return 0; /* WC */
2568 case 3: return 1; /* ADAT */
2569 case 1: return 2; /* AES */
2570 case 2: return 3; /* SPDIF */
2571 case 10: return 4; /* SYNC_IN */
2572 }
2573 }
2574
2575 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002576 }
2577
Adrian Knoth0dca1792011-01-26 19:32:14 +01002578 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002579}
2580
Adrian Knoth0dca1792011-01-26 19:32:14 +01002581
2582/**
2583 * Set the preferred sync reference to <pref>. The semantics
2584 * of <pref> are depending on the card type, see the comments
2585 * for clarification.
2586 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002587static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
Takashi Iwai763f3562005-06-03 11:25:34 +02002588{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002589 int p = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002590
Adrian Knoth0dca1792011-01-26 19:32:14 +01002591 switch (hdspm->io_type) {
2592 case AES32:
2593 hdspm->control_register &= ~HDSPM_SyncRefMask;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002594 switch (pref) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002595 case 0: /* WC */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002596 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002597 case 1: /* AES 1 */
2598 hdspm->control_register |= HDSPM_SyncRef0;
2599 break;
2600 case 2: /* AES 2 */
2601 hdspm->control_register |= HDSPM_SyncRef1;
2602 break;
2603 case 3: /* AES 3 */
2604 hdspm->control_register |=
2605 HDSPM_SyncRef1+HDSPM_SyncRef0;
2606 break;
2607 case 4: /* AES 4 */
2608 hdspm->control_register |= HDSPM_SyncRef2;
2609 break;
2610 case 5: /* AES 5 */
2611 hdspm->control_register |=
2612 HDSPM_SyncRef2+HDSPM_SyncRef0;
2613 break;
2614 case 6: /* AES 6 */
2615 hdspm->control_register |=
2616 HDSPM_SyncRef2+HDSPM_SyncRef1;
2617 break;
2618 case 7: /* AES 7 */
2619 hdspm->control_register |=
2620 HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
2621 break;
2622 case 8: /* AES 8 */
2623 hdspm->control_register |= HDSPM_SyncRef3;
2624 break;
2625 case 9: /* TCO */
2626 hdspm->control_register |=
2627 HDSPM_SyncRef3+HDSPM_SyncRef0;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002628 break;
2629 default:
2630 return -1;
2631 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002632
2633 break;
2634
2635 case MADI:
2636 case MADIface:
2637 hdspm->control_register &= ~HDSPM_SyncRefMask;
2638 if (hdspm->tco) {
2639 switch (pref) {
2640 case 0: /* WC */
2641 break;
2642 case 1: /* MADI */
2643 hdspm->control_register |= HDSPM_SyncRef0;
2644 break;
2645 case 2: /* TCO */
2646 hdspm->control_register |= HDSPM_SyncRef1;
2647 break;
2648 case 3: /* SYNC_IN */
2649 hdspm->control_register |=
2650 HDSPM_SyncRef0+HDSPM_SyncRef1;
2651 break;
2652 default:
2653 return -1;
2654 }
2655 } else {
2656 switch (pref) {
2657 case 0: /* WC */
2658 break;
2659 case 1: /* MADI */
2660 hdspm->control_register |= HDSPM_SyncRef0;
2661 break;
2662 case 2: /* SYNC_IN */
2663 hdspm->control_register |=
2664 HDSPM_SyncRef0+HDSPM_SyncRef1;
2665 break;
2666 default:
2667 return -1;
2668 }
2669 }
2670
2671 break;
2672
2673 case RayDAT:
2674 if (hdspm->tco) {
2675 switch (pref) {
2676 case 0: p = 0; break; /* WC */
2677 case 1: p = 3; break; /* ADAT 1 */
2678 case 2: p = 4; break; /* ADAT 2 */
2679 case 3: p = 5; break; /* ADAT 3 */
2680 case 4: p = 6; break; /* ADAT 4 */
2681 case 5: p = 1; break; /* AES */
2682 case 6: p = 2; break; /* SPDIF */
2683 case 7: p = 9; break; /* TCO */
2684 case 8: p = 10; break; /* SYNC_IN */
2685 default: return -1;
2686 }
2687 } else {
2688 switch (pref) {
2689 case 0: p = 0; break; /* WC */
2690 case 1: p = 3; break; /* ADAT 1 */
2691 case 2: p = 4; break; /* ADAT 2 */
2692 case 3: p = 5; break; /* ADAT 3 */
2693 case 4: p = 6; break; /* ADAT 4 */
2694 case 5: p = 1; break; /* AES */
2695 case 6: p = 2; break; /* SPDIF */
2696 case 7: p = 10; break; /* SYNC_IN */
2697 default: return -1;
2698 }
2699 }
2700 break;
2701
2702 case AIO:
2703 if (hdspm->tco) {
2704 switch (pref) {
2705 case 0: p = 0; break; /* WC */
2706 case 1: p = 3; break; /* ADAT */
2707 case 2: p = 1; break; /* AES */
2708 case 3: p = 2; break; /* SPDIF */
2709 case 4: p = 9; break; /* TCO */
2710 case 5: p = 10; break; /* SYNC_IN */
2711 default: return -1;
2712 }
2713 } else {
2714 switch (pref) {
2715 case 0: p = 0; break; /* WC */
2716 case 1: p = 3; break; /* ADAT */
2717 case 2: p = 1; break; /* AES */
2718 case 3: p = 2; break; /* SPDIF */
2719 case 4: p = 10; break; /* SYNC_IN */
2720 default: return -1;
2721 }
2722 }
2723 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002724 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002725
2726 switch (hdspm->io_type) {
2727 case RayDAT:
2728 case AIO:
2729 hdspm->settings_register &= ~HDSPM_c0_SyncRefMask;
2730 hdspm->settings_register |= HDSPM_c0_SyncRef0 * p;
2731 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2732 break;
2733
2734 case MADI:
2735 case MADIface:
2736 case AES32:
2737 hdspm_write(hdspm, HDSPM_controlRegister,
2738 hdspm->control_register);
2739 }
2740
Takashi Iwai763f3562005-06-03 11:25:34 +02002741 return 0;
2742}
2743
Adrian Knoth0dca1792011-01-26 19:32:14 +01002744
Takashi Iwai98274f02005-11-17 14:52:34 +01002745static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
2746 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002747{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002748 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002749
Adrian Knoth0dca1792011-01-26 19:32:14 +01002750 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2751 uinfo->count = 1;
2752 uinfo->value.enumerated.items = hdspm->texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +02002753
Adrian Knoth0dca1792011-01-26 19:32:14 +01002754 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2755 uinfo->value.enumerated.item =
2756 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002757
Adrian Knoth0dca1792011-01-26 19:32:14 +01002758 strcpy(uinfo->value.enumerated.name,
2759 hdspm->texts_autosync[uinfo->value.enumerated.item]);
Remy Bruno3cee5a62006-10-16 12:46:32 +02002760
Takashi Iwai763f3562005-06-03 11:25:34 +02002761 return 0;
2762}
2763
Takashi Iwai98274f02005-11-17 14:52:34 +01002764static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
2765 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002766{
Takashi Iwai98274f02005-11-17 14:52:34 +01002767 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002768 int psf = hdspm_pref_sync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002769
Adrian Knoth0dca1792011-01-26 19:32:14 +01002770 if (psf >= 0) {
2771 ucontrol->value.enumerated.item[0] = psf;
2772 return 0;
2773 }
2774
2775 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002776}
2777
Takashi Iwai98274f02005-11-17 14:52:34 +01002778static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
2779 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002780{
Takashi Iwai98274f02005-11-17 14:52:34 +01002781 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002782 int val, change = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002783
2784 if (!snd_hdspm_use_is_exclusive(hdspm))
2785 return -EBUSY;
2786
Adrian Knoth0dca1792011-01-26 19:32:14 +01002787 val = ucontrol->value.enumerated.item[0];
2788
2789 if (val < 0)
2790 val = 0;
2791 else if (val >= hdspm->texts_autosync_items)
2792 val = hdspm->texts_autosync_items-1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002793
2794 spin_lock_irq(&hdspm->lock);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002795 if (val != hdspm_pref_sync_ref(hdspm))
2796 change = (0 == hdspm_set_pref_sync_ref(hdspm, val)) ? 1 : 0;
2797
Takashi Iwai763f3562005-06-03 11:25:34 +02002798 spin_unlock_irq(&hdspm->lock);
2799 return change;
2800}
2801
Adrian Knoth0dca1792011-01-26 19:32:14 +01002802
Takashi Iwai763f3562005-06-03 11:25:34 +02002803#define HDSPM_AUTOSYNC_REF(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02002804{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2805 .name = xname, \
2806 .index = xindex, \
2807 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2808 .info = snd_hdspm_info_autosync_ref, \
2809 .get = snd_hdspm_get_autosync_ref, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002810}
2811
Adrian Knoth0dca1792011-01-26 19:32:14 +01002812static int hdspm_autosync_ref(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002813{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002814 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002815 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002816 unsigned int syncref =
2817 (status >> HDSPM_AES32_syncref_bit) & 0xF;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002818 if (syncref == 0)
2819 return HDSPM_AES32_AUTOSYNC_FROM_WORD;
2820 if (syncref <= 8)
2821 return syncref;
2822 return HDSPM_AES32_AUTOSYNC_FROM_NONE;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002823 } else if (MADI == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002824 /* This looks at the autosync selected sync reference */
2825 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Takashi Iwai763f3562005-06-03 11:25:34 +02002826
Remy Bruno3cee5a62006-10-16 12:46:32 +02002827 switch (status2 & HDSPM_SelSyncRefMask) {
2828 case HDSPM_SelSyncRef_WORD:
2829 return HDSPM_AUTOSYNC_FROM_WORD;
2830 case HDSPM_SelSyncRef_MADI:
2831 return HDSPM_AUTOSYNC_FROM_MADI;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002832 case HDSPM_SelSyncRef_TCO:
2833 return HDSPM_AUTOSYNC_FROM_TCO;
2834 case HDSPM_SelSyncRef_SyncIn:
2835 return HDSPM_AUTOSYNC_FROM_SYNC_IN;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002836 case HDSPM_SelSyncRef_NVALID:
2837 return HDSPM_AUTOSYNC_FROM_NONE;
2838 default:
2839 return 0;
2840 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002841
Takashi Iwai763f3562005-06-03 11:25:34 +02002842 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002843 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002844}
2845
Adrian Knoth0dca1792011-01-26 19:32:14 +01002846
Takashi Iwai98274f02005-11-17 14:52:34 +01002847static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
2848 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002849{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002850 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002851
Adrian Knoth0dca1792011-01-26 19:32:14 +01002852 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002853 static char *texts[] = { "WordClock", "AES1", "AES2", "AES3",
2854 "AES4", "AES5", "AES6", "AES7", "AES8", "None"};
2855
2856 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2857 uinfo->count = 1;
2858 uinfo->value.enumerated.items = 10;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002859 if (uinfo->value.enumerated.item >=
2860 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002861 uinfo->value.enumerated.item =
2862 uinfo->value.enumerated.items - 1;
2863 strcpy(uinfo->value.enumerated.name,
2864 texts[uinfo->value.enumerated.item]);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002865 } else if (MADI == hdspm->io_type) {
2866 static char *texts[] = {"Word Clock", "MADI", "TCO",
2867 "Sync In", "None" };
Remy Bruno3cee5a62006-10-16 12:46:32 +02002868
2869 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2870 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002871 uinfo->value.enumerated.items = 5;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002872 if (uinfo->value.enumerated.item >=
Adrian Knoth0dca1792011-01-26 19:32:14 +01002873 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002874 uinfo->value.enumerated.item =
2875 uinfo->value.enumerated.items - 1;
2876 strcpy(uinfo->value.enumerated.name,
2877 texts[uinfo->value.enumerated.item]);
2878 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002879 return 0;
2880}
2881
Takashi Iwai98274f02005-11-17 14:52:34 +01002882static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
2883 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002884{
Takashi Iwai98274f02005-11-17 14:52:34 +01002885 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002886
Remy Bruno65345992007-08-31 12:21:08 +02002887 ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002888 return 0;
2889}
2890
Adrian Knothbf0ff872012-12-03 14:55:49 +01002891#define HDSPM_TOGGLE_SETTING(xname, xindex) \
2892{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2893 .name = xname, \
2894 .private_value = xindex, \
2895 .info = snd_hdspm_info_toggle_setting, \
2896 .get = snd_hdspm_get_toggle_setting, \
2897 .put = snd_hdspm_put_toggle_setting \
2898}
2899
2900static int hdspm_toggle_setting(struct hdspm *hdspm, u32 regmask)
2901{
2902 return (hdspm->control_register & regmask) ? 1 : 0;
2903}
2904
2905static int hdspm_set_toggle_setting(struct hdspm *hdspm, u32 regmask, int out)
2906{
2907 if (out)
2908 hdspm->control_register |= regmask;
2909 else
2910 hdspm->control_register &= ~regmask;
2911 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2912
2913 return 0;
2914}
2915
2916#define snd_hdspm_info_toggle_setting snd_ctl_boolean_mono_info
2917
2918static int snd_hdspm_get_toggle_setting(struct snd_kcontrol *kcontrol,
2919 struct snd_ctl_elem_value *ucontrol)
2920{
2921 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2922 u32 regmask = kcontrol->private_value;
2923
2924 spin_lock_irq(&hdspm->lock);
2925 ucontrol->value.integer.value[0] = hdspm_toggle_setting(hdspm, regmask);
2926 spin_unlock_irq(&hdspm->lock);
2927 return 0;
2928}
2929
2930static int snd_hdspm_put_toggle_setting(struct snd_kcontrol *kcontrol,
2931 struct snd_ctl_elem_value *ucontrol)
2932{
2933 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2934 u32 regmask = kcontrol->private_value;
2935 int change;
2936 unsigned int val;
2937
2938 if (!snd_hdspm_use_is_exclusive(hdspm))
2939 return -EBUSY;
2940 val = ucontrol->value.integer.value[0] & 1;
2941 spin_lock_irq(&hdspm->lock);
2942 change = (int) val != hdspm_toggle_setting(hdspm, regmask);
2943 hdspm_set_toggle_setting(hdspm, regmask, val);
2944 spin_unlock_irq(&hdspm->lock);
2945 return change;
2946}
2947
Takashi Iwai763f3562005-06-03 11:25:34 +02002948#define HDSPM_INPUT_SELECT(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02002949{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2950 .name = xname, \
2951 .index = xindex, \
2952 .info = snd_hdspm_info_input_select, \
2953 .get = snd_hdspm_get_input_select, \
2954 .put = snd_hdspm_put_input_select \
Takashi Iwai763f3562005-06-03 11:25:34 +02002955}
2956
Takashi Iwai98274f02005-11-17 14:52:34 +01002957static int hdspm_input_select(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002958{
2959 return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
2960}
2961
Takashi Iwai98274f02005-11-17 14:52:34 +01002962static int hdspm_set_input_select(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002963{
2964 if (out)
2965 hdspm->control_register |= HDSPM_InputSelect0;
2966 else
2967 hdspm->control_register &= ~HDSPM_InputSelect0;
2968 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2969
2970 return 0;
2971}
2972
Takashi Iwai98274f02005-11-17 14:52:34 +01002973static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
2974 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002975{
2976 static char *texts[] = { "optical", "coaxial" };
2977
2978 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2979 uinfo->count = 1;
2980 uinfo->value.enumerated.items = 2;
2981
2982 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2983 uinfo->value.enumerated.item =
2984 uinfo->value.enumerated.items - 1;
2985 strcpy(uinfo->value.enumerated.name,
2986 texts[uinfo->value.enumerated.item]);
2987
2988 return 0;
2989}
2990
Takashi Iwai98274f02005-11-17 14:52:34 +01002991static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
2992 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002993{
Takashi Iwai98274f02005-11-17 14:52:34 +01002994 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002995
2996 spin_lock_irq(&hdspm->lock);
2997 ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
2998 spin_unlock_irq(&hdspm->lock);
2999 return 0;
3000}
3001
Takashi Iwai98274f02005-11-17 14:52:34 +01003002static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
3003 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003004{
Takashi Iwai98274f02005-11-17 14:52:34 +01003005 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003006 int change;
3007 unsigned int val;
3008
3009 if (!snd_hdspm_use_is_exclusive(hdspm))
3010 return -EBUSY;
3011 val = ucontrol->value.integer.value[0] & 1;
3012 spin_lock_irq(&hdspm->lock);
3013 change = (int) val != hdspm_input_select(hdspm);
3014 hdspm_set_input_select(hdspm, val);
3015 spin_unlock_irq(&hdspm->lock);
3016 return change;
3017}
3018
Adrian Knoth0dca1792011-01-26 19:32:14 +01003019
Remy Bruno3cee5a62006-10-16 12:46:32 +02003020#define HDSPM_DS_WIRE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003021{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3022 .name = xname, \
3023 .index = xindex, \
3024 .info = snd_hdspm_info_ds_wire, \
3025 .get = snd_hdspm_get_ds_wire, \
3026 .put = snd_hdspm_put_ds_wire \
Remy Bruno3cee5a62006-10-16 12:46:32 +02003027}
3028
3029static int hdspm_ds_wire(struct hdspm * hdspm)
3030{
3031 return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
3032}
3033
3034static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
3035{
3036 if (ds)
3037 hdspm->control_register |= HDSPM_DS_DoubleWire;
3038 else
3039 hdspm->control_register &= ~HDSPM_DS_DoubleWire;
3040 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3041
3042 return 0;
3043}
3044
3045static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
3046 struct snd_ctl_elem_info *uinfo)
3047{
3048 static char *texts[] = { "Single", "Double" };
3049
3050 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3051 uinfo->count = 1;
3052 uinfo->value.enumerated.items = 2;
3053
3054 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3055 uinfo->value.enumerated.item =
3056 uinfo->value.enumerated.items - 1;
3057 strcpy(uinfo->value.enumerated.name,
3058 texts[uinfo->value.enumerated.item]);
3059
3060 return 0;
3061}
3062
3063static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
3064 struct snd_ctl_elem_value *ucontrol)
3065{
3066 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3067
3068 spin_lock_irq(&hdspm->lock);
3069 ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
3070 spin_unlock_irq(&hdspm->lock);
3071 return 0;
3072}
3073
3074static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
3075 struct snd_ctl_elem_value *ucontrol)
3076{
3077 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3078 int change;
3079 unsigned int val;
3080
3081 if (!snd_hdspm_use_is_exclusive(hdspm))
3082 return -EBUSY;
3083 val = ucontrol->value.integer.value[0] & 1;
3084 spin_lock_irq(&hdspm->lock);
3085 change = (int) val != hdspm_ds_wire(hdspm);
3086 hdspm_set_ds_wire(hdspm, val);
3087 spin_unlock_irq(&hdspm->lock);
3088 return change;
3089}
3090
Adrian Knoth0dca1792011-01-26 19:32:14 +01003091
Remy Bruno3cee5a62006-10-16 12:46:32 +02003092#define HDSPM_QS_WIRE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003093{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3094 .name = xname, \
3095 .index = xindex, \
3096 .info = snd_hdspm_info_qs_wire, \
3097 .get = snd_hdspm_get_qs_wire, \
3098 .put = snd_hdspm_put_qs_wire \
Remy Bruno3cee5a62006-10-16 12:46:32 +02003099}
3100
3101static int hdspm_qs_wire(struct hdspm * hdspm)
3102{
3103 if (hdspm->control_register & HDSPM_QS_DoubleWire)
3104 return 1;
3105 if (hdspm->control_register & HDSPM_QS_QuadWire)
3106 return 2;
3107 return 0;
3108}
3109
3110static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
3111{
3112 hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
3113 switch (mode) {
3114 case 0:
3115 break;
3116 case 1:
3117 hdspm->control_register |= HDSPM_QS_DoubleWire;
3118 break;
3119 case 2:
3120 hdspm->control_register |= HDSPM_QS_QuadWire;
3121 break;
3122 }
3123 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3124
3125 return 0;
3126}
3127
3128static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
3129 struct snd_ctl_elem_info *uinfo)
3130{
3131 static char *texts[] = { "Single", "Double", "Quad" };
3132
3133 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3134 uinfo->count = 1;
3135 uinfo->value.enumerated.items = 3;
3136
3137 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3138 uinfo->value.enumerated.item =
3139 uinfo->value.enumerated.items - 1;
3140 strcpy(uinfo->value.enumerated.name,
3141 texts[uinfo->value.enumerated.item]);
3142
3143 return 0;
3144}
3145
3146static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
3147 struct snd_ctl_elem_value *ucontrol)
3148{
3149 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3150
3151 spin_lock_irq(&hdspm->lock);
3152 ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
3153 spin_unlock_irq(&hdspm->lock);
3154 return 0;
3155}
3156
3157static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
3158 struct snd_ctl_elem_value *ucontrol)
3159{
3160 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3161 int change;
3162 int val;
3163
3164 if (!snd_hdspm_use_is_exclusive(hdspm))
3165 return -EBUSY;
3166 val = ucontrol->value.integer.value[0];
3167 if (val < 0)
3168 val = 0;
3169 if (val > 2)
3170 val = 2;
3171 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003172 change = val != hdspm_qs_wire(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003173 hdspm_set_qs_wire(hdspm, val);
3174 spin_unlock_irq(&hdspm->lock);
3175 return change;
3176}
3177
Adrian Knoth700d1ef2011-07-29 03:11:02 +02003178#define HDSPM_MADI_SPEEDMODE(xname, xindex) \
3179{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3180 .name = xname, \
3181 .index = xindex, \
3182 .info = snd_hdspm_info_madi_speedmode, \
3183 .get = snd_hdspm_get_madi_speedmode, \
3184 .put = snd_hdspm_put_madi_speedmode \
3185}
3186
3187static int hdspm_madi_speedmode(struct hdspm *hdspm)
3188{
3189 if (hdspm->control_register & HDSPM_QuadSpeed)
3190 return 2;
3191 if (hdspm->control_register & HDSPM_DoubleSpeed)
3192 return 1;
3193 return 0;
3194}
3195
3196static int hdspm_set_madi_speedmode(struct hdspm *hdspm, int mode)
3197{
3198 hdspm->control_register &= ~(HDSPM_DoubleSpeed | HDSPM_QuadSpeed);
3199 switch (mode) {
3200 case 0:
3201 break;
3202 case 1:
3203 hdspm->control_register |= HDSPM_DoubleSpeed;
3204 break;
3205 case 2:
3206 hdspm->control_register |= HDSPM_QuadSpeed;
3207 break;
3208 }
3209 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3210
3211 return 0;
3212}
3213
3214static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol,
3215 struct snd_ctl_elem_info *uinfo)
3216{
3217 static char *texts[] = { "Single", "Double", "Quad" };
3218
3219 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3220 uinfo->count = 1;
3221 uinfo->value.enumerated.items = 3;
3222
3223 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3224 uinfo->value.enumerated.item =
3225 uinfo->value.enumerated.items - 1;
3226 strcpy(uinfo->value.enumerated.name,
3227 texts[uinfo->value.enumerated.item]);
3228
3229 return 0;
3230}
3231
3232static int snd_hdspm_get_madi_speedmode(struct snd_kcontrol *kcontrol,
3233 struct snd_ctl_elem_value *ucontrol)
3234{
3235 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3236
3237 spin_lock_irq(&hdspm->lock);
3238 ucontrol->value.enumerated.item[0] = hdspm_madi_speedmode(hdspm);
3239 spin_unlock_irq(&hdspm->lock);
3240 return 0;
3241}
3242
3243static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol,
3244 struct snd_ctl_elem_value *ucontrol)
3245{
3246 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3247 int change;
3248 int val;
3249
3250 if (!snd_hdspm_use_is_exclusive(hdspm))
3251 return -EBUSY;
3252 val = ucontrol->value.integer.value[0];
3253 if (val < 0)
3254 val = 0;
3255 if (val > 2)
3256 val = 2;
3257 spin_lock_irq(&hdspm->lock);
3258 change = val != hdspm_madi_speedmode(hdspm);
3259 hdspm_set_madi_speedmode(hdspm, val);
3260 spin_unlock_irq(&hdspm->lock);
3261 return change;
3262}
Takashi Iwai763f3562005-06-03 11:25:34 +02003263
3264#define HDSPM_MIXER(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003265{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
3266 .name = xname, \
3267 .index = xindex, \
3268 .device = 0, \
3269 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
3270 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3271 .info = snd_hdspm_info_mixer, \
3272 .get = snd_hdspm_get_mixer, \
3273 .put = snd_hdspm_put_mixer \
Takashi Iwai763f3562005-06-03 11:25:34 +02003274}
3275
Takashi Iwai98274f02005-11-17 14:52:34 +01003276static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
3277 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003278{
3279 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3280 uinfo->count = 3;
3281 uinfo->value.integer.min = 0;
3282 uinfo->value.integer.max = 65535;
3283 uinfo->value.integer.step = 1;
3284 return 0;
3285}
3286
Takashi Iwai98274f02005-11-17 14:52:34 +01003287static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
3288 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003289{
Takashi Iwai98274f02005-11-17 14:52:34 +01003290 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003291 int source;
3292 int destination;
3293
3294 source = ucontrol->value.integer.value[0];
3295 if (source < 0)
3296 source = 0;
3297 else if (source >= 2 * HDSPM_MAX_CHANNELS)
3298 source = 2 * HDSPM_MAX_CHANNELS - 1;
3299
3300 destination = ucontrol->value.integer.value[1];
3301 if (destination < 0)
3302 destination = 0;
3303 else if (destination >= HDSPM_MAX_CHANNELS)
3304 destination = HDSPM_MAX_CHANNELS - 1;
3305
3306 spin_lock_irq(&hdspm->lock);
3307 if (source >= HDSPM_MAX_CHANNELS)
3308 ucontrol->value.integer.value[2] =
3309 hdspm_read_pb_gain(hdspm, destination,
3310 source - HDSPM_MAX_CHANNELS);
3311 else
3312 ucontrol->value.integer.value[2] =
3313 hdspm_read_in_gain(hdspm, destination, source);
3314
3315 spin_unlock_irq(&hdspm->lock);
3316
3317 return 0;
3318}
3319
Takashi Iwai98274f02005-11-17 14:52:34 +01003320static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
3321 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003322{
Takashi Iwai98274f02005-11-17 14:52:34 +01003323 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003324 int change;
3325 int source;
3326 int destination;
3327 int gain;
3328
3329 if (!snd_hdspm_use_is_exclusive(hdspm))
3330 return -EBUSY;
3331
3332 source = ucontrol->value.integer.value[0];
3333 destination = ucontrol->value.integer.value[1];
3334
3335 if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
3336 return -1;
3337 if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
3338 return -1;
3339
3340 gain = ucontrol->value.integer.value[2];
3341
3342 spin_lock_irq(&hdspm->lock);
3343
3344 if (source >= HDSPM_MAX_CHANNELS)
3345 change = gain != hdspm_read_pb_gain(hdspm, destination,
3346 source -
3347 HDSPM_MAX_CHANNELS);
3348 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003349 change = gain != hdspm_read_in_gain(hdspm, destination,
3350 source);
Takashi Iwai763f3562005-06-03 11:25:34 +02003351
3352 if (change) {
3353 if (source >= HDSPM_MAX_CHANNELS)
3354 hdspm_write_pb_gain(hdspm, destination,
3355 source - HDSPM_MAX_CHANNELS,
3356 gain);
3357 else
3358 hdspm_write_in_gain(hdspm, destination, source,
3359 gain);
3360 }
3361 spin_unlock_irq(&hdspm->lock);
3362
3363 return change;
3364}
3365
3366/* The simple mixer control(s) provide gain control for the
3367 basic 1:1 mappings of playback streams to output
Adrian Knoth0dca1792011-01-26 19:32:14 +01003368 streams.
Takashi Iwai763f3562005-06-03 11:25:34 +02003369*/
3370
3371#define HDSPM_PLAYBACK_MIXER \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003372{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3373 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
3374 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3375 .info = snd_hdspm_info_playback_mixer, \
3376 .get = snd_hdspm_get_playback_mixer, \
3377 .put = snd_hdspm_put_playback_mixer \
Takashi Iwai763f3562005-06-03 11:25:34 +02003378}
3379
Takashi Iwai98274f02005-11-17 14:52:34 +01003380static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
3381 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003382{
3383 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3384 uinfo->count = 1;
3385 uinfo->value.integer.min = 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003386 uinfo->value.integer.max = 64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003387 uinfo->value.integer.step = 1;
3388 return 0;
3389}
3390
Takashi Iwai98274f02005-11-17 14:52:34 +01003391static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
3392 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003393{
Takashi Iwai98274f02005-11-17 14:52:34 +01003394 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003395 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003396
3397 channel = ucontrol->id.index - 1;
3398
Takashi Iwaida3cec32008-08-08 17:12:14 +02003399 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3400 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003401
Takashi Iwai763f3562005-06-03 11:25:34 +02003402 spin_lock_irq(&hdspm->lock);
3403 ucontrol->value.integer.value[0] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003404 (hdspm_read_pb_gain(hdspm, channel, channel)*64)/UNITY_GAIN;
Takashi Iwai763f3562005-06-03 11:25:34 +02003405 spin_unlock_irq(&hdspm->lock);
3406
Takashi Iwai763f3562005-06-03 11:25:34 +02003407 return 0;
3408}
3409
Takashi Iwai98274f02005-11-17 14:52:34 +01003410static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
3411 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003412{
Takashi Iwai98274f02005-11-17 14:52:34 +01003413 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003414 int change;
3415 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003416 int gain;
3417
3418 if (!snd_hdspm_use_is_exclusive(hdspm))
3419 return -EBUSY;
3420
3421 channel = ucontrol->id.index - 1;
3422
Takashi Iwaida3cec32008-08-08 17:12:14 +02003423 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3424 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003425
Adrian Knoth0dca1792011-01-26 19:32:14 +01003426 gain = ucontrol->value.integer.value[0]*UNITY_GAIN/64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003427
3428 spin_lock_irq(&hdspm->lock);
3429 change =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003430 gain != hdspm_read_pb_gain(hdspm, channel,
3431 channel);
Takashi Iwai763f3562005-06-03 11:25:34 +02003432 if (change)
Adrian Knoth0dca1792011-01-26 19:32:14 +01003433 hdspm_write_pb_gain(hdspm, channel, channel,
Takashi Iwai763f3562005-06-03 11:25:34 +02003434 gain);
3435 spin_unlock_irq(&hdspm->lock);
3436 return change;
3437}
3438
Adrian Knoth0dca1792011-01-26 19:32:14 +01003439#define HDSPM_SYNC_CHECK(xname, xindex) \
3440{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3441 .name = xname, \
3442 .private_value = xindex, \
3443 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3444 .info = snd_hdspm_info_sync_check, \
3445 .get = snd_hdspm_get_sync_check \
Takashi Iwai763f3562005-06-03 11:25:34 +02003446}
3447
Adrian Knoth0dca1792011-01-26 19:32:14 +01003448
Takashi Iwai98274f02005-11-17 14:52:34 +01003449static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
3450 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003451{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003452 static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" };
Takashi Iwai763f3562005-06-03 11:25:34 +02003453 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3454 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003455 uinfo->value.enumerated.items = 4;
Takashi Iwai763f3562005-06-03 11:25:34 +02003456 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3457 uinfo->value.enumerated.item =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003458 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02003459 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01003460 texts[uinfo->value.enumerated.item]);
Takashi Iwai763f3562005-06-03 11:25:34 +02003461 return 0;
3462}
3463
Adrian Knoth0dca1792011-01-26 19:32:14 +01003464static int hdspm_wc_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003465{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003466 int status, status2;
3467
3468 switch (hdspm->io_type) {
3469 case AES32:
3470 status = hdspm_read(hdspm, HDSPM_statusRegister);
Andre Schramm56bde0f2013-01-09 14:40:18 +01003471 if (status & HDSPM_AES32_wcLock) {
3472 if (status & HDSPM_AES32_wcSync)
3473 return 2;
3474 else
3475 return 1;
3476 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02003477 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003478 break;
3479
3480 case MADI:
3481 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003482 if (status2 & HDSPM_wcLock) {
3483 if (status2 & HDSPM_wcSync)
3484 return 2;
3485 else
3486 return 1;
3487 }
3488 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003489 break;
3490
3491 case RayDAT:
3492 case AIO:
3493 status = hdspm_read(hdspm, HDSPM_statusRegister);
3494
3495 if (status & 0x2000000)
3496 return 2;
3497 else if (status & 0x1000000)
3498 return 1;
3499 return 0;
3500
3501 break;
3502
3503 case MADIface:
3504 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02003505 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003506
Takashi Iwai763f3562005-06-03 11:25:34 +02003507
Adrian Knoth0dca1792011-01-26 19:32:14 +01003508 return 3;
Takashi Iwai763f3562005-06-03 11:25:34 +02003509}
3510
3511
Adrian Knoth0dca1792011-01-26 19:32:14 +01003512static int hdspm_madi_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003513{
3514 int status = hdspm_read(hdspm, HDSPM_statusRegister);
3515 if (status & HDSPM_madiLock) {
3516 if (status & HDSPM_madiSync)
3517 return 2;
3518 else
3519 return 1;
3520 }
3521 return 0;
3522}
3523
Adrian Knoth0dca1792011-01-26 19:32:14 +01003524
3525static int hdspm_s1_sync_check(struct hdspm *hdspm, int idx)
3526{
3527 int status, lock, sync;
3528
3529 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3530
3531 lock = (status & (0x1<<idx)) ? 1 : 0;
3532 sync = (status & (0x100<<idx)) ? 1 : 0;
3533
3534 if (lock && sync)
3535 return 2;
3536 else if (lock)
3537 return 1;
3538 return 0;
3539}
3540
3541
3542static int hdspm_sync_in_sync_check(struct hdspm *hdspm)
3543{
3544 int status, lock = 0, sync = 0;
3545
3546 switch (hdspm->io_type) {
3547 case RayDAT:
3548 case AIO:
3549 status = hdspm_read(hdspm, HDSPM_RD_STATUS_3);
3550 lock = (status & 0x400) ? 1 : 0;
3551 sync = (status & 0x800) ? 1 : 0;
3552 break;
3553
3554 case MADI:
Adrian Knoth2e0452f2012-10-19 17:42:27 +02003555 status = hdspm_read(hdspm, HDSPM_statusRegister);
3556 lock = (status & HDSPM_syncInLock) ? 1 : 0;
3557 sync = (status & HDSPM_syncInSync) ? 1 : 0;
3558 break;
3559
Adrian Knoth0dca1792011-01-26 19:32:14 +01003560 case AES32:
3561 status = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth9a215f42012-10-19 17:42:28 +02003562 lock = (status & 0x100000) ? 1 : 0;
3563 sync = (status & 0x200000) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003564 break;
3565
3566 case MADIface:
3567 break;
3568 }
3569
3570 if (lock && sync)
3571 return 2;
3572 else if (lock)
3573 return 1;
3574
3575 return 0;
3576}
3577
3578static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx)
3579{
3580 int status2, lock, sync;
3581 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
3582
3583 lock = (status2 & (0x0080 >> idx)) ? 1 : 0;
3584 sync = (status2 & (0x8000 >> idx)) ? 1 : 0;
3585
3586 if (sync)
3587 return 2;
3588 else if (lock)
3589 return 1;
3590 return 0;
3591}
3592
3593
3594static int hdspm_tco_sync_check(struct hdspm *hdspm)
3595{
3596 int status;
3597
3598 if (hdspm->tco) {
3599 switch (hdspm->io_type) {
3600 case MADI:
3601 case AES32:
3602 status = hdspm_read(hdspm, HDSPM_statusRegister);
3603 if (status & HDSPM_tcoLock) {
3604 if (status & HDSPM_tcoSync)
3605 return 2;
3606 else
3607 return 1;
3608 }
3609 return 0;
3610
3611 break;
3612
3613 case RayDAT:
3614 case AIO:
3615 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3616
3617 if (status & 0x8000000)
3618 return 2; /* Sync */
3619 if (status & 0x4000000)
3620 return 1; /* Lock */
3621 return 0; /* No signal */
3622 break;
3623
3624 default:
3625 break;
3626 }
3627 }
3628
3629 return 3; /* N/A */
3630}
3631
3632
3633static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
3634 struct snd_ctl_elem_value *ucontrol)
3635{
3636 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3637 int val = -1;
3638
3639 switch (hdspm->io_type) {
3640 case RayDAT:
3641 switch (kcontrol->private_value) {
3642 case 0: /* WC */
3643 val = hdspm_wc_sync_check(hdspm); break;
3644 case 7: /* TCO */
3645 val = hdspm_tco_sync_check(hdspm); break;
3646 case 8: /* SYNC IN */
3647 val = hdspm_sync_in_sync_check(hdspm); break;
3648 default:
Adrian Knothd1a3c982012-11-07 18:00:09 +01003649 val = hdspm_s1_sync_check(hdspm,
3650 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003651 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02003652 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003653
3654 case AIO:
3655 switch (kcontrol->private_value) {
3656 case 0: /* WC */
3657 val = hdspm_wc_sync_check(hdspm); break;
3658 case 4: /* TCO */
3659 val = hdspm_tco_sync_check(hdspm); break;
3660 case 5: /* SYNC IN */
3661 val = hdspm_sync_in_sync_check(hdspm); break;
3662 default:
3663 val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
3664 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02003665 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003666
3667 case MADI:
3668 switch (kcontrol->private_value) {
3669 case 0: /* WC */
3670 val = hdspm_wc_sync_check(hdspm); break;
3671 case 1: /* MADI */
3672 val = hdspm_madi_sync_check(hdspm); break;
3673 case 2: /* TCO */
3674 val = hdspm_tco_sync_check(hdspm); break;
3675 case 3: /* SYNC_IN */
3676 val = hdspm_sync_in_sync_check(hdspm); break;
3677 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02003678 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003679
3680 case MADIface:
3681 val = hdspm_madi_sync_check(hdspm); /* MADI */
3682 break;
3683
3684 case AES32:
3685 switch (kcontrol->private_value) {
3686 case 0: /* WC */
3687 val = hdspm_wc_sync_check(hdspm); break;
3688 case 9: /* TCO */
3689 val = hdspm_tco_sync_check(hdspm); break;
3690 case 10 /* SYNC IN */:
3691 val = hdspm_sync_in_sync_check(hdspm); break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01003692 default: /* AES1 to AES8 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01003693 val = hdspm_aes_sync_check(hdspm,
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01003694 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003695 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02003696 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003697
3698 }
3699
3700 if (-1 == val)
3701 val = 3;
3702
3703 ucontrol->value.enumerated.item[0] = val;
3704 return 0;
3705}
3706
3707
3708
3709/**
3710 * TCO controls
3711 **/
3712static void hdspm_tco_write(struct hdspm *hdspm)
3713{
3714 unsigned int tc[4] = { 0, 0, 0, 0};
3715
3716 switch (hdspm->tco->input) {
3717 case 0:
3718 tc[2] |= HDSPM_TCO2_set_input_MSB;
3719 break;
3720 case 1:
3721 tc[2] |= HDSPM_TCO2_set_input_LSB;
3722 break;
3723 default:
3724 break;
3725 }
3726
3727 switch (hdspm->tco->framerate) {
3728 case 1:
3729 tc[1] |= HDSPM_TCO1_LTC_Format_LSB;
3730 break;
3731 case 2:
3732 tc[1] |= HDSPM_TCO1_LTC_Format_MSB;
3733 break;
3734 case 3:
3735 tc[1] |= HDSPM_TCO1_LTC_Format_MSB +
3736 HDSPM_TCO1_set_drop_frame_flag;
3737 break;
3738 case 4:
3739 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
3740 HDSPM_TCO1_LTC_Format_MSB;
3741 break;
3742 case 5:
3743 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
3744 HDSPM_TCO1_LTC_Format_MSB +
3745 HDSPM_TCO1_set_drop_frame_flag;
3746 break;
3747 default:
3748 break;
3749 }
3750
3751 switch (hdspm->tco->wordclock) {
3752 case 1:
3753 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_LSB;
3754 break;
3755 case 2:
3756 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_MSB;
3757 break;
3758 default:
3759 break;
3760 }
3761
3762 switch (hdspm->tco->samplerate) {
3763 case 1:
3764 tc[2] |= HDSPM_TCO2_set_freq;
3765 break;
3766 case 2:
3767 tc[2] |= HDSPM_TCO2_set_freq_from_app;
3768 break;
3769 default:
3770 break;
3771 }
3772
3773 switch (hdspm->tco->pull) {
3774 case 1:
3775 tc[2] |= HDSPM_TCO2_set_pull_up;
3776 break;
3777 case 2:
3778 tc[2] |= HDSPM_TCO2_set_pull_down;
3779 break;
3780 case 3:
3781 tc[2] |= HDSPM_TCO2_set_pull_up + HDSPM_TCO2_set_01_4;
3782 break;
3783 case 4:
3784 tc[2] |= HDSPM_TCO2_set_pull_down + HDSPM_TCO2_set_01_4;
3785 break;
3786 default:
3787 break;
3788 }
3789
3790 if (1 == hdspm->tco->term) {
3791 tc[2] |= HDSPM_TCO2_set_term_75R;
3792 }
3793
3794 hdspm_write(hdspm, HDSPM_WR_TCO, tc[0]);
3795 hdspm_write(hdspm, HDSPM_WR_TCO+4, tc[1]);
3796 hdspm_write(hdspm, HDSPM_WR_TCO+8, tc[2]);
3797 hdspm_write(hdspm, HDSPM_WR_TCO+12, tc[3]);
3798}
3799
3800
3801#define HDSPM_TCO_SAMPLE_RATE(xname, xindex) \
3802{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3803 .name = xname, \
3804 .index = xindex, \
3805 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
3806 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3807 .info = snd_hdspm_info_tco_sample_rate, \
3808 .get = snd_hdspm_get_tco_sample_rate, \
3809 .put = snd_hdspm_put_tco_sample_rate \
3810}
3811
3812static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol,
3813 struct snd_ctl_elem_info *uinfo)
3814{
3815 static char *texts[] = { "44.1 kHz", "48 kHz" };
3816 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3817 uinfo->count = 1;
3818 uinfo->value.enumerated.items = 2;
3819
3820 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3821 uinfo->value.enumerated.item =
3822 uinfo->value.enumerated.items - 1;
3823
3824 strcpy(uinfo->value.enumerated.name,
3825 texts[uinfo->value.enumerated.item]);
3826
3827 return 0;
3828}
3829
3830static int snd_hdspm_get_tco_sample_rate(struct snd_kcontrol *kcontrol,
3831 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003832{
Takashi Iwai98274f02005-11-17 14:52:34 +01003833 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003834
Adrian Knoth0dca1792011-01-26 19:32:14 +01003835 ucontrol->value.enumerated.item[0] = hdspm->tco->samplerate;
3836
Takashi Iwai763f3562005-06-03 11:25:34 +02003837 return 0;
3838}
3839
Adrian Knoth0dca1792011-01-26 19:32:14 +01003840static int snd_hdspm_put_tco_sample_rate(struct snd_kcontrol *kcontrol,
3841 struct snd_ctl_elem_value *ucontrol)
Remy Bruno3cee5a62006-10-16 12:46:32 +02003842{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003843 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3844
3845 if (hdspm->tco->samplerate != ucontrol->value.enumerated.item[0]) {
3846 hdspm->tco->samplerate = ucontrol->value.enumerated.item[0];
3847
3848 hdspm_tco_write(hdspm);
3849
3850 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003851 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01003852
Remy Bruno3cee5a62006-10-16 12:46:32 +02003853 return 0;
3854}
3855
Adrian Knoth0dca1792011-01-26 19:32:14 +01003856
3857#define HDSPM_TCO_PULL(xname, xindex) \
3858{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3859 .name = xname, \
3860 .index = xindex, \
3861 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
3862 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3863 .info = snd_hdspm_info_tco_pull, \
3864 .get = snd_hdspm_get_tco_pull, \
3865 .put = snd_hdspm_put_tco_pull \
3866}
3867
3868static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol,
3869 struct snd_ctl_elem_info *uinfo)
3870{
3871 static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" };
3872 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3873 uinfo->count = 1;
3874 uinfo->value.enumerated.items = 5;
3875
3876 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3877 uinfo->value.enumerated.item =
3878 uinfo->value.enumerated.items - 1;
3879
3880 strcpy(uinfo->value.enumerated.name,
3881 texts[uinfo->value.enumerated.item]);
3882
3883 return 0;
3884}
3885
3886static int snd_hdspm_get_tco_pull(struct snd_kcontrol *kcontrol,
3887 struct snd_ctl_elem_value *ucontrol)
3888{
3889 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3890
3891 ucontrol->value.enumerated.item[0] = hdspm->tco->pull;
3892
3893 return 0;
3894}
3895
3896static int snd_hdspm_put_tco_pull(struct snd_kcontrol *kcontrol,
3897 struct snd_ctl_elem_value *ucontrol)
3898{
3899 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3900
3901 if (hdspm->tco->pull != ucontrol->value.enumerated.item[0]) {
3902 hdspm->tco->pull = ucontrol->value.enumerated.item[0];
3903
3904 hdspm_tco_write(hdspm);
3905
3906 return 1;
3907 }
3908
3909 return 0;
3910}
3911
3912#define HDSPM_TCO_WCK_CONVERSION(xname, xindex) \
3913{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3914 .name = xname, \
3915 .index = xindex, \
3916 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
3917 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3918 .info = snd_hdspm_info_tco_wck_conversion, \
3919 .get = snd_hdspm_get_tco_wck_conversion, \
3920 .put = snd_hdspm_put_tco_wck_conversion \
3921}
3922
3923static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol,
3924 struct snd_ctl_elem_info *uinfo)
3925{
3926 static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
3927 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3928 uinfo->count = 1;
3929 uinfo->value.enumerated.items = 3;
3930
3931 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3932 uinfo->value.enumerated.item =
3933 uinfo->value.enumerated.items - 1;
3934
3935 strcpy(uinfo->value.enumerated.name,
3936 texts[uinfo->value.enumerated.item]);
3937
3938 return 0;
3939}
3940
3941static int snd_hdspm_get_tco_wck_conversion(struct snd_kcontrol *kcontrol,
3942 struct snd_ctl_elem_value *ucontrol)
3943{
3944 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3945
3946 ucontrol->value.enumerated.item[0] = hdspm->tco->wordclock;
3947
3948 return 0;
3949}
3950
3951static int snd_hdspm_put_tco_wck_conversion(struct snd_kcontrol *kcontrol,
3952 struct snd_ctl_elem_value *ucontrol)
3953{
3954 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3955
3956 if (hdspm->tco->wordclock != ucontrol->value.enumerated.item[0]) {
3957 hdspm->tco->wordclock = ucontrol->value.enumerated.item[0];
3958
3959 hdspm_tco_write(hdspm);
3960
3961 return 1;
3962 }
3963
3964 return 0;
3965}
3966
3967
3968#define HDSPM_TCO_FRAME_RATE(xname, xindex) \
3969{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3970 .name = xname, \
3971 .index = xindex, \
3972 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
3973 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3974 .info = snd_hdspm_info_tco_frame_rate, \
3975 .get = snd_hdspm_get_tco_frame_rate, \
3976 .put = snd_hdspm_put_tco_frame_rate \
3977}
3978
3979static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol,
3980 struct snd_ctl_elem_info *uinfo)
3981{
3982 static char *texts[] = { "24 fps", "25 fps", "29.97fps",
3983 "29.97 dfps", "30 fps", "30 dfps" };
3984 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3985 uinfo->count = 1;
3986 uinfo->value.enumerated.items = 6;
3987
3988 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3989 uinfo->value.enumerated.item =
3990 uinfo->value.enumerated.items - 1;
3991
3992 strcpy(uinfo->value.enumerated.name,
3993 texts[uinfo->value.enumerated.item]);
3994
3995 return 0;
3996}
3997
3998static int snd_hdspm_get_tco_frame_rate(struct snd_kcontrol *kcontrol,
Remy Bruno3cee5a62006-10-16 12:46:32 +02003999 struct snd_ctl_elem_value *ucontrol)
4000{
Remy Bruno3cee5a62006-10-16 12:46:32 +02004001 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4002
Adrian Knoth0dca1792011-01-26 19:32:14 +01004003 ucontrol->value.enumerated.item[0] = hdspm->tco->framerate;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004004
Remy Bruno3cee5a62006-10-16 12:46:32 +02004005 return 0;
4006}
Takashi Iwai763f3562005-06-03 11:25:34 +02004007
Adrian Knoth0dca1792011-01-26 19:32:14 +01004008static int snd_hdspm_put_tco_frame_rate(struct snd_kcontrol *kcontrol,
4009 struct snd_ctl_elem_value *ucontrol)
4010{
4011 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4012
4013 if (hdspm->tco->framerate != ucontrol->value.enumerated.item[0]) {
4014 hdspm->tco->framerate = ucontrol->value.enumerated.item[0];
4015
4016 hdspm_tco_write(hdspm);
4017
4018 return 1;
4019 }
4020
4021 return 0;
4022}
4023
4024
4025#define HDSPM_TCO_SYNC_SOURCE(xname, xindex) \
4026{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4027 .name = xname, \
4028 .index = xindex, \
4029 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4030 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4031 .info = snd_hdspm_info_tco_sync_source, \
4032 .get = snd_hdspm_get_tco_sync_source, \
4033 .put = snd_hdspm_put_tco_sync_source \
4034}
4035
4036static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol,
4037 struct snd_ctl_elem_info *uinfo)
4038{
4039 static char *texts[] = { "LTC", "Video", "WCK" };
4040 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4041 uinfo->count = 1;
4042 uinfo->value.enumerated.items = 3;
4043
4044 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4045 uinfo->value.enumerated.item =
4046 uinfo->value.enumerated.items - 1;
4047
4048 strcpy(uinfo->value.enumerated.name,
4049 texts[uinfo->value.enumerated.item]);
4050
4051 return 0;
4052}
4053
4054static int snd_hdspm_get_tco_sync_source(struct snd_kcontrol *kcontrol,
4055 struct snd_ctl_elem_value *ucontrol)
4056{
4057 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4058
4059 ucontrol->value.enumerated.item[0] = hdspm->tco->input;
4060
4061 return 0;
4062}
4063
4064static int snd_hdspm_put_tco_sync_source(struct snd_kcontrol *kcontrol,
4065 struct snd_ctl_elem_value *ucontrol)
4066{
4067 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4068
4069 if (hdspm->tco->input != ucontrol->value.enumerated.item[0]) {
4070 hdspm->tco->input = ucontrol->value.enumerated.item[0];
4071
4072 hdspm_tco_write(hdspm);
4073
4074 return 1;
4075 }
4076
4077 return 0;
4078}
4079
4080
4081#define HDSPM_TCO_WORD_TERM(xname, xindex) \
4082{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4083 .name = xname, \
4084 .index = xindex, \
4085 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4086 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4087 .info = snd_hdspm_info_tco_word_term, \
4088 .get = snd_hdspm_get_tco_word_term, \
4089 .put = snd_hdspm_put_tco_word_term \
4090}
4091
4092static int snd_hdspm_info_tco_word_term(struct snd_kcontrol *kcontrol,
4093 struct snd_ctl_elem_info *uinfo)
4094{
4095 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
4096 uinfo->count = 1;
4097 uinfo->value.integer.min = 0;
4098 uinfo->value.integer.max = 1;
4099
4100 return 0;
4101}
4102
4103
4104static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol,
4105 struct snd_ctl_elem_value *ucontrol)
4106{
4107 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4108
4109 ucontrol->value.enumerated.item[0] = hdspm->tco->term;
4110
4111 return 0;
4112}
4113
4114
4115static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol,
4116 struct snd_ctl_elem_value *ucontrol)
4117{
4118 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4119
4120 if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) {
4121 hdspm->tco->term = ucontrol->value.enumerated.item[0];
4122
4123 hdspm_tco_write(hdspm);
4124
4125 return 1;
4126 }
4127
4128 return 0;
4129}
4130
4131
4132
Takashi Iwai763f3562005-06-03 11:25:34 +02004133
Remy Bruno3cee5a62006-10-16 12:46:32 +02004134static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004135 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004136 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Takashi Iwai763f3562005-06-03 11:25:34 +02004137 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4138 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4139 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4140 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Adrian Knothb8812c52012-10-19 17:42:26 +02004141 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004142 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4143 HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
Adrian Knoth930f4ff2012-10-19 17:42:29 +02004144 HDSPM_SYNC_CHECK("TCO SyncCheck", 2),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004145 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
Adrian Knothc9e16682012-12-03 14:55:50 +01004146 HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
4147 HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
4148 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
4149 HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
Adrian Knoth700d1ef2011-07-29 03:11:02 +02004150 HDSPM_INPUT_SELECT("Input Select", 0),
4151 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004152};
4153
4154
4155static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
4156 HDSPM_MIXER("Mixer", 0),
4157 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4158 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4159 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4160 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4161 HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
Adrian Knothc9e16682012-12-03 14:55:50 +01004162 HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
4163 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
4164 HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
Adrian Knoth700d1ef2011-07-29 03:11:02 +02004165 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004166};
4167
Adrian Knoth0dca1792011-01-26 19:32:14 +01004168static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004169 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004170 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004171 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4172 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4173 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4174 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004175 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004176 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4177 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4178 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4179 HDSPM_SYNC_CHECK("ADAT SyncCheck", 3),
4180 HDSPM_SYNC_CHECK("TCO SyncCheck", 4),
4181 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 5),
4182 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4183 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4184 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4185 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT Frequency", 3),
4186 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 4),
4187 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5)
4188
4189 /*
4190 HDSPM_INPUT_SELECT("Input Select", 0),
4191 HDSPM_SPDIF_OPTICAL("SPDIF Out Optical", 0),
4192 HDSPM_PROFESSIONAL("SPDIF Out Professional", 0);
4193 HDSPM_SPDIF_IN("SPDIF In", 0);
4194 HDSPM_BREAKOUT_CABLE("Breakout Cable", 0);
4195 HDSPM_INPUT_LEVEL("Input Level", 0);
4196 HDSPM_OUTPUT_LEVEL("Output Level", 0);
4197 HDSPM_PHONES("Phones", 0);
4198 */
4199};
4200
4201static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = {
4202 HDSPM_MIXER("Mixer", 0),
4203 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4204 HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0),
4205 HDSPM_PREF_SYNC_REF("Pref Sync Ref", 0),
4206 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4207 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4208 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4209 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4210 HDSPM_SYNC_CHECK("ADAT1 SyncCheck", 3),
4211 HDSPM_SYNC_CHECK("ADAT2 SyncCheck", 4),
4212 HDSPM_SYNC_CHECK("ADAT3 SyncCheck", 5),
4213 HDSPM_SYNC_CHECK("ADAT4 SyncCheck", 6),
4214 HDSPM_SYNC_CHECK("TCO SyncCheck", 7),
4215 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 8),
4216 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4217 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4218 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4219 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT1 Frequency", 3),
4220 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT2 Frequency", 4),
4221 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT3 Frequency", 5),
4222 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT4 Frequency", 6),
4223 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 7),
4224 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8)
4225};
4226
4227static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
4228 HDSPM_MIXER("Mixer", 0),
4229 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4230 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4231 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4232 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4233 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4234 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4235 HDSPM_SYNC_CHECK("WC Sync Check", 0),
4236 HDSPM_SYNC_CHECK("AES1 Sync Check", 1),
4237 HDSPM_SYNC_CHECK("AES2 Sync Check", 2),
4238 HDSPM_SYNC_CHECK("AES3 Sync Check", 3),
4239 HDSPM_SYNC_CHECK("AES4 Sync Check", 4),
4240 HDSPM_SYNC_CHECK("AES5 Sync Check", 5),
4241 HDSPM_SYNC_CHECK("AES6 Sync Check", 6),
4242 HDSPM_SYNC_CHECK("AES7 Sync Check", 7),
4243 HDSPM_SYNC_CHECK("AES8 Sync Check", 8),
4244 HDSPM_SYNC_CHECK("TCO Sync Check", 9),
4245 HDSPM_SYNC_CHECK("SYNC IN Sync Check", 10),
4246 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4247 HDSPM_AUTOSYNC_SAMPLE_RATE("AES1 Frequency", 1),
4248 HDSPM_AUTOSYNC_SAMPLE_RATE("AES2 Frequency", 2),
4249 HDSPM_AUTOSYNC_SAMPLE_RATE("AES3 Frequency", 3),
4250 HDSPM_AUTOSYNC_SAMPLE_RATE("AES4 Frequency", 4),
4251 HDSPM_AUTOSYNC_SAMPLE_RATE("AES5 Frequency", 5),
4252 HDSPM_AUTOSYNC_SAMPLE_RATE("AES6 Frequency", 6),
4253 HDSPM_AUTOSYNC_SAMPLE_RATE("AES7 Frequency", 7),
4254 HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8),
4255 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9),
4256 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10),
Adrian Knothc9e16682012-12-03 14:55:50 +01004257 HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
4258 HDSPM_TOGGLE_SETTING("Emphasis", HDSPM_Emphasis),
4259 HDSPM_TOGGLE_SETTING("Non Audio", HDSPM_Dolby),
4260 HDSPM_TOGGLE_SETTING("Professional", HDSPM_Professional),
4261 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004262 HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
4263 HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
4264};
4265
Adrian Knoth0dca1792011-01-26 19:32:14 +01004266
4267
4268/* Control elements for the optional TCO module */
4269static struct snd_kcontrol_new snd_hdspm_controls_tco[] = {
4270 HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0),
4271 HDSPM_TCO_PULL("TCO Pull", 0),
4272 HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0),
4273 HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0),
4274 HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0),
4275 HDSPM_TCO_WORD_TERM("TCO Word Term", 0)
4276};
4277
4278
Takashi Iwai98274f02005-11-17 14:52:34 +01004279static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
Takashi Iwai763f3562005-06-03 11:25:34 +02004280
4281
Takashi Iwai98274f02005-11-17 14:52:34 +01004282static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004283{
4284 int i;
4285
Adrian Knoth0dca1792011-01-26 19:32:14 +01004286 for (i = hdspm->ds_out_channels; i < hdspm->ss_out_channels; ++i) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004287 if (hdspm->system_sample_rate > 48000) {
4288 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004289 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
4290 SNDRV_CTL_ELEM_ACCESS_READ |
4291 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004292 } else {
4293 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004294 SNDRV_CTL_ELEM_ACCESS_READWRITE |
4295 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004296 }
4297 snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
Adrian Knoth0dca1792011-01-26 19:32:14 +01004298 SNDRV_CTL_EVENT_MASK_INFO,
4299 &hdspm->playback_mixer_ctls[i]->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02004300 }
4301
4302 return 0;
4303}
4304
4305
Adrian Knoth0dca1792011-01-26 19:32:14 +01004306static int snd_hdspm_create_controls(struct snd_card *card,
4307 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004308{
4309 unsigned int idx, limit;
4310 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01004311 struct snd_kcontrol *kctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004312 struct snd_kcontrol_new *list = NULL;
Takashi Iwai763f3562005-06-03 11:25:34 +02004313
Adrian Knoth0dca1792011-01-26 19:32:14 +01004314 switch (hdspm->io_type) {
4315 case MADI:
4316 list = snd_hdspm_controls_madi;
4317 limit = ARRAY_SIZE(snd_hdspm_controls_madi);
4318 break;
4319 case MADIface:
4320 list = snd_hdspm_controls_madiface;
4321 limit = ARRAY_SIZE(snd_hdspm_controls_madiface);
4322 break;
4323 case AIO:
4324 list = snd_hdspm_controls_aio;
4325 limit = ARRAY_SIZE(snd_hdspm_controls_aio);
4326 break;
4327 case RayDAT:
4328 list = snd_hdspm_controls_raydat;
4329 limit = ARRAY_SIZE(snd_hdspm_controls_raydat);
4330 break;
4331 case AES32:
4332 list = snd_hdspm_controls_aes32;
4333 limit = ARRAY_SIZE(snd_hdspm_controls_aes32);
4334 break;
4335 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004336
Adrian Knoth0dca1792011-01-26 19:32:14 +01004337 if (NULL != list) {
4338 for (idx = 0; idx < limit; idx++) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004339 err = snd_ctl_add(card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004340 snd_ctl_new1(&list[idx], hdspm));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004341 if (err < 0)
4342 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004343 }
4344 }
4345
Takashi Iwai763f3562005-06-03 11:25:34 +02004346
Adrian Knoth0dca1792011-01-26 19:32:14 +01004347 /* create simple 1:1 playback mixer controls */
Takashi Iwai763f3562005-06-03 11:25:34 +02004348 snd_hdspm_playback_mixer.name = "Chn";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004349 if (hdspm->system_sample_rate >= 128000) {
4350 limit = hdspm->qs_out_channels;
4351 } else if (hdspm->system_sample_rate >= 64000) {
4352 limit = hdspm->ds_out_channels;
4353 } else {
4354 limit = hdspm->ss_out_channels;
4355 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004356 for (idx = 0; idx < limit; ++idx) {
4357 snd_hdspm_playback_mixer.index = idx + 1;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004358 kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm);
4359 err = snd_ctl_add(card, kctl);
4360 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004361 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004362 hdspm->playback_mixer_ctls[idx] = kctl;
4363 }
4364
Adrian Knoth0dca1792011-01-26 19:32:14 +01004365
4366 if (hdspm->tco) {
4367 /* add tco control elements */
4368 list = snd_hdspm_controls_tco;
4369 limit = ARRAY_SIZE(snd_hdspm_controls_tco);
4370 for (idx = 0; idx < limit; idx++) {
4371 err = snd_ctl_add(card,
4372 snd_ctl_new1(&list[idx], hdspm));
4373 if (err < 0)
4374 return err;
4375 }
4376 }
4377
Takashi Iwai763f3562005-06-03 11:25:34 +02004378 return 0;
4379}
4380
4381/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01004382 /proc interface
Takashi Iwai763f3562005-06-03 11:25:34 +02004383 ------------------------------------------------------------*/
4384
4385static void
Remy Bruno3cee5a62006-10-16 12:46:32 +02004386snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
4387 struct snd_info_buffer *buffer)
Takashi Iwai763f3562005-06-03 11:25:34 +02004388{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004389 struct hdspm *hdspm = entry->private_data;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004390 unsigned int status, status2, control, freq;
4391
Takashi Iwai763f3562005-06-03 11:25:34 +02004392 char *pref_sync_ref;
4393 char *autosync_ref;
4394 char *system_clock_mode;
Takashi Iwai763f3562005-06-03 11:25:34 +02004395 char *insel;
Takashi Iwai763f3562005-06-03 11:25:34 +02004396 int x, x2;
4397
Adrian Knoth0dca1792011-01-26 19:32:14 +01004398 /* TCO stuff */
4399 int a, ltc, frames, seconds, minutes, hours;
4400 unsigned int period;
4401 u64 freq_const = 0;
4402 u32 rate;
4403
Takashi Iwai763f3562005-06-03 11:25:34 +02004404 status = hdspm_read(hdspm, HDSPM_statusRegister);
4405 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004406 control = hdspm->control_register;
4407 freq = hdspm_read(hdspm, HDSPM_timecodeRegister);
Takashi Iwai763f3562005-06-03 11:25:34 +02004408
4409 snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004410 hdspm->card_name, hdspm->card->number + 1,
4411 hdspm->firmware_rev,
4412 (status2 & HDSPM_version0) |
4413 (status2 & HDSPM_version1) | (status2 &
4414 HDSPM_version2));
4415
4416 snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n",
4417 (hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF,
Adrian Knoth7d53a632012-01-04 14:31:16 +01004418 hdspm->serial);
Takashi Iwai763f3562005-06-03 11:25:34 +02004419
4420 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004421 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
Takashi Iwai763f3562005-06-03 11:25:34 +02004422
4423 snd_iprintf(buffer, "--- System ---\n");
4424
4425 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004426 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4427 status & HDSPM_audioIRQPending,
4428 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4429 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4430 hdspm->irq_count);
Takashi Iwai763f3562005-06-03 11:25:34 +02004431 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004432 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4433 "estimated= %ld (bytes)\n",
4434 ((status & HDSPM_BufferID) ? 1 : 0),
4435 (status & HDSPM_BufferPositionMask),
4436 (status & HDSPM_BufferPositionMask) %
4437 (2 * (int)hdspm->period_bytes),
4438 ((status & HDSPM_BufferPositionMask) - 64) %
4439 (2 * (int)hdspm->period_bytes),
4440 (long) hdspm_hw_pointer(hdspm) * 4);
Takashi Iwai763f3562005-06-03 11:25:34 +02004441
4442 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004443 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4444 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4445 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4446 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4447 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
Takashi Iwai763f3562005-06-03 11:25:34 +02004448 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004449 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4450 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4451 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4452 snd_iprintf(buffer,
4453 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4454 "status2=0x%x\n",
4455 hdspm->control_register, hdspm->control2_register,
4456 status, status2);
4457 if (status & HDSPM_tco_detect) {
4458 snd_iprintf(buffer, "TCO module detected.\n");
4459 a = hdspm_read(hdspm, HDSPM_RD_TCO+4);
4460 if (a & HDSPM_TCO1_LTC_Input_valid) {
4461 snd_iprintf(buffer, " LTC valid, ");
4462 switch (a & (HDSPM_TCO1_LTC_Format_LSB |
4463 HDSPM_TCO1_LTC_Format_MSB)) {
4464 case 0:
4465 snd_iprintf(buffer, "24 fps, ");
4466 break;
4467 case HDSPM_TCO1_LTC_Format_LSB:
4468 snd_iprintf(buffer, "25 fps, ");
4469 break;
4470 case HDSPM_TCO1_LTC_Format_MSB:
4471 snd_iprintf(buffer, "29.97 fps, ");
4472 break;
4473 default:
4474 snd_iprintf(buffer, "30 fps, ");
4475 break;
4476 }
4477 if (a & HDSPM_TCO1_set_drop_frame_flag) {
4478 snd_iprintf(buffer, "drop frame\n");
4479 } else {
4480 snd_iprintf(buffer, "full frame\n");
4481 }
4482 } else {
4483 snd_iprintf(buffer, " no LTC\n");
4484 }
4485 if (a & HDSPM_TCO1_Video_Input_Format_NTSC) {
4486 snd_iprintf(buffer, " Video: NTSC\n");
4487 } else if (a & HDSPM_TCO1_Video_Input_Format_PAL) {
4488 snd_iprintf(buffer, " Video: PAL\n");
4489 } else {
4490 snd_iprintf(buffer, " No video\n");
4491 }
4492 if (a & HDSPM_TCO1_TCO_lock) {
4493 snd_iprintf(buffer, " Sync: lock\n");
4494 } else {
4495 snd_iprintf(buffer, " Sync: no lock\n");
4496 }
4497
4498 switch (hdspm->io_type) {
4499 case MADI:
4500 case AES32:
4501 freq_const = 110069313433624ULL;
4502 break;
4503 case RayDAT:
4504 case AIO:
4505 freq_const = 104857600000000ULL;
4506 break;
4507 case MADIface:
4508 break; /* no TCO possible */
4509 }
4510
4511 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
4512 snd_iprintf(buffer, " period: %u\n", period);
4513
4514
4515 /* rate = freq_const/period; */
4516 rate = div_u64(freq_const, period);
4517
4518 if (control & HDSPM_QuadSpeed) {
4519 rate *= 4;
4520 } else if (control & HDSPM_DoubleSpeed) {
4521 rate *= 2;
4522 }
4523
4524 snd_iprintf(buffer, " Frequency: %u Hz\n",
4525 (unsigned int) rate);
4526
4527 ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
4528 frames = ltc & 0xF;
4529 ltc >>= 4;
4530 frames += (ltc & 0x3) * 10;
4531 ltc >>= 4;
4532 seconds = ltc & 0xF;
4533 ltc >>= 4;
4534 seconds += (ltc & 0x7) * 10;
4535 ltc >>= 4;
4536 minutes = ltc & 0xF;
4537 ltc >>= 4;
4538 minutes += (ltc & 0x7) * 10;
4539 ltc >>= 4;
4540 hours = ltc & 0xF;
4541 ltc >>= 4;
4542 hours += (ltc & 0x3) * 10;
4543 snd_iprintf(buffer,
4544 " LTC In: %02d:%02d:%02d:%02d\n",
4545 hours, minutes, seconds, frames);
4546
4547 } else {
4548 snd_iprintf(buffer, "No TCO module detected.\n");
4549 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004550
4551 snd_iprintf(buffer, "--- Settings ---\n");
4552
Adrian Knoth7cb155f2011-08-15 00:22:53 +02004553 x = hdspm_get_latency(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02004554
4555 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004556 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4557 x, (unsigned long) hdspm->period_bytes);
Takashi Iwai763f3562005-06-03 11:25:34 +02004558
Adrian Knoth0dca1792011-01-26 19:32:14 +01004559 snd_iprintf(buffer, "Line out: %s\n",
4560 (hdspm->control_register & HDSPM_LineOut) ? "on " : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004561
4562 switch (hdspm->control_register & HDSPM_InputMask) {
4563 case HDSPM_InputOptical:
4564 insel = "Optical";
4565 break;
4566 case HDSPM_InputCoaxial:
4567 insel = "Coaxial";
4568 break;
4569 default:
Masanari Iidaec8f53f2012-11-02 00:28:50 +09004570 insel = "Unknown";
Takashi Iwai763f3562005-06-03 11:25:34 +02004571 }
4572
Takashi Iwai763f3562005-06-03 11:25:34 +02004573 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004574 "ClearTrackMarker = %s, Transmit in %s Channel Mode, "
4575 "Auto Input %s\n",
4576 (hdspm->control_register & HDSPM_clr_tms) ? "on" : "off",
4577 (hdspm->control_register & HDSPM_TX_64ch) ? "64" : "56",
4578 (hdspm->control_register & HDSPM_AutoInp) ? "on" : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004579
Adrian Knoth0dca1792011-01-26 19:32:14 +01004580
Remy Bruno3cee5a62006-10-16 12:46:32 +02004581 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
Adrian Knoth0dca1792011-01-26 19:32:14 +01004582 system_clock_mode = "AutoSync";
Remy Bruno3cee5a62006-10-16 12:46:32 +02004583 else
Takashi Iwai763f3562005-06-03 11:25:34 +02004584 system_clock_mode = "Master";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004585 snd_iprintf(buffer, "AutoSync Reference: %s\n", system_clock_mode);
Takashi Iwai763f3562005-06-03 11:25:34 +02004586
4587 switch (hdspm_pref_sync_ref(hdspm)) {
4588 case HDSPM_SYNC_FROM_WORD:
4589 pref_sync_ref = "Word Clock";
4590 break;
4591 case HDSPM_SYNC_FROM_MADI:
4592 pref_sync_ref = "MADI Sync";
4593 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004594 case HDSPM_SYNC_FROM_TCO:
4595 pref_sync_ref = "TCO";
4596 break;
4597 case HDSPM_SYNC_FROM_SYNC_IN:
4598 pref_sync_ref = "Sync In";
4599 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004600 default:
4601 pref_sync_ref = "XXXX Clock";
4602 break;
4603 }
4604 snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004605 pref_sync_ref);
Takashi Iwai763f3562005-06-03 11:25:34 +02004606
4607 snd_iprintf(buffer, "System Clock Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004608 hdspm->system_sample_rate);
Takashi Iwai763f3562005-06-03 11:25:34 +02004609
4610
4611 snd_iprintf(buffer, "--- Status:\n");
4612
4613 x = status & HDSPM_madiSync;
4614 x2 = status2 & HDSPM_wcSync;
4615
4616 snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004617 (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
4618 "NoLock",
4619 (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
4620 "NoLock");
Takashi Iwai763f3562005-06-03 11:25:34 +02004621
4622 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004623 case HDSPM_AUTOSYNC_FROM_SYNC_IN:
4624 autosync_ref = "Sync In";
4625 break;
4626 case HDSPM_AUTOSYNC_FROM_TCO:
4627 autosync_ref = "TCO";
4628 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004629 case HDSPM_AUTOSYNC_FROM_WORD:
4630 autosync_ref = "Word Clock";
4631 break;
4632 case HDSPM_AUTOSYNC_FROM_MADI:
4633 autosync_ref = "MADI Sync";
4634 break;
4635 case HDSPM_AUTOSYNC_FROM_NONE:
4636 autosync_ref = "Input not valid";
4637 break;
4638 default:
4639 autosync_ref = "---";
4640 break;
4641 }
4642 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004643 "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
4644 autosync_ref, hdspm_external_sample_rate(hdspm),
4645 (status & HDSPM_madiFreqMask) >> 22,
4646 (status2 & HDSPM_wcFreqMask) >> 5);
Takashi Iwai763f3562005-06-03 11:25:34 +02004647
4648 snd_iprintf(buffer, "Input: %s, Mode=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004649 (status & HDSPM_AB_int) ? "Coax" : "Optical",
4650 (status & HDSPM_RX_64ch) ? "64 channels" :
4651 "56 channels");
Takashi Iwai763f3562005-06-03 11:25:34 +02004652
4653 snd_iprintf(buffer, "\n");
4654}
4655
Remy Bruno3cee5a62006-10-16 12:46:32 +02004656static void
4657snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
4658 struct snd_info_buffer *buffer)
4659{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004660 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004661 unsigned int status;
4662 unsigned int status2;
4663 unsigned int timecode;
Andre Schramm56bde0f2013-01-09 14:40:18 +01004664 unsigned int wcLock, wcSync;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004665 int pref_syncref;
4666 char *autosync_ref;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004667 int x;
4668
4669 status = hdspm_read(hdspm, HDSPM_statusRegister);
4670 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
4671 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
4672
4673 snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
4674 hdspm->card_name, hdspm->card->number + 1,
4675 hdspm->firmware_rev);
4676
4677 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
4678 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
4679
4680 snd_iprintf(buffer, "--- System ---\n");
4681
4682 snd_iprintf(buffer,
4683 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4684 status & HDSPM_audioIRQPending,
4685 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4686 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4687 hdspm->irq_count);
4688 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004689 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4690 "estimated= %ld (bytes)\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004691 ((status & HDSPM_BufferID) ? 1 : 0),
4692 (status & HDSPM_BufferPositionMask),
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004693 (status & HDSPM_BufferPositionMask) %
4694 (2 * (int)hdspm->period_bytes),
4695 ((status & HDSPM_BufferPositionMask) - 64) %
4696 (2 * (int)hdspm->period_bytes),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004697 (long) hdspm_hw_pointer(hdspm) * 4);
4698
4699 snd_iprintf(buffer,
4700 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4701 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4702 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4703 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4704 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
4705 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004706 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4707 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4708 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4709 snd_iprintf(buffer,
4710 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4711 "status2=0x%x\n",
4712 hdspm->control_register, hdspm->control2_register,
4713 status, status2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02004714
4715 snd_iprintf(buffer, "--- Settings ---\n");
4716
Adrian Knoth7cb155f2011-08-15 00:22:53 +02004717 x = hdspm_get_latency(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02004718
4719 snd_iprintf(buffer,
4720 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4721 x, (unsigned long) hdspm->period_bytes);
4722
Adrian Knoth0dca1792011-01-26 19:32:14 +01004723 snd_iprintf(buffer, "Line out: %s\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004724 (hdspm->
Adrian Knoth0dca1792011-01-26 19:32:14 +01004725 control_register & HDSPM_LineOut) ? "on " : "off");
Remy Bruno3cee5a62006-10-16 12:46:32 +02004726
4727 snd_iprintf(buffer,
4728 "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
4729 (hdspm->
4730 control_register & HDSPM_clr_tms) ? "on" : "off",
4731 (hdspm->
4732 control_register & HDSPM_Emphasis) ? "on" : "off",
4733 (hdspm->
4734 control_register & HDSPM_Dolby) ? "on" : "off");
4735
Remy Bruno3cee5a62006-10-16 12:46:32 +02004736
4737 pref_syncref = hdspm_pref_sync_ref(hdspm);
4738 if (pref_syncref == 0)
4739 snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
4740 else
4741 snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
4742 pref_syncref);
4743
4744 snd_iprintf(buffer, "System Clock Frequency: %d\n",
4745 hdspm->system_sample_rate);
4746
4747 snd_iprintf(buffer, "Double speed: %s\n",
4748 hdspm->control_register & HDSPM_DS_DoubleWire?
4749 "Double wire" : "Single wire");
4750 snd_iprintf(buffer, "Quad speed: %s\n",
4751 hdspm->control_register & HDSPM_QS_DoubleWire?
4752 "Double wire" :
4753 hdspm->control_register & HDSPM_QS_QuadWire?
4754 "Quad wire" : "Single wire");
4755
4756 snd_iprintf(buffer, "--- Status:\n");
4757
Andre Schramm56bde0f2013-01-09 14:40:18 +01004758 wcLock = status & HDSPM_AES32_wcLock;
4759 wcSync = wcLock && (status & HDSPM_AES32_wcSync);
4760
Remy Bruno3cee5a62006-10-16 12:46:32 +02004761 snd_iprintf(buffer, "Word: %s Frequency: %d\n",
Andre Schramm56bde0f2013-01-09 14:40:18 +01004762 (wcLock) ? (wcSync ? "Sync " : "Lock ") : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004763 HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004764
4765 for (x = 0; x < 8; x++) {
4766 snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004767 x+1,
4768 (status2 & (HDSPM_LockAES >> x)) ?
Adrian Knoth0dca1792011-01-26 19:32:14 +01004769 "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004770 HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004771 }
4772
4773 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004774 case HDSPM_AES32_AUTOSYNC_FROM_NONE:
4775 autosync_ref = "None"; break;
4776 case HDSPM_AES32_AUTOSYNC_FROM_WORD:
4777 autosync_ref = "Word Clock"; break;
4778 case HDSPM_AES32_AUTOSYNC_FROM_AES1:
4779 autosync_ref = "AES1"; break;
4780 case HDSPM_AES32_AUTOSYNC_FROM_AES2:
4781 autosync_ref = "AES2"; break;
4782 case HDSPM_AES32_AUTOSYNC_FROM_AES3:
4783 autosync_ref = "AES3"; break;
4784 case HDSPM_AES32_AUTOSYNC_FROM_AES4:
4785 autosync_ref = "AES4"; break;
4786 case HDSPM_AES32_AUTOSYNC_FROM_AES5:
4787 autosync_ref = "AES5"; break;
4788 case HDSPM_AES32_AUTOSYNC_FROM_AES6:
4789 autosync_ref = "AES6"; break;
4790 case HDSPM_AES32_AUTOSYNC_FROM_AES7:
4791 autosync_ref = "AES7"; break;
4792 case HDSPM_AES32_AUTOSYNC_FROM_AES8:
4793 autosync_ref = "AES8"; break;
4794 default:
4795 autosync_ref = "---"; break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004796 }
4797 snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
4798
4799 snd_iprintf(buffer, "\n");
4800}
4801
Adrian Knoth0dca1792011-01-26 19:32:14 +01004802static void
4803snd_hdspm_proc_read_raydat(struct snd_info_entry *entry,
4804 struct snd_info_buffer *buffer)
4805{
4806 struct hdspm *hdspm = entry->private_data;
4807 unsigned int status1, status2, status3, control, i;
4808 unsigned int lock, sync;
4809
4810 status1 = hdspm_read(hdspm, HDSPM_RD_STATUS_1); /* s1 */
4811 status2 = hdspm_read(hdspm, HDSPM_RD_STATUS_2); /* freq */
4812 status3 = hdspm_read(hdspm, HDSPM_RD_STATUS_3); /* s2 */
4813
4814 control = hdspm->control_register;
4815
4816 snd_iprintf(buffer, "STATUS1: 0x%08x\n", status1);
4817 snd_iprintf(buffer, "STATUS2: 0x%08x\n", status2);
4818 snd_iprintf(buffer, "STATUS3: 0x%08x\n", status3);
4819
4820
4821 snd_iprintf(buffer, "\n*** CLOCK MODE\n\n");
4822
4823 snd_iprintf(buffer, "Clock mode : %s\n",
4824 (hdspm_system_clock_mode(hdspm) == 0) ? "master" : "slave");
4825 snd_iprintf(buffer, "System frequency: %d Hz\n",
4826 hdspm_get_system_sample_rate(hdspm));
4827
4828 snd_iprintf(buffer, "\n*** INPUT STATUS\n\n");
4829
4830 lock = 0x1;
4831 sync = 0x100;
4832
4833 for (i = 0; i < 8; i++) {
4834 snd_iprintf(buffer, "s1_input %d: Lock %d, Sync %d, Freq %s\n",
4835 i,
4836 (status1 & lock) ? 1 : 0,
4837 (status1 & sync) ? 1 : 0,
4838 texts_freq[(status2 >> (i * 4)) & 0xF]);
4839
4840 lock = lock<<1;
4841 sync = sync<<1;
4842 }
4843
4844 snd_iprintf(buffer, "WC input: Lock %d, Sync %d, Freq %s\n",
4845 (status1 & 0x1000000) ? 1 : 0,
4846 (status1 & 0x2000000) ? 1 : 0,
4847 texts_freq[(status1 >> 16) & 0xF]);
4848
4849 snd_iprintf(buffer, "TCO input: Lock %d, Sync %d, Freq %s\n",
4850 (status1 & 0x4000000) ? 1 : 0,
4851 (status1 & 0x8000000) ? 1 : 0,
4852 texts_freq[(status1 >> 20) & 0xF]);
4853
4854 snd_iprintf(buffer, "SYNC IN: Lock %d, Sync %d, Freq %s\n",
4855 (status3 & 0x400) ? 1 : 0,
4856 (status3 & 0x800) ? 1 : 0,
4857 texts_freq[(status2 >> 12) & 0xF]);
4858
4859}
4860
Remy Bruno3cee5a62006-10-16 12:46:32 +02004861#ifdef CONFIG_SND_DEBUG
4862static void
Adrian Knoth0dca1792011-01-26 19:32:14 +01004863snd_hdspm_proc_read_debug(struct snd_info_entry *entry,
Remy Bruno3cee5a62006-10-16 12:46:32 +02004864 struct snd_info_buffer *buffer)
4865{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004866 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004867
4868 int j,i;
4869
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004870 for (i = 0; i < 256 /* 1024*64 */; i += j) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004871 snd_iprintf(buffer, "0x%08X: ", i);
4872 for (j = 0; j < 16; j += 4)
4873 snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
4874 snd_iprintf(buffer, "\n");
4875 }
4876}
4877#endif
4878
4879
Adrian Knoth0dca1792011-01-26 19:32:14 +01004880static void snd_hdspm_proc_ports_in(struct snd_info_entry *entry,
4881 struct snd_info_buffer *buffer)
4882{
4883 struct hdspm *hdspm = entry->private_data;
4884 int i;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004885
Adrian Knoth0dca1792011-01-26 19:32:14 +01004886 snd_iprintf(buffer, "# generated by hdspm\n");
4887
4888 for (i = 0; i < hdspm->max_channels_in; i++) {
4889 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_in[i]);
4890 }
4891}
4892
4893static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry,
4894 struct snd_info_buffer *buffer)
4895{
4896 struct hdspm *hdspm = entry->private_data;
4897 int i;
4898
4899 snd_iprintf(buffer, "# generated by hdspm\n");
4900
4901 for (i = 0; i < hdspm->max_channels_out; i++) {
4902 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_out[i]);
4903 }
4904}
4905
4906
Bill Pembertone23e7a12012-12-06 12:35:10 -05004907static void snd_hdspm_proc_init(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004908{
Takashi Iwai98274f02005-11-17 14:52:34 +01004909 struct snd_info_entry *entry;
Takashi Iwai763f3562005-06-03 11:25:34 +02004910
Adrian Knoth0dca1792011-01-26 19:32:14 +01004911 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) {
4912 switch (hdspm->io_type) {
4913 case AES32:
4914 snd_info_set_text_ops(entry, hdspm,
4915 snd_hdspm_proc_read_aes32);
4916 break;
4917 case MADI:
4918 snd_info_set_text_ops(entry, hdspm,
4919 snd_hdspm_proc_read_madi);
4920 break;
4921 case MADIface:
4922 /* snd_info_set_text_ops(entry, hdspm,
4923 snd_hdspm_proc_read_madiface); */
4924 break;
4925 case RayDAT:
4926 snd_info_set_text_ops(entry, hdspm,
4927 snd_hdspm_proc_read_raydat);
4928 break;
4929 case AIO:
4930 break;
4931 }
4932 }
4933
4934 if (!snd_card_proc_new(hdspm->card, "ports.in", &entry)) {
4935 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_in);
4936 }
4937
4938 if (!snd_card_proc_new(hdspm->card, "ports.out", &entry)) {
4939 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_out);
4940 }
4941
Remy Bruno3cee5a62006-10-16 12:46:32 +02004942#ifdef CONFIG_SND_DEBUG
4943 /* debug file to read all hdspm registers */
4944 if (!snd_card_proc_new(hdspm->card, "debug", &entry))
4945 snd_info_set_text_ops(entry, hdspm,
4946 snd_hdspm_proc_read_debug);
4947#endif
Takashi Iwai763f3562005-06-03 11:25:34 +02004948}
4949
4950/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01004951 hdspm intitialize
Takashi Iwai763f3562005-06-03 11:25:34 +02004952 ------------------------------------------------------------*/
4953
Takashi Iwai98274f02005-11-17 14:52:34 +01004954static int snd_hdspm_set_defaults(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004955{
Takashi Iwai763f3562005-06-03 11:25:34 +02004956 /* ASSUMPTION: hdspm->lock is either held, or there is no need to
Joe Perches561de312007-12-18 13:13:47 +01004957 hold it (e.g. during module initialization).
Adrian Knoth0dca1792011-01-26 19:32:14 +01004958 */
Takashi Iwai763f3562005-06-03 11:25:34 +02004959
4960 /* set defaults: */
4961
Adrian Knoth0dca1792011-01-26 19:32:14 +01004962 hdspm->settings_register = 0;
4963
4964 switch (hdspm->io_type) {
4965 case MADI:
4966 case MADIface:
4967 hdspm->control_register =
4968 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
4969 break;
4970
4971 case RayDAT:
4972 case AIO:
4973 hdspm->settings_register = 0x1 + 0x1000;
4974 /* Magic values are: LAT_0, LAT_2, Master, freq1, tx64ch, inp_0,
4975 * line_out */
4976 hdspm->control_register =
4977 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
4978 break;
4979
4980 case AES32:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004981 hdspm->control_register =
4982 HDSPM_ClockModeMaster | /* Master Cloack Mode on */
Adrian Knoth0dca1792011-01-26 19:32:14 +01004983 hdspm_encode_latency(7) | /* latency max=8192samples */
Remy Bruno3cee5a62006-10-16 12:46:32 +02004984 HDSPM_SyncRef0 | /* AES1 is syncclock */
4985 HDSPM_LineOut | /* Analog output in */
4986 HDSPM_Professional; /* Professional mode */
Adrian Knoth0dca1792011-01-26 19:32:14 +01004987 break;
4988 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004989
4990 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
4991
Adrian Knoth0dca1792011-01-26 19:32:14 +01004992 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01004993 /* No control2 register for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +02004994#ifdef SNDRV_BIG_ENDIAN
Remy Brunoffb2c3c2007-03-07 19:08:46 +01004995 hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004996#else
Remy Brunoffb2c3c2007-03-07 19:08:46 +01004997 hdspm->control2_register = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02004998#endif
4999
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005000 hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
5001 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005002 hdspm_compute_period_size(hdspm);
5003
5004 /* silence everything */
5005
5006 all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
5007
Adrian Knoth0dca1792011-01-26 19:32:14 +01005008 if (hdspm->io_type == AIO || hdspm->io_type == RayDAT) {
5009 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
Takashi Iwai763f3562005-06-03 11:25:34 +02005010 }
5011
5012 /* set a default rate so that the channel map is set up. */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005013 hdspm_set_rate(hdspm, 48000, 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02005014
5015 return 0;
5016}
5017
5018
5019/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005020 interrupt
Takashi Iwai763f3562005-06-03 11:25:34 +02005021 ------------------------------------------------------------*/
5022
David Howells7d12e782006-10-05 14:55:46 +01005023static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02005024{
Takashi Iwai98274f02005-11-17 14:52:34 +01005025 struct hdspm *hdspm = (struct hdspm *) dev_id;
Takashi Iwai763f3562005-06-03 11:25:34 +02005026 unsigned int status;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005027 int i, audio, midi, schedule = 0;
5028 /* cycles_t now; */
Takashi Iwai763f3562005-06-03 11:25:34 +02005029
5030 status = hdspm_read(hdspm, HDSPM_statusRegister);
5031
5032 audio = status & HDSPM_audioIRQPending;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005033 midi = status & (HDSPM_midi0IRQPending | HDSPM_midi1IRQPending |
5034 HDSPM_midi2IRQPending | HDSPM_midi3IRQPending);
Takashi Iwai763f3562005-06-03 11:25:34 +02005035
Adrian Knoth0dca1792011-01-26 19:32:14 +01005036 /* now = get_cycles(); */
5037 /**
5038 * LAT_2..LAT_0 period counter (win) counter (mac)
5039 * 6 4096 ~256053425 ~514672358
5040 * 5 2048 ~128024983 ~257373821
5041 * 4 1024 ~64023706 ~128718089
5042 * 3 512 ~32005945 ~64385999
5043 * 2 256 ~16003039 ~32260176
5044 * 1 128 ~7998738 ~16194507
5045 * 0 64 ~3998231 ~8191558
5046 **/
5047 /*
5048 snd_printk(KERN_INFO "snd_hdspm_interrupt %llu @ %llx\n",
5049 now-hdspm->last_interrupt, status & 0xFFC0);
5050 hdspm->last_interrupt = now;
5051 */
5052
5053 if (!audio && !midi)
Takashi Iwai763f3562005-06-03 11:25:34 +02005054 return IRQ_NONE;
5055
5056 hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
5057 hdspm->irq_count++;
5058
Takashi Iwai763f3562005-06-03 11:25:34 +02005059
5060 if (audio) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005061 if (hdspm->capture_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005062 snd_pcm_period_elapsed(hdspm->capture_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005063
5064 if (hdspm->playback_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005065 snd_pcm_period_elapsed(hdspm->playback_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005066 }
5067
Adrian Knoth0dca1792011-01-26 19:32:14 +01005068 if (midi) {
5069 i = 0;
5070 while (i < hdspm->midiPorts) {
5071 if ((hdspm_read(hdspm,
5072 hdspm->midi[i].statusIn) & 0xff) &&
5073 (status & hdspm->midi[i].irq)) {
5074 /* we disable interrupts for this input until
5075 * processing is done
5076 */
5077 hdspm->control_register &= ~hdspm->midi[i].ie;
5078 hdspm_write(hdspm, HDSPM_controlRegister,
5079 hdspm->control_register);
5080 hdspm->midi[i].pending = 1;
5081 schedule = 1;
5082 }
5083
5084 i++;
5085 }
5086
5087 if (schedule)
5088 tasklet_hi_schedule(&hdspm->midi_tasklet);
Takashi Iwai763f3562005-06-03 11:25:34 +02005089 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005090
Takashi Iwai763f3562005-06-03 11:25:34 +02005091 return IRQ_HANDLED;
5092}
5093
5094/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005095 pcm interface
Takashi Iwai763f3562005-06-03 11:25:34 +02005096 ------------------------------------------------------------*/
5097
5098
Adrian Knoth0dca1792011-01-26 19:32:14 +01005099static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream
5100 *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005101{
Takashi Iwai98274f02005-11-17 14:52:34 +01005102 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005103 return hdspm_hw_pointer(hdspm);
5104}
5105
Takashi Iwai763f3562005-06-03 11:25:34 +02005106
Takashi Iwai98274f02005-11-17 14:52:34 +01005107static int snd_hdspm_reset(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005108{
Takashi Iwai98274f02005-11-17 14:52:34 +01005109 struct snd_pcm_runtime *runtime = substream->runtime;
5110 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5111 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005112
5113 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5114 other = hdspm->capture_substream;
5115 else
5116 other = hdspm->playback_substream;
5117
5118 if (hdspm->running)
5119 runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
5120 else
5121 runtime->status->hw_ptr = 0;
5122 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005123 struct snd_pcm_substream *s;
5124 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01005125 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005126 if (s == other) {
5127 oruntime->status->hw_ptr =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005128 runtime->status->hw_ptr;
Takashi Iwai763f3562005-06-03 11:25:34 +02005129 break;
5130 }
5131 }
5132 }
5133 return 0;
5134}
5135
Takashi Iwai98274f02005-11-17 14:52:34 +01005136static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
5137 struct snd_pcm_hw_params *params)
Takashi Iwai763f3562005-06-03 11:25:34 +02005138{
Takashi Iwai98274f02005-11-17 14:52:34 +01005139 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005140 int err;
5141 int i;
5142 pid_t this_pid;
5143 pid_t other_pid;
Takashi Iwai763f3562005-06-03 11:25:34 +02005144
5145 spin_lock_irq(&hdspm->lock);
5146
5147 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5148 this_pid = hdspm->playback_pid;
5149 other_pid = hdspm->capture_pid;
5150 } else {
5151 this_pid = hdspm->capture_pid;
5152 other_pid = hdspm->playback_pid;
5153 }
5154
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005155 if (other_pid > 0 && this_pid != other_pid) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005156
5157 /* The other stream is open, and not by the same
5158 task as this one. Make sure that the parameters
5159 that matter are the same.
Adrian Knoth0dca1792011-01-26 19:32:14 +01005160 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005161
5162 if (params_rate(params) != hdspm->system_sample_rate) {
5163 spin_unlock_irq(&hdspm->lock);
5164 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005165 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005166 return -EBUSY;
5167 }
5168
5169 if (params_period_size(params) != hdspm->period_bytes / 4) {
5170 spin_unlock_irq(&hdspm->lock);
5171 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005172 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005173 return -EBUSY;
5174 }
5175
5176 }
5177 /* We're fine. */
5178 spin_unlock_irq(&hdspm->lock);
5179
5180 /* how to make sure that the rate matches an externally-set one ? */
5181
5182 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005183 err = hdspm_set_rate(hdspm, params_rate(params), 0);
5184 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005185 snd_printk(KERN_INFO "err on hdspm_set_rate: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005186 spin_unlock_irq(&hdspm->lock);
5187 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005188 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005189 return err;
5190 }
5191 spin_unlock_irq(&hdspm->lock);
5192
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005193 err = hdspm_set_interrupt_interval(hdspm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005194 params_period_size(params));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005195 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005196 snd_printk(KERN_INFO "err on hdspm_set_interrupt_interval: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005197 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005198 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005199 return err;
5200 }
5201
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005202 /* Memory allocation, takashi's method, dont know if we should
5203 * spinlock
5204 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005205 /* malloc all buffer even if not enabled to get sure */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005206 /* Update for MADI rev 204: we need to allocate for all channels,
5207 * otherwise it doesn't work at 96kHz */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005208
Takashi Iwai763f3562005-06-03 11:25:34 +02005209 err =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005210 snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
5211 if (err < 0) {
5212 snd_printk(KERN_INFO "err on snd_pcm_lib_malloc_pages: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005213 return err;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005214 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005215
Takashi Iwai763f3562005-06-03 11:25:34 +02005216 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5217
Takashi Iwai77a23f22008-08-21 13:00:13 +02005218 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferOut,
Takashi Iwai763f3562005-06-03 11:25:34 +02005219 params_channels(params));
5220
5221 for (i = 0; i < params_channels(params); ++i)
5222 snd_hdspm_enable_out(hdspm, i, 1);
5223
5224 hdspm->playback_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005225 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005226 snd_printdd("Allocated sample buffer for playback at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005227 hdspm->playback_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005228 } else {
Takashi Iwai77a23f22008-08-21 13:00:13 +02005229 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn,
Takashi Iwai763f3562005-06-03 11:25:34 +02005230 params_channels(params));
5231
5232 for (i = 0; i < params_channels(params); ++i)
5233 snd_hdspm_enable_in(hdspm, i, 1);
5234
5235 hdspm->capture_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005236 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005237 snd_printdd("Allocated sample buffer for capture at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005238 hdspm->capture_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005239 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005240
Remy Bruno3cee5a62006-10-16 12:46:32 +02005241 /*
5242 snd_printdd("Allocated sample buffer for %s at 0x%08X\n",
5243 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5244 "playback" : "capture",
Takashi Iwai77a23f22008-08-21 13:00:13 +02005245 snd_pcm_sgbuf_get_addr(substream, 0));
Adrian Knoth0dca1792011-01-26 19:32:14 +01005246 */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005247 /*
Adrian Knoth0dca1792011-01-26 19:32:14 +01005248 snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n",
5249 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5250 "playback" : "capture",
5251 params_rate(params), params_channels(params),
5252 params_buffer_size(params));
5253 */
5254
5255
5256 /* Switch to native float format if requested */
5257 if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) {
5258 if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT))
5259 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE float format.\n");
5260
5261 hdspm->control_register |= HDSPe_FLOAT_FORMAT;
5262 } else if (SNDRV_PCM_FORMAT_S32_LE == params_format(params)) {
5263 if (hdspm->control_register & HDSPe_FLOAT_FORMAT)
5264 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE integer format.\n");
5265
5266 hdspm->control_register &= ~HDSPe_FLOAT_FORMAT;
5267 }
5268 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5269
Takashi Iwai763f3562005-06-03 11:25:34 +02005270 return 0;
5271}
5272
Takashi Iwai98274f02005-11-17 14:52:34 +01005273static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005274{
5275 int i;
Takashi Iwai98274f02005-11-17 14:52:34 +01005276 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005277
5278 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5279
Adrian Knoth0dca1792011-01-26 19:32:14 +01005280 /* params_channels(params) should be enough,
Takashi Iwai763f3562005-06-03 11:25:34 +02005281 but to get sure in case of error */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005282 for (i = 0; i < hdspm->max_channels_out; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005283 snd_hdspm_enable_out(hdspm, i, 0);
5284
5285 hdspm->playback_buffer = NULL;
5286 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005287 for (i = 0; i < hdspm->max_channels_in; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005288 snd_hdspm_enable_in(hdspm, i, 0);
5289
5290 hdspm->capture_buffer = NULL;
5291
5292 }
5293
5294 snd_pcm_lib_free_pages(substream);
5295
5296 return 0;
5297}
5298
Adrian Knoth0dca1792011-01-26 19:32:14 +01005299
Takashi Iwai98274f02005-11-17 14:52:34 +01005300static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005301 struct snd_pcm_channel_info *info)
Takashi Iwai763f3562005-06-03 11:25:34 +02005302{
Takashi Iwai98274f02005-11-17 14:52:34 +01005303 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005304
Adrian Knoth0dca1792011-01-26 19:32:14 +01005305 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5306 if (snd_BUG_ON(info->channel >= hdspm->max_channels_out)) {
5307 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel out of range (%d)\n", info->channel);
5308 return -EINVAL;
5309 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005310
Adrian Knoth0dca1792011-01-26 19:32:14 +01005311 if (hdspm->channel_map_out[info->channel] < 0) {
5312 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel %d mapped out\n", info->channel);
5313 return -EINVAL;
5314 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005315
Adrian Knoth0dca1792011-01-26 19:32:14 +01005316 info->offset = hdspm->channel_map_out[info->channel] *
5317 HDSPM_CHANNEL_BUFFER_BYTES;
5318 } else {
5319 if (snd_BUG_ON(info->channel >= hdspm->max_channels_in)) {
5320 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel out of range (%d)\n", info->channel);
5321 return -EINVAL;
5322 }
5323
5324 if (hdspm->channel_map_in[info->channel] < 0) {
5325 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel %d mapped out\n", info->channel);
5326 return -EINVAL;
5327 }
5328
5329 info->offset = hdspm->channel_map_in[info->channel] *
5330 HDSPM_CHANNEL_BUFFER_BYTES;
5331 }
5332
Takashi Iwai763f3562005-06-03 11:25:34 +02005333 info->first = 0;
5334 info->step = 32;
5335 return 0;
5336}
5337
Adrian Knoth0dca1792011-01-26 19:32:14 +01005338
Takashi Iwai98274f02005-11-17 14:52:34 +01005339static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005340 unsigned int cmd, void *arg)
Takashi Iwai763f3562005-06-03 11:25:34 +02005341{
5342 switch (cmd) {
5343 case SNDRV_PCM_IOCTL1_RESET:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005344 return snd_hdspm_reset(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005345
5346 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Adrian Knoth0dca1792011-01-26 19:32:14 +01005347 {
5348 struct snd_pcm_channel_info *info = arg;
5349 return snd_hdspm_channel_info(substream, info);
5350 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005351 default:
5352 break;
5353 }
5354
5355 return snd_pcm_lib_ioctl(substream, cmd, arg);
5356}
5357
Takashi Iwai98274f02005-11-17 14:52:34 +01005358static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
Takashi Iwai763f3562005-06-03 11:25:34 +02005359{
Takashi Iwai98274f02005-11-17 14:52:34 +01005360 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5361 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005362 int running;
5363
5364 spin_lock(&hdspm->lock);
5365 running = hdspm->running;
5366 switch (cmd) {
5367 case SNDRV_PCM_TRIGGER_START:
5368 running |= 1 << substream->stream;
5369 break;
5370 case SNDRV_PCM_TRIGGER_STOP:
5371 running &= ~(1 << substream->stream);
5372 break;
5373 default:
5374 snd_BUG();
5375 spin_unlock(&hdspm->lock);
5376 return -EINVAL;
5377 }
5378 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5379 other = hdspm->capture_substream;
5380 else
5381 other = hdspm->playback_substream;
5382
5383 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005384 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01005385 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005386 if (s == other) {
5387 snd_pcm_trigger_done(s, substream);
5388 if (cmd == SNDRV_PCM_TRIGGER_START)
5389 running |= 1 << s->stream;
5390 else
5391 running &= ~(1 << s->stream);
5392 goto _ok;
5393 }
5394 }
5395 if (cmd == SNDRV_PCM_TRIGGER_START) {
5396 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005397 && substream->stream ==
5398 SNDRV_PCM_STREAM_CAPTURE)
Takashi Iwai763f3562005-06-03 11:25:34 +02005399 hdspm_silence_playback(hdspm);
5400 } else {
5401 if (running &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01005402 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Takashi Iwai763f3562005-06-03 11:25:34 +02005403 hdspm_silence_playback(hdspm);
5404 }
5405 } else {
5406 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
5407 hdspm_silence_playback(hdspm);
5408 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005409_ok:
Takashi Iwai763f3562005-06-03 11:25:34 +02005410 snd_pcm_trigger_done(substream, substream);
5411 if (!hdspm->running && running)
5412 hdspm_start_audio(hdspm);
5413 else if (hdspm->running && !running)
5414 hdspm_stop_audio(hdspm);
5415 hdspm->running = running;
5416 spin_unlock(&hdspm->lock);
5417
5418 return 0;
5419}
5420
Takashi Iwai98274f02005-11-17 14:52:34 +01005421static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005422{
5423 return 0;
5424}
5425
Takashi Iwai98274f02005-11-17 14:52:34 +01005426static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005427 .info = (SNDRV_PCM_INFO_MMAP |
5428 SNDRV_PCM_INFO_MMAP_VALID |
5429 SNDRV_PCM_INFO_NONINTERLEAVED |
5430 SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
5431 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5432 .rates = (SNDRV_PCM_RATE_32000 |
5433 SNDRV_PCM_RATE_44100 |
5434 SNDRV_PCM_RATE_48000 |
5435 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005436 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5437 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ),
Takashi Iwai763f3562005-06-03 11:25:34 +02005438 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005439 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005440 .channels_min = 1,
5441 .channels_max = HDSPM_MAX_CHANNELS,
5442 .buffer_bytes_max =
5443 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
Adrian Knoth1b6fa102011-08-15 00:22:51 +02005444 .period_bytes_min = (32 * 4),
Takashi Iwai52e6fb42011-08-15 10:40:59 +02005445 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005446 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005447 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005448 .fifo_size = 0
5449};
5450
Takashi Iwai98274f02005-11-17 14:52:34 +01005451static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005452 .info = (SNDRV_PCM_INFO_MMAP |
5453 SNDRV_PCM_INFO_MMAP_VALID |
5454 SNDRV_PCM_INFO_NONINTERLEAVED |
5455 SNDRV_PCM_INFO_SYNC_START),
5456 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5457 .rates = (SNDRV_PCM_RATE_32000 |
5458 SNDRV_PCM_RATE_44100 |
5459 SNDRV_PCM_RATE_48000 |
5460 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005461 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5462 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
Takashi Iwai763f3562005-06-03 11:25:34 +02005463 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005464 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005465 .channels_min = 1,
5466 .channels_max = HDSPM_MAX_CHANNELS,
5467 .buffer_bytes_max =
5468 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
Adrian Knoth1b6fa102011-08-15 00:22:51 +02005469 .period_bytes_min = (32 * 4),
Takashi Iwai52e6fb42011-08-15 10:40:59 +02005470 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005471 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005472 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005473 .fifo_size = 0
5474};
5475
Adrian Knoth0dca1792011-01-26 19:32:14 +01005476static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
5477 struct snd_pcm_hw_rule *rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005478{
Takashi Iwai98274f02005-11-17 14:52:34 +01005479 struct hdspm *hdspm = rule->private;
5480 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005481 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005482 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005483 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5484
Adrian Knoth0dca1792011-01-26 19:32:14 +01005485 if (r->min > 96000 && r->max <= 192000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005486 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005487 .min = hdspm->qs_in_channels,
5488 .max = hdspm->qs_in_channels,
5489 .integer = 1,
5490 };
5491 return snd_interval_refine(c, &t);
5492 } else if (r->min > 48000 && r->max <= 96000) {
5493 struct snd_interval t = {
5494 .min = hdspm->ds_in_channels,
5495 .max = hdspm->ds_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005496 .integer = 1,
5497 };
5498 return snd_interval_refine(c, &t);
5499 } else if (r->max < 64000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005500 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005501 .min = hdspm->ss_in_channels,
5502 .max = hdspm->ss_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005503 .integer = 1,
5504 };
5505 return snd_interval_refine(c, &t);
5506 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005507
Takashi Iwai763f3562005-06-03 11:25:34 +02005508 return 0;
5509}
5510
Adrian Knoth0dca1792011-01-26 19:32:14 +01005511static int snd_hdspm_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
Takashi Iwai98274f02005-11-17 14:52:34 +01005512 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005513{
Takashi Iwai98274f02005-11-17 14:52:34 +01005514 struct hdspm *hdspm = rule->private;
5515 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005516 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005517 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005518 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5519
Adrian Knoth0dca1792011-01-26 19:32:14 +01005520 if (r->min > 96000 && r->max <= 192000) {
5521 struct snd_interval t = {
5522 .min = hdspm->qs_out_channels,
5523 .max = hdspm->qs_out_channels,
5524 .integer = 1,
5525 };
5526 return snd_interval_refine(c, &t);
5527 } else if (r->min > 48000 && r->max <= 96000) {
5528 struct snd_interval t = {
5529 .min = hdspm->ds_out_channels,
5530 .max = hdspm->ds_out_channels,
5531 .integer = 1,
5532 };
5533 return snd_interval_refine(c, &t);
5534 } else if (r->max < 64000) {
5535 struct snd_interval t = {
5536 .min = hdspm->ss_out_channels,
5537 .max = hdspm->ss_out_channels,
5538 .integer = 1,
5539 };
5540 return snd_interval_refine(c, &t);
5541 } else {
5542 }
5543 return 0;
5544}
5545
5546static int snd_hdspm_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
5547 struct snd_pcm_hw_rule * rule)
5548{
5549 struct hdspm *hdspm = rule->private;
5550 struct snd_interval *c =
5551 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5552 struct snd_interval *r =
5553 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5554
5555 if (c->min >= hdspm->ss_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005556 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005557 .min = 32000,
5558 .max = 48000,
5559 .integer = 1,
5560 };
5561 return snd_interval_refine(r, &t);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005562 } else if (c->max <= hdspm->qs_in_channels) {
5563 struct snd_interval t = {
5564 .min = 128000,
5565 .max = 192000,
5566 .integer = 1,
5567 };
5568 return snd_interval_refine(r, &t);
5569 } else if (c->max <= hdspm->ds_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005570 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005571 .min = 64000,
5572 .max = 96000,
5573 .integer = 1,
5574 };
Takashi Iwai763f3562005-06-03 11:25:34 +02005575 return snd_interval_refine(r, &t);
5576 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005577
5578 return 0;
5579}
5580static int snd_hdspm_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
5581 struct snd_pcm_hw_rule *rule)
5582{
5583 struct hdspm *hdspm = rule->private;
5584 struct snd_interval *c =
5585 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5586 struct snd_interval *r =
5587 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5588
5589 if (c->min >= hdspm->ss_out_channels) {
5590 struct snd_interval t = {
5591 .min = 32000,
5592 .max = 48000,
5593 .integer = 1,
5594 };
5595 return snd_interval_refine(r, &t);
5596 } else if (c->max <= hdspm->qs_out_channels) {
5597 struct snd_interval t = {
5598 .min = 128000,
5599 .max = 192000,
5600 .integer = 1,
5601 };
5602 return snd_interval_refine(r, &t);
5603 } else if (c->max <= hdspm->ds_out_channels) {
5604 struct snd_interval t = {
5605 .min = 64000,
5606 .max = 96000,
5607 .integer = 1,
5608 };
5609 return snd_interval_refine(r, &t);
5610 }
5611
Takashi Iwai763f3562005-06-03 11:25:34 +02005612 return 0;
5613}
5614
Adrian Knoth0dca1792011-01-26 19:32:14 +01005615static int snd_hdspm_hw_rule_in_channels(struct snd_pcm_hw_params *params,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005616 struct snd_pcm_hw_rule *rule)
5617{
5618 unsigned int list[3];
5619 struct hdspm *hdspm = rule->private;
5620 struct snd_interval *c = hw_param_interval(params,
5621 SNDRV_PCM_HW_PARAM_CHANNELS);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005622
5623 list[0] = hdspm->qs_in_channels;
5624 list[1] = hdspm->ds_in_channels;
5625 list[2] = hdspm->ss_in_channels;
5626 return snd_interval_list(c, 3, list, 0);
5627}
5628
5629static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params,
5630 struct snd_pcm_hw_rule *rule)
5631{
5632 unsigned int list[3];
5633 struct hdspm *hdspm = rule->private;
5634 struct snd_interval *c = hw_param_interval(params,
5635 SNDRV_PCM_HW_PARAM_CHANNELS);
5636
5637 list[0] = hdspm->qs_out_channels;
5638 list[1] = hdspm->ds_out_channels;
5639 list[2] = hdspm->ss_out_channels;
5640 return snd_interval_list(c, 3, list, 0);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005641}
5642
5643
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005644static unsigned int hdspm_aes32_sample_rates[] = {
5645 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000
5646};
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005647
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005648static struct snd_pcm_hw_constraint_list
5649hdspm_hw_constraints_aes32_sample_rates = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005650 .count = ARRAY_SIZE(hdspm_aes32_sample_rates),
5651 .list = hdspm_aes32_sample_rates,
5652 .mask = 0
5653};
5654
Takashi Iwai98274f02005-11-17 14:52:34 +01005655static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005656{
Takashi Iwai98274f02005-11-17 14:52:34 +01005657 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5658 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02005659
Takashi Iwai763f3562005-06-03 11:25:34 +02005660 spin_lock_irq(&hdspm->lock);
5661
5662 snd_pcm_set_sync(substream);
5663
Adrian Knoth0dca1792011-01-26 19:32:14 +01005664
Takashi Iwai763f3562005-06-03 11:25:34 +02005665 runtime->hw = snd_hdspm_playback_subinfo;
5666
5667 if (hdspm->capture_substream == NULL)
5668 hdspm_stop_audio(hdspm);
5669
5670 hdspm->playback_pid = current->pid;
5671 hdspm->playback_substream = substream;
5672
5673 spin_unlock_irq(&hdspm->lock);
5674
5675 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Takashi Iwaid8776812011-08-15 10:45:42 +02005676 snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005677
Adrian Knoth0dca1792011-01-26 19:32:14 +01005678 switch (hdspm->io_type) {
5679 case AIO:
5680 case RayDAT:
Takashi Iwaid8776812011-08-15 10:45:42 +02005681 snd_pcm_hw_constraint_minmax(runtime,
5682 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5683 32, 4096);
5684 /* RayDAT & AIO have a fixed buffer of 16384 samples per channel */
5685 snd_pcm_hw_constraint_minmax(runtime,
5686 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
5687 16384, 16384);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005688 break;
5689
5690 default:
Takashi Iwaid8776812011-08-15 10:45:42 +02005691 snd_pcm_hw_constraint_minmax(runtime,
5692 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5693 64, 8192);
5694 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005695 }
5696
5697 if (AES32 == hdspm->io_type) {
Takashi Iwai3fa9e3d2011-08-15 10:42:23 +02005698 runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005699 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
5700 &hdspm_hw_constraints_aes32_sample_rates);
5701 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005702 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005703 snd_hdspm_hw_rule_rate_out_channels, hdspm,
5704 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005705 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01005706
5707 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5708 snd_hdspm_hw_rule_out_channels, hdspm,
5709 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
5710
5711 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5712 snd_hdspm_hw_rule_out_channels_rate, hdspm,
5713 SNDRV_PCM_HW_PARAM_RATE, -1);
5714
Takashi Iwai763f3562005-06-03 11:25:34 +02005715 return 0;
5716}
5717
Takashi Iwai98274f02005-11-17 14:52:34 +01005718static int snd_hdspm_playback_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005719{
Takashi Iwai98274f02005-11-17 14:52:34 +01005720 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005721
5722 spin_lock_irq(&hdspm->lock);
5723
5724 hdspm->playback_pid = -1;
5725 hdspm->playback_substream = NULL;
5726
5727 spin_unlock_irq(&hdspm->lock);
5728
5729 return 0;
5730}
5731
5732
Takashi Iwai98274f02005-11-17 14:52:34 +01005733static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005734{
Takashi Iwai98274f02005-11-17 14:52:34 +01005735 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5736 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02005737
5738 spin_lock_irq(&hdspm->lock);
5739 snd_pcm_set_sync(substream);
5740 runtime->hw = snd_hdspm_capture_subinfo;
5741
5742 if (hdspm->playback_substream == NULL)
5743 hdspm_stop_audio(hdspm);
5744
5745 hdspm->capture_pid = current->pid;
5746 hdspm->capture_substream = substream;
5747
5748 spin_unlock_irq(&hdspm->lock);
5749
5750 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Takashi Iwaid8776812011-08-15 10:45:42 +02005751 snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
5752
Adrian Knoth0dca1792011-01-26 19:32:14 +01005753 switch (hdspm->io_type) {
5754 case AIO:
5755 case RayDAT:
Takashi Iwaid8776812011-08-15 10:45:42 +02005756 snd_pcm_hw_constraint_minmax(runtime,
5757 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5758 32, 4096);
5759 snd_pcm_hw_constraint_minmax(runtime,
5760 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
5761 16384, 16384);
5762 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005763
5764 default:
Takashi Iwaid8776812011-08-15 10:45:42 +02005765 snd_pcm_hw_constraint_minmax(runtime,
5766 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5767 64, 8192);
5768 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005769 }
5770
5771 if (AES32 == hdspm->io_type) {
Takashi Iwai3fa9e3d2011-08-15 10:42:23 +02005772 runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005773 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
5774 &hdspm_hw_constraints_aes32_sample_rates);
5775 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005776 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth88fabbf2011-02-23 11:43:10 +01005777 snd_hdspm_hw_rule_rate_in_channels, hdspm,
5778 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005779 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01005780
5781 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5782 snd_hdspm_hw_rule_in_channels, hdspm,
5783 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
5784
5785 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5786 snd_hdspm_hw_rule_in_channels_rate, hdspm,
5787 SNDRV_PCM_HW_PARAM_RATE, -1);
5788
Takashi Iwai763f3562005-06-03 11:25:34 +02005789 return 0;
5790}
5791
Takashi Iwai98274f02005-11-17 14:52:34 +01005792static int snd_hdspm_capture_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005793{
Takashi Iwai98274f02005-11-17 14:52:34 +01005794 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005795
5796 spin_lock_irq(&hdspm->lock);
5797
5798 hdspm->capture_pid = -1;
5799 hdspm->capture_substream = NULL;
5800
5801 spin_unlock_irq(&hdspm->lock);
5802 return 0;
5803}
5804
Adrian Knoth0dca1792011-01-26 19:32:14 +01005805static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
Takashi Iwai763f3562005-06-03 11:25:34 +02005806{
Adrian Knoth0dca1792011-01-26 19:32:14 +01005807 /* we have nothing to initialize but the call is required */
5808 return 0;
5809}
5810
5811static inline int copy_u32_le(void __user *dest, void __iomem *src)
5812{
5813 u32 val = readl(src);
5814 return copy_to_user(dest, &val, 4);
5815}
5816
5817static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
Dan Carpenter2ca595a2011-09-23 09:25:05 +03005818 unsigned int cmd, unsigned long arg)
Adrian Knoth0dca1792011-01-26 19:32:14 +01005819{
5820 void __user *argp = (void __user *)arg;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005821 struct hdspm *hdspm = hw->private_data;
Takashi Iwai98274f02005-11-17 14:52:34 +01005822 struct hdspm_mixer_ioctl mixer;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005823 struct hdspm_config info;
5824 struct hdspm_status status;
Takashi Iwai98274f02005-11-17 14:52:34 +01005825 struct hdspm_version hdspm_version;
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005826 struct hdspm_peak_rms *levels;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005827 struct hdspm_ltc ltc;
5828 unsigned int statusregister;
5829 long unsigned int s;
5830 int i = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005831
5832 switch (cmd) {
5833
Takashi Iwai763f3562005-06-03 11:25:34 +02005834 case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005835 levels = &hdspm->peak_rms;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005836 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005837 levels->input_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005838 readl(hdspm->iobase +
5839 HDSPM_MADI_INPUT_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005840 levels->playback_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005841 readl(hdspm->iobase +
5842 HDSPM_MADI_PLAYBACK_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005843 levels->output_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005844 readl(hdspm->iobase +
5845 HDSPM_MADI_OUTPUT_PEAK + i*4);
5846
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005847 levels->input_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005848 ((uint64_t) readl(hdspm->iobase +
5849 HDSPM_MADI_INPUT_RMS_H + i*4) << 32) |
5850 (uint64_t) readl(hdspm->iobase +
5851 HDSPM_MADI_INPUT_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005852 levels->playback_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005853 ((uint64_t)readl(hdspm->iobase +
5854 HDSPM_MADI_PLAYBACK_RMS_H+i*4) << 32) |
5855 (uint64_t)readl(hdspm->iobase +
5856 HDSPM_MADI_PLAYBACK_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005857 levels->output_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005858 ((uint64_t)readl(hdspm->iobase +
5859 HDSPM_MADI_OUTPUT_RMS_H + i*4) << 32) |
5860 (uint64_t)readl(hdspm->iobase +
5861 HDSPM_MADI_OUTPUT_RMS_L + i*4);
5862 }
5863
5864 if (hdspm->system_sample_rate > 96000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005865 levels->speed = qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005866 } else if (hdspm->system_sample_rate > 48000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005867 levels->speed = ds;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005868 } else {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005869 levels->speed = ss;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005870 }
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005871 levels->status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005872
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005873 s = copy_to_user(argp, levels, sizeof(struct hdspm_peak_rms));
Adrian Knoth0dca1792011-01-26 19:32:14 +01005874 if (0 != s) {
5875 /* snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu
5876 [Levels]\n", sizeof(struct hdspm_peak_rms), s);
5877 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005878 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005879 }
5880 break;
5881
5882 case SNDRV_HDSPM_IOCTL_GET_LTC:
5883 ltc.ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
5884 i = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
5885 if (i & HDSPM_TCO1_LTC_Input_valid) {
5886 switch (i & (HDSPM_TCO1_LTC_Format_LSB |
5887 HDSPM_TCO1_LTC_Format_MSB)) {
5888 case 0:
5889 ltc.format = fps_24;
5890 break;
5891 case HDSPM_TCO1_LTC_Format_LSB:
5892 ltc.format = fps_25;
5893 break;
5894 case HDSPM_TCO1_LTC_Format_MSB:
5895 ltc.format = fps_2997;
5896 break;
5897 default:
5898 ltc.format = 30;
5899 break;
5900 }
5901 if (i & HDSPM_TCO1_set_drop_frame_flag) {
5902 ltc.frame = drop_frame;
5903 } else {
5904 ltc.frame = full_frame;
5905 }
5906 } else {
5907 ltc.format = format_invalid;
5908 ltc.frame = frame_invalid;
5909 }
5910 if (i & HDSPM_TCO1_Video_Input_Format_NTSC) {
5911 ltc.input_format = ntsc;
5912 } else if (i & HDSPM_TCO1_Video_Input_Format_PAL) {
5913 ltc.input_format = pal;
5914 } else {
5915 ltc.input_format = no_video;
5916 }
5917
5918 s = copy_to_user(argp, &ltc, sizeof(struct hdspm_ltc));
5919 if (0 != s) {
5920 /*
5921 snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */
Takashi Iwai763f3562005-06-03 11:25:34 +02005922 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005923 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005924
5925 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02005926
Adrian Knoth0dca1792011-01-26 19:32:14 +01005927 case SNDRV_HDSPM_IOCTL_GET_CONFIG:
Takashi Iwai763f3562005-06-03 11:25:34 +02005928
Adrian Knoth4ab69a22011-02-23 11:43:14 +01005929 memset(&info, 0, sizeof(info));
Takashi Iwai763f3562005-06-03 11:25:34 +02005930 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005931 info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
5932 info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02005933
5934 info.system_sample_rate = hdspm->system_sample_rate;
5935 info.autosync_sample_rate =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005936 hdspm_external_sample_rate(hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005937 info.system_clock_mode = hdspm_system_clock_mode(hdspm);
5938 info.clock_source = hdspm_clock_source(hdspm);
5939 info.autosync_ref = hdspm_autosync_ref(hdspm);
Adrian Knothc9e16682012-12-03 14:55:50 +01005940 info.line_out = hdspm_toggle_setting(hdspm, HDSPM_LineOut);
Takashi Iwai763f3562005-06-03 11:25:34 +02005941 info.passthru = 0;
5942 spin_unlock_irq(&hdspm->lock);
Dan Carpenter2ca595a2011-09-23 09:25:05 +03005943 if (copy_to_user(argp, &info, sizeof(info)))
Takashi Iwai763f3562005-06-03 11:25:34 +02005944 return -EFAULT;
5945 break;
5946
Adrian Knoth0dca1792011-01-26 19:32:14 +01005947 case SNDRV_HDSPM_IOCTL_GET_STATUS:
Dan Carpenter643d6bb2011-09-23 09:24:21 +03005948 memset(&status, 0, sizeof(status));
5949
Adrian Knoth0dca1792011-01-26 19:32:14 +01005950 status.card_type = hdspm->io_type;
5951
5952 status.autosync_source = hdspm_autosync_ref(hdspm);
5953
5954 status.card_clock = 110069313433624ULL;
5955 status.master_period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
5956
5957 switch (hdspm->io_type) {
5958 case MADI:
5959 case MADIface:
5960 status.card_specific.madi.sync_wc =
5961 hdspm_wc_sync_check(hdspm);
5962 status.card_specific.madi.sync_madi =
5963 hdspm_madi_sync_check(hdspm);
5964 status.card_specific.madi.sync_tco =
5965 hdspm_tco_sync_check(hdspm);
5966 status.card_specific.madi.sync_in =
5967 hdspm_sync_in_sync_check(hdspm);
5968
5969 statusregister =
5970 hdspm_read(hdspm, HDSPM_statusRegister);
5971 status.card_specific.madi.madi_input =
5972 (statusregister & HDSPM_AB_int) ? 1 : 0;
5973 status.card_specific.madi.channel_format =
Adrian Knoth9e6ff522011-10-27 21:57:52 +02005974 (statusregister & HDSPM_RX_64ch) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005975 /* TODO: Mac driver sets it when f_s>48kHz */
5976 status.card_specific.madi.frame_format = 0;
5977
5978 default:
5979 break;
5980 }
5981
Dan Carpenter2ca595a2011-09-23 09:25:05 +03005982 if (copy_to_user(argp, &status, sizeof(status)))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005983 return -EFAULT;
5984
5985
5986 break;
5987
Takashi Iwai763f3562005-06-03 11:25:34 +02005988 case SNDRV_HDSPM_IOCTL_GET_VERSION:
Dan Carpenter643d6bb2011-09-23 09:24:21 +03005989 memset(&hdspm_version, 0, sizeof(hdspm_version));
5990
Adrian Knoth0dca1792011-01-26 19:32:14 +01005991 hdspm_version.card_type = hdspm->io_type;
5992 strncpy(hdspm_version.cardname, hdspm->card_name,
5993 sizeof(hdspm_version.cardname));
Adrian Knoth7d53a632012-01-04 14:31:16 +01005994 hdspm_version.serial = hdspm->serial;
Takashi Iwai763f3562005-06-03 11:25:34 +02005995 hdspm_version.firmware_rev = hdspm->firmware_rev;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005996 hdspm_version.addons = 0;
5997 if (hdspm->tco)
5998 hdspm_version.addons |= HDSPM_ADDON_TCO;
5999
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006000 if (copy_to_user(argp, &hdspm_version,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006001 sizeof(hdspm_version)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006002 return -EFAULT;
6003 break;
6004
6005 case SNDRV_HDSPM_IOCTL_GET_MIXER:
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006006 if (copy_from_user(&mixer, argp, sizeof(mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006007 return -EFAULT;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006008 if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006009 sizeof(struct hdspm_mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006010 return -EFAULT;
6011 break;
6012
6013 default:
6014 return -EINVAL;
6015 }
6016 return 0;
6017}
6018
Takashi Iwai98274f02005-11-17 14:52:34 +01006019static struct snd_pcm_ops snd_hdspm_playback_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006020 .open = snd_hdspm_playback_open,
6021 .close = snd_hdspm_playback_release,
6022 .ioctl = snd_hdspm_ioctl,
6023 .hw_params = snd_hdspm_hw_params,
6024 .hw_free = snd_hdspm_hw_free,
6025 .prepare = snd_hdspm_prepare,
6026 .trigger = snd_hdspm_trigger,
6027 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006028 .page = snd_pcm_sgbuf_ops_page,
6029};
6030
Takashi Iwai98274f02005-11-17 14:52:34 +01006031static struct snd_pcm_ops snd_hdspm_capture_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006032 .open = snd_hdspm_capture_open,
6033 .close = snd_hdspm_capture_release,
6034 .ioctl = snd_hdspm_ioctl,
6035 .hw_params = snd_hdspm_hw_params,
6036 .hw_free = snd_hdspm_hw_free,
6037 .prepare = snd_hdspm_prepare,
6038 .trigger = snd_hdspm_trigger,
6039 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006040 .page = snd_pcm_sgbuf_ops_page,
6041};
6042
Bill Pembertone23e7a12012-12-06 12:35:10 -05006043static int snd_hdspm_create_hwdep(struct snd_card *card,
6044 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006045{
Takashi Iwai98274f02005-11-17 14:52:34 +01006046 struct snd_hwdep *hw;
Takashi Iwai763f3562005-06-03 11:25:34 +02006047 int err;
6048
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006049 err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw);
6050 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006051 return err;
6052
6053 hdspm->hwdep = hw;
6054 hw->private_data = hdspm;
6055 strcpy(hw->name, "HDSPM hwdep interface");
6056
Adrian Knoth0dca1792011-01-26 19:32:14 +01006057 hw->ops.open = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006058 hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
Adrian Knoth8de5d6f2012-03-08 15:38:04 +01006059 hw->ops.ioctl_compat = snd_hdspm_hwdep_ioctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006060 hw->ops.release = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006061
6062 return 0;
6063}
6064
6065
6066/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01006067 memory interface
Takashi Iwai763f3562005-06-03 11:25:34 +02006068 ------------------------------------------------------------*/
Bill Pembertone23e7a12012-12-06 12:35:10 -05006069static int snd_hdspm_preallocate_memory(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006070{
6071 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01006072 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006073 size_t wanted;
6074
6075 pcm = hdspm->pcm;
6076
Remy Bruno3cee5a62006-10-16 12:46:32 +02006077 wanted = HDSPM_DMA_AREA_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02006078
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006079 err =
Takashi Iwai763f3562005-06-03 11:25:34 +02006080 snd_pcm_lib_preallocate_pages_for_all(pcm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006081 SNDRV_DMA_TYPE_DEV_SG,
Takashi Iwai763f3562005-06-03 11:25:34 +02006082 snd_dma_pci_data(hdspm->pci),
6083 wanted,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006084 wanted);
6085 if (err < 0) {
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006086 snd_printdd("Could not preallocate %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006087
6088 return err;
6089 } else
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006090 snd_printdd(" Preallocated %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006091
6092 return 0;
6093}
6094
Adrian Knoth0dca1792011-01-26 19:32:14 +01006095
6096static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +02006097 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02006098 unsigned int reg, int channels)
6099{
6100 int i;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006101
6102 /* continuous memory segment */
Takashi Iwai763f3562005-06-03 11:25:34 +02006103 for (i = 0; i < (channels * 16); i++)
6104 hdspm_write(hdspm, reg + 4 * i,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006105 snd_pcm_sgbuf_get_addr(substream, 4096 * i));
Takashi Iwai763f3562005-06-03 11:25:34 +02006106}
6107
Adrian Knoth0dca1792011-01-26 19:32:14 +01006108
Takashi Iwai763f3562005-06-03 11:25:34 +02006109/* ------------- ALSA Devices ---------------------------- */
Bill Pembertone23e7a12012-12-06 12:35:10 -05006110static int snd_hdspm_create_pcm(struct snd_card *card,
6111 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006112{
Takashi Iwai98274f02005-11-17 14:52:34 +01006113 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006114 int err;
6115
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006116 err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm);
6117 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006118 return err;
6119
6120 hdspm->pcm = pcm;
6121 pcm->private_data = hdspm;
6122 strcpy(pcm->name, hdspm->card_name);
6123
6124 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
6125 &snd_hdspm_playback_ops);
6126 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
6127 &snd_hdspm_capture_ops);
6128
6129 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
6130
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006131 err = snd_hdspm_preallocate_memory(hdspm);
6132 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006133 return err;
6134
6135 return 0;
6136}
6137
Takashi Iwai98274f02005-11-17 14:52:34 +01006138static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006139{
Adrian Knoth7c7102b2011-02-28 15:14:50 +01006140 int i;
6141
6142 for (i = 0; i < hdspm->midiPorts; i++)
6143 snd_hdspm_flush_midi_input(hdspm, i);
Takashi Iwai763f3562005-06-03 11:25:34 +02006144}
6145
Bill Pembertone23e7a12012-12-06 12:35:10 -05006146static int snd_hdspm_create_alsa_devices(struct snd_card *card,
6147 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006148{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006149 int err, i;
Takashi Iwai763f3562005-06-03 11:25:34 +02006150
6151 snd_printdd("Create card...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006152 err = snd_hdspm_create_pcm(card, hdspm);
6153 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006154 return err;
6155
Adrian Knoth0dca1792011-01-26 19:32:14 +01006156 i = 0;
6157 while (i < hdspm->midiPorts) {
6158 err = snd_hdspm_create_midi(card, hdspm, i);
6159 if (err < 0) {
6160 return err;
6161 }
6162 i++;
6163 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006164
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006165 err = snd_hdspm_create_controls(card, hdspm);
6166 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006167 return err;
6168
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006169 err = snd_hdspm_create_hwdep(card, hdspm);
6170 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006171 return err;
6172
6173 snd_printdd("proc init...\n");
6174 snd_hdspm_proc_init(hdspm);
6175
6176 hdspm->system_sample_rate = -1;
6177 hdspm->last_external_sample_rate = -1;
6178 hdspm->last_internal_sample_rate = -1;
6179 hdspm->playback_pid = -1;
6180 hdspm->capture_pid = -1;
6181 hdspm->capture_substream = NULL;
6182 hdspm->playback_substream = NULL;
6183
6184 snd_printdd("Set defaults...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006185 err = snd_hdspm_set_defaults(hdspm);
6186 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006187 return err;
6188
6189 snd_printdd("Update mixer controls...\n");
6190 hdspm_update_simple_mixer_controls(hdspm);
6191
6192 snd_printdd("Initializeing complete ???\n");
6193
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006194 err = snd_card_register(card);
6195 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006196 snd_printk(KERN_ERR "HDSPM: error registering card\n");
6197 return err;
6198 }
6199
6200 snd_printdd("... yes now\n");
6201
6202 return 0;
6203}
6204
Bill Pembertone23e7a12012-12-06 12:35:10 -05006205static int snd_hdspm_create(struct snd_card *card,
6206 struct hdspm *hdspm)
6207{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006208
Takashi Iwai763f3562005-06-03 11:25:34 +02006209 struct pci_dev *pci = hdspm->pci;
6210 int err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006211 unsigned long io_extent;
6212
6213 hdspm->irq = -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02006214 hdspm->card = card;
6215
6216 spin_lock_init(&hdspm->lock);
6217
Takashi Iwai763f3562005-06-03 11:25:34 +02006218 pci_read_config_word(hdspm->pci,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006219 PCI_CLASS_REVISION, &hdspm->firmware_rev);
Remy Bruno3cee5a62006-10-16 12:46:32 +02006220
Takashi Iwai763f3562005-06-03 11:25:34 +02006221 strcpy(card->mixername, "Xilinx FPGA");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006222 strcpy(card->driver, "HDSPM");
6223
6224 switch (hdspm->firmware_rev) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01006225 case HDSPM_RAYDAT_REV:
6226 hdspm->io_type = RayDAT;
6227 hdspm->card_name = "RME RayDAT";
6228 hdspm->midiPorts = 2;
6229 break;
6230 case HDSPM_AIO_REV:
6231 hdspm->io_type = AIO;
6232 hdspm->card_name = "RME AIO";
6233 hdspm->midiPorts = 1;
6234 break;
6235 case HDSPM_MADIFACE_REV:
6236 hdspm->io_type = MADIface;
6237 hdspm->card_name = "RME MADIface";
6238 hdspm->midiPorts = 1;
6239 break;
Adrian Knoth5027f342011-02-28 15:14:49 +01006240 default:
Adrian Knothc09403d2011-10-27 21:57:54 +02006241 if ((hdspm->firmware_rev == 0xf0) ||
6242 ((hdspm->firmware_rev >= 0xe6) &&
6243 (hdspm->firmware_rev <= 0xea))) {
6244 hdspm->io_type = AES32;
6245 hdspm->card_name = "RME AES32";
6246 hdspm->midiPorts = 2;
Adrian Knoth05c7cc92011-11-21 16:15:36 +01006247 } else if ((hdspm->firmware_rev == 0xd2) ||
Adrian Knothc09403d2011-10-27 21:57:54 +02006248 ((hdspm->firmware_rev >= 0xc8) &&
6249 (hdspm->firmware_rev <= 0xcf))) {
6250 hdspm->io_type = MADI;
6251 hdspm->card_name = "RME MADI";
6252 hdspm->midiPorts = 3;
6253 } else {
6254 snd_printk(KERN_ERR
6255 "HDSPM: unknown firmware revision %x\n",
Adrian Knoth5027f342011-02-28 15:14:49 +01006256 hdspm->firmware_rev);
Adrian Knothc09403d2011-10-27 21:57:54 +02006257 return -ENODEV;
6258 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02006259 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006260
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006261 err = pci_enable_device(pci);
6262 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006263 return err;
6264
6265 pci_set_master(hdspm->pci);
6266
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006267 err = pci_request_regions(pci, "hdspm");
6268 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006269 return err;
6270
6271 hdspm->port = pci_resource_start(pci, 0);
6272 io_extent = pci_resource_len(pci, 0);
6273
6274 snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006275 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006276
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006277 hdspm->iobase = ioremap_nocache(hdspm->port, io_extent);
6278 if (!hdspm->iobase) {
6279 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006280 "unable to remap region 0x%lx-0x%lx\n",
6281 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006282 return -EBUSY;
6283 }
6284 snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006285 (unsigned long)hdspm->iobase, hdspm->port,
6286 hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006287
6288 if (request_irq(pci->irq, snd_hdspm_interrupt,
Takashi Iwai934c2b62011-06-10 16:36:37 +02006289 IRQF_SHARED, KBUILD_MODNAME, hdspm)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006290 snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
6291 return -EBUSY;
6292 }
6293
6294 snd_printdd("use IRQ %d\n", pci->irq);
6295
6296 hdspm->irq = pci->irq;
Takashi Iwai763f3562005-06-03 11:25:34 +02006297
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006298 snd_printdd("kmalloc Mixer memory of %zd Bytes\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006299 sizeof(struct hdspm_mixer));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006300 hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL);
6301 if (!hdspm->mixer) {
6302 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006303 "unable to kmalloc Mixer memory of %d Bytes\n",
6304 (int)sizeof(struct hdspm_mixer));
Julia Lawallb17cbdd2012-08-19 09:02:54 +02006305 return -ENOMEM;
Takashi Iwai763f3562005-06-03 11:25:34 +02006306 }
6307
Adrian Knoth0dca1792011-01-26 19:32:14 +01006308 hdspm->port_names_in = NULL;
6309 hdspm->port_names_out = NULL;
6310
6311 switch (hdspm->io_type) {
6312 case AES32:
Adrian Knothd2d10a22011-02-28 15:14:47 +01006313 hdspm->ss_in_channels = hdspm->ss_out_channels = AES32_CHANNELS;
6314 hdspm->ds_in_channels = hdspm->ds_out_channels = AES32_CHANNELS;
6315 hdspm->qs_in_channels = hdspm->qs_out_channels = AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006316
6317 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6318 channel_map_aes32;
6319 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6320 channel_map_aes32;
6321 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6322 channel_map_aes32;
6323 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6324 texts_ports_aes32;
6325 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6326 texts_ports_aes32;
6327 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6328 texts_ports_aes32;
6329
Adrian Knothd2d10a22011-02-28 15:14:47 +01006330 hdspm->max_channels_out = hdspm->max_channels_in =
6331 AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006332 hdspm->port_names_in = hdspm->port_names_out =
6333 texts_ports_aes32;
6334 hdspm->channel_map_in = hdspm->channel_map_out =
6335 channel_map_aes32;
6336
Adrian Knoth0dca1792011-01-26 19:32:14 +01006337 break;
6338
6339 case MADI:
6340 case MADIface:
6341 hdspm->ss_in_channels = hdspm->ss_out_channels =
6342 MADI_SS_CHANNELS;
6343 hdspm->ds_in_channels = hdspm->ds_out_channels =
6344 MADI_DS_CHANNELS;
6345 hdspm->qs_in_channels = hdspm->qs_out_channels =
6346 MADI_QS_CHANNELS;
6347
6348 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6349 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006350 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006351 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006352 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006353 channel_map_unity_ss;
6354
6355 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6356 texts_ports_madi;
6357 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6358 texts_ports_madi;
6359 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6360 texts_ports_madi;
6361 break;
6362
6363 case AIO:
6364 if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) {
6365 snd_printk(KERN_INFO "HDSPM: AEB input board found, but not supported\n");
6366 }
6367
6368 hdspm->ss_in_channels = AIO_IN_SS_CHANNELS;
6369 hdspm->ds_in_channels = AIO_IN_DS_CHANNELS;
6370 hdspm->qs_in_channels = AIO_IN_QS_CHANNELS;
6371 hdspm->ss_out_channels = AIO_OUT_SS_CHANNELS;
6372 hdspm->ds_out_channels = AIO_OUT_DS_CHANNELS;
6373 hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS;
6374
6375 hdspm->channel_map_out_ss = channel_map_aio_out_ss;
6376 hdspm->channel_map_out_ds = channel_map_aio_out_ds;
6377 hdspm->channel_map_out_qs = channel_map_aio_out_qs;
6378
6379 hdspm->channel_map_in_ss = channel_map_aio_in_ss;
6380 hdspm->channel_map_in_ds = channel_map_aio_in_ds;
6381 hdspm->channel_map_in_qs = channel_map_aio_in_qs;
6382
6383 hdspm->port_names_in_ss = texts_ports_aio_in_ss;
6384 hdspm->port_names_out_ss = texts_ports_aio_out_ss;
6385 hdspm->port_names_in_ds = texts_ports_aio_in_ds;
6386 hdspm->port_names_out_ds = texts_ports_aio_out_ds;
6387 hdspm->port_names_in_qs = texts_ports_aio_in_qs;
6388 hdspm->port_names_out_qs = texts_ports_aio_out_qs;
6389
6390 break;
6391
6392 case RayDAT:
6393 hdspm->ss_in_channels = hdspm->ss_out_channels =
6394 RAYDAT_SS_CHANNELS;
6395 hdspm->ds_in_channels = hdspm->ds_out_channels =
6396 RAYDAT_DS_CHANNELS;
6397 hdspm->qs_in_channels = hdspm->qs_out_channels =
6398 RAYDAT_QS_CHANNELS;
6399
6400 hdspm->max_channels_in = RAYDAT_SS_CHANNELS;
6401 hdspm->max_channels_out = RAYDAT_SS_CHANNELS;
6402
6403 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6404 channel_map_raydat_ss;
6405 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6406 channel_map_raydat_ds;
6407 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6408 channel_map_raydat_qs;
6409 hdspm->channel_map_in = hdspm->channel_map_out =
6410 channel_map_raydat_ss;
6411
6412 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6413 texts_ports_raydat_ss;
6414 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6415 texts_ports_raydat_ds;
6416 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6417 texts_ports_raydat_qs;
6418
6419
6420 break;
6421
6422 }
6423
6424 /* TCO detection */
6425 switch (hdspm->io_type) {
6426 case AIO:
6427 case RayDAT:
6428 if (hdspm_read(hdspm, HDSPM_statusRegister2) &
6429 HDSPM_s2_tco_detect) {
6430 hdspm->midiPorts++;
6431 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6432 GFP_KERNEL);
6433 if (NULL != hdspm->tco) {
6434 hdspm_tco_write(hdspm);
6435 }
6436 snd_printk(KERN_INFO "HDSPM: AIO/RayDAT TCO module found\n");
6437 } else {
6438 hdspm->tco = NULL;
6439 }
6440 break;
6441
6442 case MADI:
6443 if (hdspm_read(hdspm, HDSPM_statusRegister) & HDSPM_tco_detect) {
6444 hdspm->midiPorts++;
6445 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6446 GFP_KERNEL);
6447 if (NULL != hdspm->tco) {
6448 hdspm_tco_write(hdspm);
6449 }
6450 snd_printk(KERN_INFO "HDSPM: MADI TCO module found\n");
6451 } else {
6452 hdspm->tco = NULL;
6453 }
6454 break;
6455
6456 default:
6457 hdspm->tco = NULL;
6458 }
6459
6460 /* texts */
6461 switch (hdspm->io_type) {
6462 case AES32:
6463 if (hdspm->tco) {
6464 hdspm->texts_autosync = texts_autosync_aes_tco;
6465 hdspm->texts_autosync_items = 10;
6466 } else {
6467 hdspm->texts_autosync = texts_autosync_aes;
6468 hdspm->texts_autosync_items = 9;
6469 }
6470 break;
6471
6472 case MADI:
6473 if (hdspm->tco) {
6474 hdspm->texts_autosync = texts_autosync_madi_tco;
6475 hdspm->texts_autosync_items = 4;
6476 } else {
6477 hdspm->texts_autosync = texts_autosync_madi;
6478 hdspm->texts_autosync_items = 3;
6479 }
6480 break;
6481
6482 case MADIface:
6483
6484 break;
6485
6486 case RayDAT:
6487 if (hdspm->tco) {
6488 hdspm->texts_autosync = texts_autosync_raydat_tco;
6489 hdspm->texts_autosync_items = 9;
6490 } else {
6491 hdspm->texts_autosync = texts_autosync_raydat;
6492 hdspm->texts_autosync_items = 8;
6493 }
6494 break;
6495
6496 case AIO:
6497 if (hdspm->tco) {
6498 hdspm->texts_autosync = texts_autosync_aio_tco;
6499 hdspm->texts_autosync_items = 6;
6500 } else {
6501 hdspm->texts_autosync = texts_autosync_aio;
6502 hdspm->texts_autosync_items = 5;
6503 }
6504 break;
6505
6506 }
6507
6508 tasklet_init(&hdspm->midi_tasklet,
6509 hdspm_midi_tasklet, (unsigned long) hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006510
Adrian Knothf7de8ba2012-01-10 20:58:40 +01006511
6512 if (hdspm->io_type != MADIface) {
6513 hdspm->serial = (hdspm_read(hdspm,
6514 HDSPM_midiStatusIn0)>>8) & 0xFFFFFF;
6515 /* id contains either a user-provided value or the default
6516 * NULL. If it's the default, we're safe to
6517 * fill card->id with the serial number.
6518 *
6519 * If the serial number is 0xFFFFFF, then we're dealing with
6520 * an old PCI revision that comes without a sane number. In
6521 * this case, we don't set card->id to avoid collisions
6522 * when running with multiple cards.
6523 */
6524 if (NULL == id[hdspm->dev] && hdspm->serial != 0xFFFFFF) {
6525 sprintf(card->id, "HDSPMx%06x", hdspm->serial);
6526 snd_card_set_id(card, card->id);
6527 }
6528 }
6529
Takashi Iwai763f3562005-06-03 11:25:34 +02006530 snd_printdd("create alsa devices.\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006531 err = snd_hdspm_create_alsa_devices(card, hdspm);
6532 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006533 return err;
6534
6535 snd_hdspm_initialize_midi_flush(hdspm);
6536
6537 return 0;
6538}
6539
Adrian Knoth0dca1792011-01-26 19:32:14 +01006540
Takashi Iwai98274f02005-11-17 14:52:34 +01006541static int snd_hdspm_free(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006542{
6543
6544 if (hdspm->port) {
6545
6546 /* stop th audio, and cancel all interrupts */
6547 hdspm->control_register &=
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006548 ~(HDSPM_Start | HDSPM_AudioInterruptEnable |
Adrian Knoth0dca1792011-01-26 19:32:14 +01006549 HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable |
6550 HDSPM_Midi2InterruptEnable | HDSPM_Midi3InterruptEnable);
Takashi Iwai763f3562005-06-03 11:25:34 +02006551 hdspm_write(hdspm, HDSPM_controlRegister,
6552 hdspm->control_register);
6553 }
6554
6555 if (hdspm->irq >= 0)
6556 free_irq(hdspm->irq, (void *) hdspm);
6557
Jesper Juhlfc584222005-10-24 15:11:28 +02006558 kfree(hdspm->mixer);
Takashi Iwai763f3562005-06-03 11:25:34 +02006559
6560 if (hdspm->iobase)
6561 iounmap(hdspm->iobase);
6562
Takashi Iwai763f3562005-06-03 11:25:34 +02006563 if (hdspm->port)
6564 pci_release_regions(hdspm->pci);
6565
6566 pci_disable_device(hdspm->pci);
6567 return 0;
6568}
6569
Adrian Knoth0dca1792011-01-26 19:32:14 +01006570
Takashi Iwai98274f02005-11-17 14:52:34 +01006571static void snd_hdspm_card_free(struct snd_card *card)
Takashi Iwai763f3562005-06-03 11:25:34 +02006572{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006573 struct hdspm *hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006574
6575 if (hdspm)
6576 snd_hdspm_free(hdspm);
6577}
6578
Adrian Knoth0dca1792011-01-26 19:32:14 +01006579
Bill Pembertone23e7a12012-12-06 12:35:10 -05006580static int snd_hdspm_probe(struct pci_dev *pci,
6581 const struct pci_device_id *pci_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02006582{
6583 static int dev;
Takashi Iwai98274f02005-11-17 14:52:34 +01006584 struct hdspm *hdspm;
6585 struct snd_card *card;
Takashi Iwai763f3562005-06-03 11:25:34 +02006586 int err;
6587
6588 if (dev >= SNDRV_CARDS)
6589 return -ENODEV;
6590 if (!enable[dev]) {
6591 dev++;
6592 return -ENOENT;
6593 }
6594
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006595 err = snd_card_create(index[dev], id[dev],
Adrian Knoth0dca1792011-01-26 19:32:14 +01006596 THIS_MODULE, sizeof(struct hdspm), &card);
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006597 if (err < 0)
6598 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006599
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006600 hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006601 card->private_free = snd_hdspm_card_free;
6602 hdspm->dev = dev;
6603 hdspm->pci = pci;
6604
Takashi Iwaic187c042007-02-19 15:27:33 +01006605 snd_card_set_dev(card, &pci->dev);
6606
Adrian Knoth0dca1792011-01-26 19:32:14 +01006607 err = snd_hdspm_create(card, hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006608 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006609 snd_card_free(card);
6610 return err;
6611 }
6612
Adrian Knoth0dca1792011-01-26 19:32:14 +01006613 if (hdspm->io_type != MADIface) {
6614 sprintf(card->shortname, "%s_%x",
6615 hdspm->card_name,
Adrian Knoth7d53a632012-01-04 14:31:16 +01006616 hdspm->serial);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006617 sprintf(card->longname, "%s S/N 0x%x at 0x%lx, irq %d",
6618 hdspm->card_name,
Adrian Knoth7d53a632012-01-04 14:31:16 +01006619 hdspm->serial,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006620 hdspm->port, hdspm->irq);
6621 } else {
6622 sprintf(card->shortname, "%s", hdspm->card_name);
6623 sprintf(card->longname, "%s at 0x%lx, irq %d",
6624 hdspm->card_name, hdspm->port, hdspm->irq);
6625 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006626
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006627 err = snd_card_register(card);
6628 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006629 snd_card_free(card);
6630 return err;
6631 }
6632
6633 pci_set_drvdata(pci, card);
6634
6635 dev++;
6636 return 0;
6637}
6638
Bill Pembertone23e7a12012-12-06 12:35:10 -05006639static void snd_hdspm_remove(struct pci_dev *pci)
Takashi Iwai763f3562005-06-03 11:25:34 +02006640{
6641 snd_card_free(pci_get_drvdata(pci));
6642 pci_set_drvdata(pci, NULL);
6643}
6644
Takashi Iwaie9f66d92012-04-24 12:25:00 +02006645static struct pci_driver hdspm_driver = {
Takashi Iwai3733e422011-06-10 16:20:20 +02006646 .name = KBUILD_MODNAME,
Takashi Iwai763f3562005-06-03 11:25:34 +02006647 .id_table = snd_hdspm_ids,
6648 .probe = snd_hdspm_probe,
Bill Pembertone23e7a12012-12-06 12:35:10 -05006649 .remove = snd_hdspm_remove,
Takashi Iwai763f3562005-06-03 11:25:34 +02006650};
6651
Takashi Iwaie9f66d92012-04-24 12:25:00 +02006652module_pci_driver(hdspm_driver);