blob: 1a52a1ae1f4cc961373db0ae5417c8b58b53f31a [file] [log] [blame]
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001/*
Takashi Iwai763f3562005-06-03 11:25:34 +02002 * ALSA driver for RME Hammerfall DSP MADI audio interface(s)
3 *
4 * Copyright (c) 2003 Winfried Ritsch (IEM)
5 * code based on hdsp.c Paul Davis
6 * Marcus Andersson
7 * Thomas Charbonnel
Remy Bruno3cee5a62006-10-16 12:46:32 +02008 * Modified 2006-06-01 for AES32 support by Remy Bruno
9 * <remy.bruno@trinnov.com>
Takashi Iwai763f3562005-06-03 11:25:34 +020010 *
Adrian Knoth0dca1792011-01-26 19:32:14 +010011 * Modified 2009-04-13 for proper metering by Florian Faber
12 * <faber@faberman.de>
13 *
14 * Modified 2009-04-14 for native float support by Florian Faber
15 * <faber@faberman.de>
16 *
17 * Modified 2009-04-26 fixed bug in rms metering by Florian Faber
18 * <faber@faberman.de>
19 *
20 * Modified 2009-04-30 added hw serial number support by Florian Faber
21 *
22 * Modified 2011-01-14 added S/PDIF input on RayDATs by Adrian Knoth
23 *
24 * Modified 2011-01-25 variable period sizes on RayDAT/AIO by Adrian Knoth
25 *
Takashi Iwai763f3562005-06-03 11:25:34 +020026 * This program is free software; you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License as published by
28 * the Free Software Foundation; either version 2 of the License, or
29 * (at your option) any later version.
30 *
31 * This program is distributed in the hope that it will be useful,
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 * GNU General Public License for more details.
35 *
36 * You should have received a copy of the GNU General Public License
37 * along with this program; if not, write to the Free Software
38 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 *
40 */
Takashi Iwai763f3562005-06-03 11:25:34 +020041#include <linux/init.h>
42#include <linux/delay.h>
43#include <linux/interrupt.h>
44#include <linux/moduleparam.h>
45#include <linux/slab.h>
46#include <linux/pci.h>
Takashi Iwai3f7440a2009-06-05 17:40:04 +020047#include <linux/math64.h>
Takashi Iwai763f3562005-06-03 11:25:34 +020048#include <asm/io.h>
49
50#include <sound/core.h>
51#include <sound/control.h>
52#include <sound/pcm.h>
Adrian Knoth0dca1792011-01-26 19:32:14 +010053#include <sound/pcm_params.h>
Takashi Iwai763f3562005-06-03 11:25:34 +020054#include <sound/info.h>
55#include <sound/asoundef.h>
56#include <sound/rawmidi.h>
57#include <sound/hwdep.h>
58#include <sound/initval.h>
59
60#include <sound/hdspm.h>
61
62static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
63static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
64static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
65
Takashi Iwai763f3562005-06-03 11:25:34 +020066module_param_array(index, int, NULL, 0444);
67MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");
68
69module_param_array(id, charp, NULL, 0444);
70MODULE_PARM_DESC(id, "ID string for RME HDSPM interface.");
71
72module_param_array(enable, bool, NULL, 0444);
73MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");
74
Takashi Iwai763f3562005-06-03 11:25:34 +020075
76MODULE_AUTHOR
Adrian Knoth0dca1792011-01-26 19:32:14 +010077(
78 "Winfried Ritsch <ritsch_AT_iem.at>, "
79 "Paul Davis <paul@linuxaudiosystems.com>, "
80 "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, "
81 "Remy Bruno <remy.bruno@trinnov.com>, "
82 "Florian Faber <faberman@linuxproaudio.org>, "
83 "Adrian Knoth <adi@drcomp.erfurt.thur.de>"
84);
Takashi Iwai763f3562005-06-03 11:25:34 +020085MODULE_DESCRIPTION("RME HDSPM");
86MODULE_LICENSE("GPL");
87MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
88
Adrian Knoth0dca1792011-01-26 19:32:14 +010089/* --- Write registers. ---
Takashi Iwai763f3562005-06-03 11:25:34 +020090 These are defined as byte-offsets from the iobase value. */
91
Adrian Knoth0dca1792011-01-26 19:32:14 +010092#define HDSPM_WR_SETTINGS 0
93#define HDSPM_outputBufferAddress 32
94#define HDSPM_inputBufferAddress 36
Takashi Iwai763f3562005-06-03 11:25:34 +020095#define HDSPM_controlRegister 64
96#define HDSPM_interruptConfirmation 96
97#define HDSPM_control2Reg 256 /* not in specs ???????? */
Remy Brunoffb2c3c2007-03-07 19:08:46 +010098#define HDSPM_freqReg 256 /* for AES32 */
Adrian Knoth0dca1792011-01-26 19:32:14 +010099#define HDSPM_midiDataOut0 352 /* just believe in old code */
100#define HDSPM_midiDataOut1 356
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100101#define HDSPM_eeprom_wr 384 /* for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200102
103/* DMA enable for 64 channels, only Bit 0 is relevant */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100104#define HDSPM_outputEnableBase 512 /* 512-767 input DMA */
Takashi Iwai763f3562005-06-03 11:25:34 +0200105#define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */
106
Adrian Knoth0dca1792011-01-26 19:32:14 +0100107/* 16 page addresses for each of the 64 channels DMA buffer in and out
Takashi Iwai763f3562005-06-03 11:25:34 +0200108 (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */
109#define HDSPM_pageAddressBufferOut 8192
110#define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4)
111
112#define HDSPM_MADI_mixerBase 32768 /* 32768-65535 for 2x64x64 Fader */
113
114#define HDSPM_MATRIX_MIXER_SIZE 8192 /* = 2*64*64 * 4 Byte => 32kB */
115
116/* --- Read registers. ---
117 These are defined as byte-offsets from the iobase value */
118#define HDSPM_statusRegister 0
Remy Bruno3cee5a62006-10-16 12:46:32 +0200119/*#define HDSPM_statusRegister2 96 */
120/* after RME Windows driver sources, status2 is 4-byte word # 48 = word at
121 * offset 192, for AES32 *and* MADI
122 * => need to check that offset 192 is working on MADI */
123#define HDSPM_statusRegister2 192
124#define HDSPM_timecodeRegister 128
Takashi Iwai763f3562005-06-03 11:25:34 +0200125
Adrian Knoth0dca1792011-01-26 19:32:14 +0100126/* AIO, RayDAT */
127#define HDSPM_RD_STATUS_0 0
128#define HDSPM_RD_STATUS_1 64
129#define HDSPM_RD_STATUS_2 128
130#define HDSPM_RD_STATUS_3 192
131
132#define HDSPM_RD_TCO 256
133#define HDSPM_RD_PLL_FREQ 512
134#define HDSPM_WR_TCO 128
135
136#define HDSPM_TCO1_TCO_lock 0x00000001
137#define HDSPM_TCO1_WCK_Input_Range_LSB 0x00000002
138#define HDSPM_TCO1_WCK_Input_Range_MSB 0x00000004
139#define HDSPM_TCO1_LTC_Input_valid 0x00000008
140#define HDSPM_TCO1_WCK_Input_valid 0x00000010
141#define HDSPM_TCO1_Video_Input_Format_NTSC 0x00000020
142#define HDSPM_TCO1_Video_Input_Format_PAL 0x00000040
143
144#define HDSPM_TCO1_set_TC 0x00000100
145#define HDSPM_TCO1_set_drop_frame_flag 0x00000200
146#define HDSPM_TCO1_LTC_Format_LSB 0x00000400
147#define HDSPM_TCO1_LTC_Format_MSB 0x00000800
148
149#define HDSPM_TCO2_TC_run 0x00010000
150#define HDSPM_TCO2_WCK_IO_ratio_LSB 0x00020000
151#define HDSPM_TCO2_WCK_IO_ratio_MSB 0x00040000
152#define HDSPM_TCO2_set_num_drop_frames_LSB 0x00080000
153#define HDSPM_TCO2_set_num_drop_frames_MSB 0x00100000
154#define HDSPM_TCO2_set_jam_sync 0x00200000
155#define HDSPM_TCO2_set_flywheel 0x00400000
156
157#define HDSPM_TCO2_set_01_4 0x01000000
158#define HDSPM_TCO2_set_pull_down 0x02000000
159#define HDSPM_TCO2_set_pull_up 0x04000000
160#define HDSPM_TCO2_set_freq 0x08000000
161#define HDSPM_TCO2_set_term_75R 0x10000000
162#define HDSPM_TCO2_set_input_LSB 0x20000000
163#define HDSPM_TCO2_set_input_MSB 0x40000000
164#define HDSPM_TCO2_set_freq_from_app 0x80000000
165
166
167#define HDSPM_midiDataOut0 352
168#define HDSPM_midiDataOut1 356
169#define HDSPM_midiDataOut2 368
170
Takashi Iwai763f3562005-06-03 11:25:34 +0200171#define HDSPM_midiDataIn0 360
172#define HDSPM_midiDataIn1 364
Adrian Knoth0dca1792011-01-26 19:32:14 +0100173#define HDSPM_midiDataIn2 372
174#define HDSPM_midiDataIn3 376
Takashi Iwai763f3562005-06-03 11:25:34 +0200175
176/* status is data bytes in MIDI-FIFO (0-128) */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100177#define HDSPM_midiStatusOut0 384
178#define HDSPM_midiStatusOut1 388
179#define HDSPM_midiStatusOut2 400
180
181#define HDSPM_midiStatusIn0 392
182#define HDSPM_midiStatusIn1 396
183#define HDSPM_midiStatusIn2 404
184#define HDSPM_midiStatusIn3 408
Takashi Iwai763f3562005-06-03 11:25:34 +0200185
186
187/* the meters are regular i/o-mapped registers, but offset
188 considerably from the rest. the peak registers are reset
Adrian Knoth0dca1792011-01-26 19:32:14 +0100189 when read; the least-significant 4 bits are full-scale counters;
Takashi Iwai763f3562005-06-03 11:25:34 +0200190 the actual peak value is in the most-significant 24 bits.
191*/
Adrian Knoth0dca1792011-01-26 19:32:14 +0100192
193#define HDSPM_MADI_INPUT_PEAK 4096
194#define HDSPM_MADI_PLAYBACK_PEAK 4352
195#define HDSPM_MADI_OUTPUT_PEAK 4608
196
197#define HDSPM_MADI_INPUT_RMS_L 6144
198#define HDSPM_MADI_PLAYBACK_RMS_L 6400
199#define HDSPM_MADI_OUTPUT_RMS_L 6656
200
201#define HDSPM_MADI_INPUT_RMS_H 7168
202#define HDSPM_MADI_PLAYBACK_RMS_H 7424
203#define HDSPM_MADI_OUTPUT_RMS_H 7680
Takashi Iwai763f3562005-06-03 11:25:34 +0200204
205/* --- Control Register bits --------- */
206#define HDSPM_Start (1<<0) /* start engine */
207
208#define HDSPM_Latency0 (1<<1) /* buffer size = 2^n */
209#define HDSPM_Latency1 (1<<2) /* where n is defined */
210#define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */
211
Adrian Knoth0dca1792011-01-26 19:32:14 +0100212#define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Autosync */
213#define HDSPM_c0Master 0x1 /* Master clock bit in settings
214 register [RayDAT, AIO] */
Takashi Iwai763f3562005-06-03 11:25:34 +0200215
216#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */
217
218#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */
219#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */
220#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200221#define HDSPM_QuadSpeed (1<<31) /* quad speed bit */
Takashi Iwai763f3562005-06-03 11:25:34 +0200222
Remy Bruno3cee5a62006-10-16 12:46:32 +0200223#define HDSPM_Professional (1<<9) /* Professional */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200224#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200225 56channelMODE=0 */ /* MADI ONLY*/
226#define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200227
Adrian Knoth0dca1792011-01-26 19:32:14 +0100228#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200229 0=off, 1=on */ /* MADI ONLY */
230#define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200231
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200232#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax
233 * -- MADI ONLY
234 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200235#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
236
Remy Bruno3cee5a62006-10-16 12:46:32 +0200237#define HDSPM_SyncRef2 (1<<13)
238#define HDSPM_SyncRef3 (1<<25)
Takashi Iwai763f3562005-06-03 11:25:34 +0200239
Remy Bruno3cee5a62006-10-16 12:46:32 +0200240#define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100241#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use
Takashi Iwai763f3562005-06-03 11:25:34 +0200242 AES additional bits in
243 lower 5 Audiodatabits ??? */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200244#define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */
245#define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200246
Adrian Knoth0dca1792011-01-26 19:32:14 +0100247#define HDSPM_Midi0InterruptEnable 0x0400000
248#define HDSPM_Midi1InterruptEnable 0x0800000
249#define HDSPM_Midi2InterruptEnable 0x0200000
250#define HDSPM_Midi3InterruptEnable 0x4000000
Takashi Iwai763f3562005-06-03 11:25:34 +0200251
252#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100253#define HDSPe_FLOAT_FORMAT 0x2000000
Takashi Iwai763f3562005-06-03 11:25:34 +0200254
Remy Bruno3cee5a62006-10-16 12:46:32 +0200255#define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */
256#define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */
257#define HDSPM_QS_QuadWire (1<<28) /* AES32 ONLY */
258
259#define HDSPM_wclk_sel (1<<30)
Takashi Iwai763f3562005-06-03 11:25:34 +0200260
261/* --- bit helper defines */
262#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200263#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|\
264 HDSPM_DoubleSpeed|HDSPM_QuadSpeed)
Takashi Iwai763f3562005-06-03 11:25:34 +0200265#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1)
266#define HDSPM_InputOptical 0
267#define HDSPM_InputCoaxial (HDSPM_InputSelect0)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200268#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\
269 HDSPM_SyncRef2|HDSPM_SyncRef3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200270
Adrian Knoth0dca1792011-01-26 19:32:14 +0100271#define HDSPM_c0_SyncRef0 0x2
272#define HDSPM_c0_SyncRef1 0x4
273#define HDSPM_c0_SyncRef2 0x8
274#define HDSPM_c0_SyncRef3 0x10
275#define HDSPM_c0_SyncRefMask (HDSPM_c0_SyncRef0 | HDSPM_c0_SyncRef1 |\
276 HDSPM_c0_SyncRef2 | HDSPM_c0_SyncRef3)
277
278#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */
279#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */
280#define HDSPM_SYNC_FROM_TCO 2
281#define HDSPM_SYNC_FROM_SYNC_IN 3
Takashi Iwai763f3562005-06-03 11:25:34 +0200282
283#define HDSPM_Frequency32KHz HDSPM_Frequency0
284#define HDSPM_Frequency44_1KHz HDSPM_Frequency1
285#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0)
286#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0)
287#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200288#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|\
289 HDSPM_Frequency0)
Remy Bruno3cee5a62006-10-16 12:46:32 +0200290#define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0)
291#define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200292#define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\
293 HDSPM_Frequency0)
Takashi Iwai763f3562005-06-03 11:25:34 +0200294
Takashi Iwai763f3562005-06-03 11:25:34 +0200295
296/* Synccheck Status */
297#define HDSPM_SYNC_CHECK_NO_LOCK 0
298#define HDSPM_SYNC_CHECK_LOCK 1
299#define HDSPM_SYNC_CHECK_SYNC 2
300
301/* AutoSync References - used by "autosync_ref" control switch */
302#define HDSPM_AUTOSYNC_FROM_WORD 0
303#define HDSPM_AUTOSYNC_FROM_MADI 1
Adrian Knoth0dca1792011-01-26 19:32:14 +0100304#define HDSPM_AUTOSYNC_FROM_TCO 2
305#define HDSPM_AUTOSYNC_FROM_SYNC_IN 3
306#define HDSPM_AUTOSYNC_FROM_NONE 4
Takashi Iwai763f3562005-06-03 11:25:34 +0200307
308/* Possible sources of MADI input */
309#define HDSPM_OPTICAL 0 /* optical */
310#define HDSPM_COAXIAL 1 /* BNC */
311
312#define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask)
Adrian Knoth0dca1792011-01-26 19:32:14 +0100313#define hdspm_decode_latency(x) ((((x) & HDSPM_LatencyMask)>>1))
Takashi Iwai763f3562005-06-03 11:25:34 +0200314
315#define hdspm_encode_in(x) (((x)&0x3)<<14)
316#define hdspm_decode_in(x) (((x)>>14)&0x3)
317
318/* --- control2 register bits --- */
319#define HDSPM_TMS (1<<0)
320#define HDSPM_TCK (1<<1)
321#define HDSPM_TDI (1<<2)
322#define HDSPM_JTAG (1<<3)
323#define HDSPM_PWDN (1<<4)
324#define HDSPM_PROGRAM (1<<5)
325#define HDSPM_CONFIG_MODE_0 (1<<6)
326#define HDSPM_CONFIG_MODE_1 (1<<7)
327/*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/
328#define HDSPM_BIGENDIAN_MODE (1<<9)
329#define HDSPM_RD_MULTIPLE (1<<10)
330
Remy Bruno3cee5a62006-10-16 12:46:32 +0200331/* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200332 that do not conflict with specific bits for AES32 seem to be valid also
333 for the AES32
334 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200335#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200336#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn MODE=0 */
337#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1
338 * (like inp0)
339 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100340
Takashi Iwai763f3562005-06-03 11:25:34 +0200341#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100342#define HDSPM_madiSync (1<<18) /* MADI is in sync */
343
344#define HDSPM_tcoLock 0x00000020 /* Optional TCO locked status FOR HDSPe MADI! */
345#define HDSPM_tcoSync 0x10000000 /* Optional TCO sync status */
346
347#define HDSPM_syncInLock 0x00010000 /* Sync In lock status FOR HDSPe MADI! */
348#define HDSPM_syncInSync 0x00020000 /* Sync In sync status FOR HDSPe MADI! */
Takashi Iwai763f3562005-06-03 11:25:34 +0200349
350#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100351 /* since 64byte accurate, last 6 bits are not used */
Takashi Iwai763f3562005-06-03 11:25:34 +0200352
Adrian Knoth0dca1792011-01-26 19:32:14 +0100353
354
Takashi Iwai763f3562005-06-03 11:25:34 +0200355#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */
356
357#define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */
358#define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */
359#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */
360#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */
361
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200362#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with
363 * Interrupt
364 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100365#define HDSPM_tco_detect 0x08000000
366#define HDSPM_tco_lock 0x20000000
367
368#define HDSPM_s2_tco_detect 0x00000040
369#define HDSPM_s2_AEBO_D 0x00000080
370#define HDSPM_s2_AEBI_D 0x00000100
371
372
373#define HDSPM_midi0IRQPending 0x40000000
374#define HDSPM_midi1IRQPending 0x80000000
375#define HDSPM_midi2IRQPending 0x20000000
376#define HDSPM_midi2IRQPendingAES 0x00000020
377#define HDSPM_midi3IRQPending 0x00200000
Takashi Iwai763f3562005-06-03 11:25:34 +0200378
379/* --- status bit helpers */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200380#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\
381 HDSPM_madiFreq2|HDSPM_madiFreq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200382#define HDSPM_madiFreq32 (HDSPM_madiFreq0)
383#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1)
384#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1)
385#define HDSPM_madiFreq64 (HDSPM_madiFreq2)
386#define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2)
387#define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2)
388#define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2)
389#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
390#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0)
391
Remy Bruno3cee5a62006-10-16 12:46:32 +0200392/* Status2 Register bits */ /* MADI ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200393
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
444#define HDSPM_AES32_wcFreq_bit 22
Adrian Knoth0dca1792011-01-26 19:32:14 +0100445/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function
Remy Bruno3cee5a62006-10-16 12:46:32 +0200446 HDSPM_bit2freq */
447#define HDSPM_AES32_syncref_bit 16
448/* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */
449
450#define HDSPM_AES32_AUTOSYNC_FROM_WORD 0
451#define HDSPM_AES32_AUTOSYNC_FROM_AES1 1
452#define HDSPM_AES32_AUTOSYNC_FROM_AES2 2
453#define HDSPM_AES32_AUTOSYNC_FROM_AES3 3
454#define HDSPM_AES32_AUTOSYNC_FROM_AES4 4
455#define HDSPM_AES32_AUTOSYNC_FROM_AES5 5
456#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6
457#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7
458#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8
Remy Bruno65345992007-08-31 12:21:08 +0200459#define HDSPM_AES32_AUTOSYNC_FROM_NONE 9
Remy Bruno3cee5a62006-10-16 12:46:32 +0200460
461/* status2 */
462/* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */
463#define HDSPM_LockAES 0x80
464#define HDSPM_LockAES1 0x80
465#define HDSPM_LockAES2 0x40
466#define HDSPM_LockAES3 0x20
467#define HDSPM_LockAES4 0x10
468#define HDSPM_LockAES5 0x8
469#define HDSPM_LockAES6 0x4
470#define HDSPM_LockAES7 0x2
471#define HDSPM_LockAES8 0x1
472/*
473 Timecode
474 After windows driver sources, bits 4*i to 4*i+3 give the input frequency on
475 AES i+1
476 bits 3210
477 0001 32kHz
478 0010 44.1kHz
479 0011 48kHz
480 0100 64kHz
481 0101 88.2kHz
482 0110 96kHz
483 0111 128kHz
484 1000 176.4kHz
485 1001 192kHz
486 NB: Timecode register doesn't seem to work on AES32 card revision 230
487*/
488
Takashi Iwai763f3562005-06-03 11:25:34 +0200489/* Mixer Values */
490#define UNITY_GAIN 32768 /* = 65536/2 */
491#define MINUS_INFINITY_GAIN 0
492
Takashi Iwai763f3562005-06-03 11:25:34 +0200493/* Number of channels for different Speed Modes */
494#define MADI_SS_CHANNELS 64
495#define MADI_DS_CHANNELS 32
496#define MADI_QS_CHANNELS 16
497
Adrian Knoth0dca1792011-01-26 19:32:14 +0100498#define RAYDAT_SS_CHANNELS 36
499#define RAYDAT_DS_CHANNELS 20
500#define RAYDAT_QS_CHANNELS 12
501
502#define AIO_IN_SS_CHANNELS 14
503#define AIO_IN_DS_CHANNELS 10
504#define AIO_IN_QS_CHANNELS 8
505#define AIO_OUT_SS_CHANNELS 16
506#define AIO_OUT_DS_CHANNELS 12
507#define AIO_OUT_QS_CHANNELS 10
508
Adrian Knothd2d10a22011-02-28 15:14:47 +0100509#define AES32_CHANNELS 16
510
Takashi Iwai763f3562005-06-03 11:25:34 +0200511/* the size of a substream (1 mono data stream) */
512#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024)
513#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
514
515/* the size of the area we need to allocate for DMA transfers. the
516 size is the same regardless of the number of channels, and
Adrian Knoth0dca1792011-01-26 19:32:14 +0100517 also the latency to use.
Takashi Iwai763f3562005-06-03 11:25:34 +0200518 for one direction !!!
519*/
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100520#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
Takashi Iwai763f3562005-06-03 11:25:34 +0200521#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
522
Remy Bruno3cee5a62006-10-16 12:46:32 +0200523/* revisions >= 230 indicate AES32 card */
Adrian Knoth5f8b4d52011-07-29 03:11:04 +0200524#define HDSPM_MADI_ANCIENT_REV 204
Adrian Knothefef0542011-06-12 17:26:19 +0200525#define HDSPM_MADI_OLD_REV 207
Adrian Knoth0dca1792011-01-26 19:32:14 +0100526#define HDSPM_MADI_REV 210
527#define HDSPM_RAYDAT_REV 211
528#define HDSPM_AIO_REV 212
529#define HDSPM_MADIFACE_REV 213
530#define HDSPM_AES_REV 240
Adrian Knoth526ea862011-02-28 15:14:48 +0100531#define HDSPM_AES32_REV 234
Adrian Knothbdd32552011-03-07 19:10:11 +0100532#define HDSPM_AES32_OLD_REV 233
Remy Bruno3cee5a62006-10-16 12:46:32 +0200533
Remy Bruno65345992007-08-31 12:21:08 +0200534/* speed factor modes */
535#define HDSPM_SPEED_SINGLE 0
536#define HDSPM_SPEED_DOUBLE 1
537#define HDSPM_SPEED_QUAD 2
Adrian Knoth0dca1792011-01-26 19:32:14 +0100538
Remy Bruno65345992007-08-31 12:21:08 +0200539/* names for speed modes */
540static char *hdspm_speed_names[] = { "single", "double", "quad" };
541
Adrian Knoth0dca1792011-01-26 19:32:14 +0100542static char *texts_autosync_aes_tco[] = { "Word Clock",
543 "AES1", "AES2", "AES3", "AES4",
544 "AES5", "AES6", "AES7", "AES8",
545 "TCO" };
546static char *texts_autosync_aes[] = { "Word Clock",
547 "AES1", "AES2", "AES3", "AES4",
548 "AES5", "AES6", "AES7", "AES8" };
549static char *texts_autosync_madi_tco[] = { "Word Clock",
550 "MADI", "TCO", "Sync In" };
551static char *texts_autosync_madi[] = { "Word Clock",
552 "MADI", "Sync In" };
553
554static char *texts_autosync_raydat_tco[] = {
555 "Word Clock",
556 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
557 "AES", "SPDIF", "TCO", "Sync In"
558};
559static char *texts_autosync_raydat[] = {
560 "Word Clock",
561 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
562 "AES", "SPDIF", "Sync In"
563};
564static char *texts_autosync_aio_tco[] = {
565 "Word Clock",
566 "ADAT", "AES", "SPDIF", "TCO", "Sync In"
567};
568static char *texts_autosync_aio[] = { "Word Clock",
569 "ADAT", "AES", "SPDIF", "Sync In" };
570
571static char *texts_freq[] = {
572 "No Lock",
573 "32 kHz",
574 "44.1 kHz",
575 "48 kHz",
576 "64 kHz",
577 "88.2 kHz",
578 "96 kHz",
579 "128 kHz",
580 "176.4 kHz",
581 "192 kHz"
582};
583
Adrian Knoth0dca1792011-01-26 19:32:14 +0100584static char *texts_ports_madi[] = {
585 "MADI.1", "MADI.2", "MADI.3", "MADI.4", "MADI.5", "MADI.6",
586 "MADI.7", "MADI.8", "MADI.9", "MADI.10", "MADI.11", "MADI.12",
587 "MADI.13", "MADI.14", "MADI.15", "MADI.16", "MADI.17", "MADI.18",
588 "MADI.19", "MADI.20", "MADI.21", "MADI.22", "MADI.23", "MADI.24",
589 "MADI.25", "MADI.26", "MADI.27", "MADI.28", "MADI.29", "MADI.30",
590 "MADI.31", "MADI.32", "MADI.33", "MADI.34", "MADI.35", "MADI.36",
591 "MADI.37", "MADI.38", "MADI.39", "MADI.40", "MADI.41", "MADI.42",
592 "MADI.43", "MADI.44", "MADI.45", "MADI.46", "MADI.47", "MADI.48",
593 "MADI.49", "MADI.50", "MADI.51", "MADI.52", "MADI.53", "MADI.54",
594 "MADI.55", "MADI.56", "MADI.57", "MADI.58", "MADI.59", "MADI.60",
595 "MADI.61", "MADI.62", "MADI.63", "MADI.64",
596};
597
598
599static char *texts_ports_raydat_ss[] = {
600 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT1.5", "ADAT1.6",
601 "ADAT1.7", "ADAT1.8", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
602 "ADAT2.5", "ADAT2.6", "ADAT2.7", "ADAT2.8", "ADAT3.1", "ADAT3.2",
603 "ADAT3.3", "ADAT3.4", "ADAT3.5", "ADAT3.6", "ADAT3.7", "ADAT3.8",
604 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4", "ADAT4.5", "ADAT4.6",
605 "ADAT4.7", "ADAT4.8",
606 "AES.L", "AES.R",
607 "SPDIF.L", "SPDIF.R"
608};
609
610static char *texts_ports_raydat_ds[] = {
611 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4",
612 "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
613 "ADAT3.1", "ADAT3.2", "ADAT3.3", "ADAT3.4",
614 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4",
615 "AES.L", "AES.R",
616 "SPDIF.L", "SPDIF.R"
617};
618
619static char *texts_ports_raydat_qs[] = {
620 "ADAT1.1", "ADAT1.2",
621 "ADAT2.1", "ADAT2.2",
622 "ADAT3.1", "ADAT3.2",
623 "ADAT4.1", "ADAT4.2",
624 "AES.L", "AES.R",
625 "SPDIF.L", "SPDIF.R"
626};
627
628
629static char *texts_ports_aio_in_ss[] = {
630 "Analogue.L", "Analogue.R",
631 "AES.L", "AES.R",
632 "SPDIF.L", "SPDIF.R",
633 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
634 "ADAT.7", "ADAT.8"
635};
636
637static char *texts_ports_aio_out_ss[] = {
638 "Analogue.L", "Analogue.R",
639 "AES.L", "AES.R",
640 "SPDIF.L", "SPDIF.R",
641 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
642 "ADAT.7", "ADAT.8",
643 "Phone.L", "Phone.R"
644};
645
646static char *texts_ports_aio_in_ds[] = {
647 "Analogue.L", "Analogue.R",
648 "AES.L", "AES.R",
649 "SPDIF.L", "SPDIF.R",
650 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
651};
652
653static char *texts_ports_aio_out_ds[] = {
654 "Analogue.L", "Analogue.R",
655 "AES.L", "AES.R",
656 "SPDIF.L", "SPDIF.R",
657 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
658 "Phone.L", "Phone.R"
659};
660
661static char *texts_ports_aio_in_qs[] = {
662 "Analogue.L", "Analogue.R",
663 "AES.L", "AES.R",
664 "SPDIF.L", "SPDIF.R",
665 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
666};
667
668static char *texts_ports_aio_out_qs[] = {
669 "Analogue.L", "Analogue.R",
670 "AES.L", "AES.R",
671 "SPDIF.L", "SPDIF.R",
672 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
673 "Phone.L", "Phone.R"
674};
675
Adrian Knoth432d2502011-02-23 11:43:08 +0100676static char *texts_ports_aes32[] = {
677 "AES.1", "AES.2", "AES.3", "AES.4", "AES.5", "AES.6", "AES.7",
678 "AES.8", "AES.9.", "AES.10", "AES.11", "AES.12", "AES.13", "AES.14",
679 "AES.15", "AES.16"
680};
681
Adrian Knoth55a57602011-01-27 11:23:15 +0100682/* These tables map the ALSA channels 1..N to the channels that we
683 need to use in order to find the relevant channel buffer. RME
684 refers to this kind of mapping as between "the ADAT channel and
685 the DMA channel." We index it using the logical audio channel,
686 and the value is the DMA channel (i.e. channel buffer number)
687 where the data for that channel can be read/written from/to.
688*/
689
690static char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = {
691 0, 1, 2, 3, 4, 5, 6, 7,
692 8, 9, 10, 11, 12, 13, 14, 15,
693 16, 17, 18, 19, 20, 21, 22, 23,
694 24, 25, 26, 27, 28, 29, 30, 31,
695 32, 33, 34, 35, 36, 37, 38, 39,
696 40, 41, 42, 43, 44, 45, 46, 47,
697 48, 49, 50, 51, 52, 53, 54, 55,
698 56, 57, 58, 59, 60, 61, 62, 63
699};
700
Adrian Knoth55a57602011-01-27 11:23:15 +0100701static char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = {
702 4, 5, 6, 7, 8, 9, 10, 11, /* ADAT 1 */
703 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT 2 */
704 20, 21, 22, 23, 24, 25, 26, 27, /* ADAT 3 */
705 28, 29, 30, 31, 32, 33, 34, 35, /* ADAT 4 */
706 0, 1, /* AES */
707 2, 3, /* SPDIF */
708 -1, -1, -1, -1,
709 -1, -1, -1, -1, -1, -1, -1, -1,
710 -1, -1, -1, -1, -1, -1, -1, -1,
711 -1, -1, -1, -1, -1, -1, -1, -1,
712};
713
714static char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = {
715 4, 5, 6, 7, /* ADAT 1 */
716 8, 9, 10, 11, /* ADAT 2 */
717 12, 13, 14, 15, /* ADAT 3 */
718 16, 17, 18, 19, /* ADAT 4 */
719 0, 1, /* AES */
720 2, 3, /* SPDIF */
721 -1, -1, -1, -1,
722 -1, -1, -1, -1, -1, -1, -1, -1,
723 -1, -1, -1, -1, -1, -1, -1, -1,
724 -1, -1, -1, -1, -1, -1, -1, -1,
725 -1, -1, -1, -1, -1, -1, -1, -1,
726 -1, -1, -1, -1, -1, -1, -1, -1,
727};
728
729static char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = {
730 4, 5, /* ADAT 1 */
731 6, 7, /* ADAT 2 */
732 8, 9, /* ADAT 3 */
733 10, 11, /* ADAT 4 */
734 0, 1, /* AES */
735 2, 3, /* SPDIF */
736 -1, -1, -1, -1,
737 -1, -1, -1, -1, -1, -1, -1, -1,
738 -1, -1, -1, -1, -1, -1, -1, -1,
739 -1, -1, -1, -1, -1, -1, -1, -1,
740 -1, -1, -1, -1, -1, -1, -1, -1,
741 -1, -1, -1, -1, -1, -1, -1, -1,
742 -1, -1, -1, -1, -1, -1, -1, -1,
743};
744
745static char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = {
746 0, 1, /* line in */
747 8, 9, /* aes in, */
748 10, 11, /* spdif in */
749 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT in */
750 -1, -1,
751 -1, -1, -1, -1, -1, -1, -1, -1,
752 -1, -1, -1, -1, -1, -1, -1, -1,
753 -1, -1, -1, -1, -1, -1, -1, -1,
754 -1, -1, -1, -1, -1, -1, -1, -1,
755 -1, -1, -1, -1, -1, -1, -1, -1,
756 -1, -1, -1, -1, -1, -1, -1, -1,
757};
758
759static char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = {
760 0, 1, /* line out */
761 8, 9, /* aes out */
762 10, 11, /* spdif out */
763 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT out */
764 6, 7, /* phone out */
765 -1, -1, -1, -1, -1, -1, -1, -1,
766 -1, -1, -1, -1, -1, -1, -1, -1,
767 -1, -1, -1, -1, -1, -1, -1, -1,
768 -1, -1, -1, -1, -1, -1, -1, -1,
769 -1, -1, -1, -1, -1, -1, -1, -1,
770 -1, -1, -1, -1, -1, -1, -1, -1,
771};
772
773static char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = {
774 0, 1, /* line in */
775 8, 9, /* aes in */
776 10, 11, /* spdif in */
777 12, 14, 16, 18, /* adat in */
778 -1, -1, -1, -1, -1, -1,
779 -1, -1, -1, -1, -1, -1, -1, -1,
780 -1, -1, -1, -1, -1, -1, -1, -1,
781 -1, -1, -1, -1, -1, -1, -1, -1,
782 -1, -1, -1, -1, -1, -1, -1, -1,
783 -1, -1, -1, -1, -1, -1, -1, -1,
784 -1, -1, -1, -1, -1, -1, -1, -1
785};
786
787static char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = {
788 0, 1, /* line out */
789 8, 9, /* aes out */
790 10, 11, /* spdif out */
791 12, 14, 16, 18, /* adat out */
792 6, 7, /* phone out */
793 -1, -1, -1, -1,
794 -1, -1, -1, -1, -1, -1, -1, -1,
795 -1, -1, -1, -1, -1, -1, -1, -1,
796 -1, -1, -1, -1, -1, -1, -1, -1,
797 -1, -1, -1, -1, -1, -1, -1, -1,
798 -1, -1, -1, -1, -1, -1, -1, -1,
799 -1, -1, -1, -1, -1, -1, -1, -1
800};
801
802static char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = {
803 0, 1, /* line in */
804 8, 9, /* aes in */
805 10, 11, /* spdif in */
806 12, 16, /* adat in */
807 -1, -1, -1, -1, -1, -1, -1, -1,
808 -1, -1, -1, -1, -1, -1, -1, -1,
809 -1, -1, -1, -1, -1, -1, -1, -1,
810 -1, -1, -1, -1, -1, -1, -1, -1,
811 -1, -1, -1, -1, -1, -1, -1, -1,
812 -1, -1, -1, -1, -1, -1, -1, -1,
813 -1, -1, -1, -1, -1, -1, -1, -1
814};
815
816static char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = {
817 0, 1, /* line out */
818 8, 9, /* aes out */
819 10, 11, /* spdif out */
820 12, 16, /* adat out */
821 6, 7, /* phone out */
822 -1, -1, -1, -1, -1, -1,
823 -1, -1, -1, -1, -1, -1, -1, -1,
824 -1, -1, -1, -1, -1, -1, -1, -1,
825 -1, -1, -1, -1, -1, -1, -1, -1,
826 -1, -1, -1, -1, -1, -1, -1, -1,
827 -1, -1, -1, -1, -1, -1, -1, -1,
828 -1, -1, -1, -1, -1, -1, -1, -1
829};
830
Adrian Knoth432d2502011-02-23 11:43:08 +0100831static char channel_map_aes32[HDSPM_MAX_CHANNELS] = {
832 0, 1, 2, 3, 4, 5, 6, 7,
833 8, 9, 10, 11, 12, 13, 14, 15,
834 -1, -1, -1, -1, -1, -1, -1, -1,
835 -1, -1, -1, -1, -1, -1, -1, -1,
836 -1, -1, -1, -1, -1, -1, -1, -1,
837 -1, -1, -1, -1, -1, -1, -1, -1,
838 -1, -1, -1, -1, -1, -1, -1, -1,
839 -1, -1, -1, -1, -1, -1, -1, -1
840};
841
Takashi Iwai98274f02005-11-17 14:52:34 +0100842struct hdspm_midi {
843 struct hdspm *hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +0200844 int id;
Takashi Iwai98274f02005-11-17 14:52:34 +0100845 struct snd_rawmidi *rmidi;
846 struct snd_rawmidi_substream *input;
847 struct snd_rawmidi_substream *output;
Takashi Iwai763f3562005-06-03 11:25:34 +0200848 char istimer; /* timer in use */
849 struct timer_list timer;
850 spinlock_t lock;
851 int pending;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100852 int dataIn;
853 int statusIn;
854 int dataOut;
855 int statusOut;
856 int ie;
857 int irq;
858};
859
860struct hdspm_tco {
861 int input;
862 int framerate;
863 int wordclock;
864 int samplerate;
865 int pull;
866 int term; /* 0 = off, 1 = on */
Takashi Iwai763f3562005-06-03 11:25:34 +0200867};
868
Takashi Iwai98274f02005-11-17 14:52:34 +0100869struct hdspm {
Takashi Iwai763f3562005-06-03 11:25:34 +0200870 spinlock_t lock;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200871 /* only one playback and/or capture stream */
872 struct snd_pcm_substream *capture_substream;
873 struct snd_pcm_substream *playback_substream;
Takashi Iwai763f3562005-06-03 11:25:34 +0200874
875 char *card_name; /* for procinfo */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200876 unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
877
Adrian Knoth0dca1792011-01-26 19:32:14 +0100878 uint8_t io_type;
Takashi Iwai763f3562005-06-03 11:25:34 +0200879
Takashi Iwai763f3562005-06-03 11:25:34 +0200880 int monitor_outs; /* set up monitoring outs init flag */
881
882 u32 control_register; /* cached value */
883 u32 control2_register; /* cached value */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100884 u32 settings_register;
Takashi Iwai763f3562005-06-03 11:25:34 +0200885
Adrian Knoth0dca1792011-01-26 19:32:14 +0100886 struct hdspm_midi midi[4];
Takashi Iwai763f3562005-06-03 11:25:34 +0200887 struct tasklet_struct midi_tasklet;
888
889 size_t period_bytes;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100890 unsigned char ss_in_channels;
891 unsigned char ds_in_channels;
892 unsigned char qs_in_channels;
893 unsigned char ss_out_channels;
894 unsigned char ds_out_channels;
895 unsigned char qs_out_channels;
896
897 unsigned char max_channels_in;
898 unsigned char max_channels_out;
899
Takashi Iwai286bed02011-06-30 12:45:36 +0200900 signed char *channel_map_in;
901 signed char *channel_map_out;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100902
Takashi Iwai286bed02011-06-30 12:45:36 +0200903 signed char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs;
904 signed char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100905
906 char **port_names_in;
907 char **port_names_out;
908
909 char **port_names_in_ss, **port_names_in_ds, **port_names_in_qs;
910 char **port_names_out_ss, **port_names_out_ds, **port_names_out_qs;
Takashi Iwai763f3562005-06-03 11:25:34 +0200911
912 unsigned char *playback_buffer; /* suitably aligned address */
913 unsigned char *capture_buffer; /* suitably aligned address */
914
915 pid_t capture_pid; /* process id which uses capture */
916 pid_t playback_pid; /* process id which uses capture */
917 int running; /* running status */
918
919 int last_external_sample_rate; /* samplerate mystic ... */
920 int last_internal_sample_rate;
921 int system_sample_rate;
922
Takashi Iwai763f3562005-06-03 11:25:34 +0200923 int dev; /* Hardware vars... */
924 int irq;
925 unsigned long port;
926 void __iomem *iobase;
927
928 int irq_count; /* for debug */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100929 int midiPorts;
Takashi Iwai763f3562005-06-03 11:25:34 +0200930
Takashi Iwai98274f02005-11-17 14:52:34 +0100931 struct snd_card *card; /* one card */
932 struct snd_pcm *pcm; /* has one pcm */
933 struct snd_hwdep *hwdep; /* and a hwdep for additional ioctl */
Takashi Iwai763f3562005-06-03 11:25:34 +0200934 struct pci_dev *pci; /* and an pci info */
935
936 /* Mixer vars */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200937 /* fast alsa mixer */
938 struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS];
939 /* but input to much, so not used */
940 struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS];
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300941 /* full mixer accessible over mixer ioctl or hwdep-device */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200942 struct hdspm_mixer *mixer;
Takashi Iwai763f3562005-06-03 11:25:34 +0200943
Adrian Knoth0dca1792011-01-26 19:32:14 +0100944 struct hdspm_tco *tco; /* NULL if no TCO detected */
Takashi Iwai763f3562005-06-03 11:25:34 +0200945
Adrian Knoth0dca1792011-01-26 19:32:14 +0100946 char **texts_autosync;
947 int texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +0200948
Adrian Knoth0dca1792011-01-26 19:32:14 +0100949 cycles_t last_interrupt;
Jaroslav Kysela730a5862011-01-27 13:03:15 +0100950
951 struct hdspm_peak_rms peak_rms;
Takashi Iwai763f3562005-06-03 11:25:34 +0200952};
953
Takashi Iwai763f3562005-06-03 11:25:34 +0200954
Alexey Dobriyancebe41d2010-02-06 00:21:03 +0200955static DEFINE_PCI_DEVICE_TABLE(snd_hdspm_ids) = {
Takashi Iwai763f3562005-06-03 11:25:34 +0200956 {
957 .vendor = PCI_VENDOR_ID_XILINX,
958 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
959 .subvendor = PCI_ANY_ID,
960 .subdevice = PCI_ANY_ID,
961 .class = 0,
962 .class_mask = 0,
963 .driver_data = 0},
964 {0,}
965};
966
967MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
968
969/* prototypes */
Takashi Iwai98274f02005-11-17 14:52:34 +0100970static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
971 struct hdspm * hdspm);
972static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
973 struct hdspm * hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +0200974
Adrian Knoth0dca1792011-01-26 19:32:14 +0100975static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
976static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
977static int hdspm_autosync_ref(struct hdspm *hdspm);
978static int snd_hdspm_set_defaults(struct hdspm *hdspm);
979static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +0200980 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +0200981 unsigned int reg, int channels);
982
Remy Bruno3cee5a62006-10-16 12:46:32 +0200983static inline int HDSPM_bit2freq(int n)
984{
Denys Vlasenko62cef822008-04-14 13:04:18 +0200985 static const int bit2freq_tab[] = {
986 0, 32000, 44100, 48000, 64000, 88200,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200987 96000, 128000, 176400, 192000 };
988 if (n < 1 || n > 9)
989 return 0;
990 return bit2freq_tab[n];
991}
992
Adrian Knoth0dca1792011-01-26 19:32:14 +0100993/* Write/read to/from HDSPM with Adresses in Bytes
Takashi Iwai763f3562005-06-03 11:25:34 +0200994 not words but only 32Bit writes are allowed */
995
Takashi Iwai98274f02005-11-17 14:52:34 +0100996static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
Takashi Iwai763f3562005-06-03 11:25:34 +0200997 unsigned int val)
998{
999 writel(val, hdspm->iobase + reg);
1000}
1001
Takashi Iwai98274f02005-11-17 14:52:34 +01001002static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
Takashi Iwai763f3562005-06-03 11:25:34 +02001003{
1004 return readl(hdspm->iobase + reg);
1005}
1006
Adrian Knoth0dca1792011-01-26 19:32:14 +01001007/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
1008 mixer is write only on hardware so we have to cache him for read
Takashi Iwai763f3562005-06-03 11:25:34 +02001009 each fader is a u32, but uses only the first 16 bit */
1010
Takashi Iwai98274f02005-11-17 14:52:34 +01001011static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001012 unsigned int in)
1013{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001014 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001015 return 0;
1016
1017 return hdspm->mixer->ch[chan].in[in];
1018}
1019
Takashi Iwai98274f02005-11-17 14:52:34 +01001020static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001021 unsigned int pb)
1022{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001023 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001024 return 0;
1025 return hdspm->mixer->ch[chan].pb[pb];
1026}
1027
Denys Vlasenko62cef822008-04-14 13:04:18 +02001028static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001029 unsigned int in, unsigned short data)
1030{
1031 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
1032 return -1;
1033
1034 hdspm_write(hdspm,
1035 HDSPM_MADI_mixerBase +
1036 ((in + 128 * chan) * sizeof(u32)),
1037 (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
1038 return 0;
1039}
1040
Denys Vlasenko62cef822008-04-14 13:04:18 +02001041static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001042 unsigned int pb, unsigned short data)
1043{
1044 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
1045 return -1;
1046
1047 hdspm_write(hdspm,
1048 HDSPM_MADI_mixerBase +
1049 ((64 + pb + 128 * chan) * sizeof(u32)),
1050 (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
1051 return 0;
1052}
1053
1054
1055/* enable DMA for specific channels, now available for DSP-MADI */
Takashi Iwai98274f02005-11-17 14:52:34 +01001056static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001057{
1058 hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
1059}
1060
Takashi Iwai98274f02005-11-17 14:52:34 +01001061static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001062{
1063 hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
1064}
1065
1066/* check if same process is writing and reading */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001067static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001068{
1069 unsigned long flags;
1070 int ret = 1;
1071
1072 spin_lock_irqsave(&hdspm->lock, flags);
1073 if ((hdspm->playback_pid != hdspm->capture_pid) &&
1074 (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
1075 ret = 0;
1076 }
1077 spin_unlock_irqrestore(&hdspm->lock, flags);
1078 return ret;
1079}
1080
1081/* check for external sample rate */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001082static int hdspm_external_sample_rate(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001083{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001084 unsigned int status, status2, timecode;
1085 int syncref, rate = 0, rate_bits;
Takashi Iwai763f3562005-06-03 11:25:34 +02001086
Adrian Knoth0dca1792011-01-26 19:32:14 +01001087 switch (hdspm->io_type) {
1088 case AES32:
1089 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1090 status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01001091 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001092
1093 syncref = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001094
Remy Bruno3cee5a62006-10-16 12:46:32 +02001095 if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD &&
1096 status & HDSPM_AES32_wcLock)
Adrian Knoth0dca1792011-01-26 19:32:14 +01001097 return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF);
1098
Remy Bruno3cee5a62006-10-16 12:46:32 +02001099 if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001100 syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
1101 status2 & (HDSPM_LockAES >>
1102 (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1)))
1103 return HDSPM_bit2freq((timecode >> (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF);
Remy Bruno3cee5a62006-10-16 12:46:32 +02001104 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001105 break;
1106
1107 case MADIface:
1108 status = hdspm_read(hdspm, HDSPM_statusRegister);
1109
1110 if (!(status & HDSPM_madiLock)) {
1111 rate = 0; /* no lock */
1112 } else {
1113 switch (status & (HDSPM_status1_freqMask)) {
1114 case HDSPM_status1_F_0*1:
1115 rate = 32000; break;
1116 case HDSPM_status1_F_0*2:
1117 rate = 44100; break;
1118 case HDSPM_status1_F_0*3:
1119 rate = 48000; break;
1120 case HDSPM_status1_F_0*4:
1121 rate = 64000; break;
1122 case HDSPM_status1_F_0*5:
1123 rate = 88200; break;
1124 case HDSPM_status1_F_0*6:
1125 rate = 96000; break;
1126 case HDSPM_status1_F_0*7:
1127 rate = 128000; break;
1128 case HDSPM_status1_F_0*8:
1129 rate = 176400; break;
1130 case HDSPM_status1_F_0*9:
1131 rate = 192000; break;
1132 default:
1133 rate = 0; break;
1134 }
1135 }
1136
1137 break;
1138
1139 case MADI:
1140 case AIO:
1141 case RayDAT:
1142 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1143 status = hdspm_read(hdspm, HDSPM_statusRegister);
1144 rate = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02001145
Remy Bruno3cee5a62006-10-16 12:46:32 +02001146 /* if wordclock has synced freq and wordclock is valid */
1147 if ((status2 & HDSPM_wcLock) != 0 &&
Adrian Knothfedf1532011-06-12 17:26:18 +02001148 (status2 & HDSPM_SelSyncRef0) == 0) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02001149
1150 rate_bits = status2 & HDSPM_wcFreqMask;
1151
Adrian Knoth0dca1792011-01-26 19:32:14 +01001152
Remy Bruno3cee5a62006-10-16 12:46:32 +02001153 switch (rate_bits) {
1154 case HDSPM_wcFreq32:
1155 rate = 32000;
1156 break;
1157 case HDSPM_wcFreq44_1:
1158 rate = 44100;
1159 break;
1160 case HDSPM_wcFreq48:
1161 rate = 48000;
1162 break;
1163 case HDSPM_wcFreq64:
1164 rate = 64000;
1165 break;
1166 case HDSPM_wcFreq88_2:
1167 rate = 88200;
1168 break;
1169 case HDSPM_wcFreq96:
1170 rate = 96000;
1171 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001172 default:
1173 rate = 0;
1174 break;
1175 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001176 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001177
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001178 /* if rate detected and Syncref is Word than have it,
1179 * word has priority to MADI
1180 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001181 if (rate != 0 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001182 (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
Remy Bruno3cee5a62006-10-16 12:46:32 +02001183 return rate;
1184
Adrian Knoth0dca1792011-01-26 19:32:14 +01001185 /* maybe a madi input (which is taken if sel sync is madi) */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001186 if (status & HDSPM_madiLock) {
1187 rate_bits = status & HDSPM_madiFreqMask;
1188
1189 switch (rate_bits) {
1190 case HDSPM_madiFreq32:
1191 rate = 32000;
1192 break;
1193 case HDSPM_madiFreq44_1:
1194 rate = 44100;
1195 break;
1196 case HDSPM_madiFreq48:
1197 rate = 48000;
1198 break;
1199 case HDSPM_madiFreq64:
1200 rate = 64000;
1201 break;
1202 case HDSPM_madiFreq88_2:
1203 rate = 88200;
1204 break;
1205 case HDSPM_madiFreq96:
1206 rate = 96000;
1207 break;
1208 case HDSPM_madiFreq128:
1209 rate = 128000;
1210 break;
1211 case HDSPM_madiFreq176_4:
1212 rate = 176400;
1213 break;
1214 case HDSPM_madiFreq192:
1215 rate = 192000;
1216 break;
1217 default:
1218 rate = 0;
1219 break;
1220 }
Adrian Knothd12c51d2011-07-29 03:11:03 +02001221
1222 /* QS and DS rates normally can not be detected
1223 * automatically by the card. Only exception is MADI
1224 * in 96k frame mode.
1225 *
1226 * So if we read SS values (32 .. 48k), check for
1227 * user-provided DS/QS bits in the control register
1228 * and multiply the base frequency accordingly.
1229 */
1230 if (rate <= 48000) {
1231 if (hdspm->control_register & HDSPM_QuadSpeed)
1232 rate *= 4;
1233 else if (hdspm->control_register &
1234 HDSPM_DoubleSpeed)
1235 rate *= 2;
1236 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02001237 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001238 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001239 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001240
1241 return rate;
Takashi Iwai763f3562005-06-03 11:25:34 +02001242}
1243
Adrian Knoth7cb155f2011-08-15 00:22:53 +02001244/* return latency in samples per period */
1245static int hdspm_get_latency(struct hdspm *hdspm)
1246{
1247 int n;
1248
1249 n = hdspm_decode_latency(hdspm->control_register);
1250
1251 /* Special case for new RME cards with 32 samples period size.
1252 * The three latency bits in the control register
1253 * (HDSP_LatencyMask) encode latency values of 64 samples as
1254 * 0, 128 samples as 1 ... 4096 samples as 6. For old cards, 7
1255 * denotes 8192 samples, but on new cards like RayDAT or AIO,
1256 * it corresponds to 32 samples.
1257 */
1258 if ((7 == n) && (RayDAT == hdspm->io_type || AIO == hdspm->io_type))
1259 n = -1;
1260
1261 return 1 << (n + 6);
1262}
1263
Takashi Iwai763f3562005-06-03 11:25:34 +02001264/* Latency function */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001265static inline void hdspm_compute_period_size(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001266{
Adrian Knoth7cb155f2011-08-15 00:22:53 +02001267 hdspm->period_bytes = 4 * hdspm_get_latency(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001268}
1269
Adrian Knoth0dca1792011-01-26 19:32:14 +01001270
1271static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001272{
1273 int position;
1274
1275 position = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth483cee72011-02-23 11:43:09 +01001276
1277 switch (hdspm->io_type) {
1278 case RayDAT:
1279 case AIO:
1280 position &= HDSPM_BufferPositionMask;
1281 position /= 4; /* Bytes per sample */
1282 break;
1283 default:
1284 position = (position & HDSPM_BufferID) ?
1285 (hdspm->period_bytes / 4) : 0;
1286 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001287
1288 return position;
1289}
1290
1291
Takashi Iwai98274f02005-11-17 14:52:34 +01001292static inline void hdspm_start_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001293{
1294 s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
1295 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1296}
1297
Takashi Iwai98274f02005-11-17 14:52:34 +01001298static inline void hdspm_stop_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001299{
1300 s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
1301 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1302}
1303
1304/* should I silence all or only opened ones ? doit all for first even is 4MB*/
Denys Vlasenko62cef822008-04-14 13:04:18 +02001305static void hdspm_silence_playback(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001306{
1307 int i;
1308 int n = hdspm->period_bytes;
1309 void *buf = hdspm->playback_buffer;
1310
Remy Bruno3cee5a62006-10-16 12:46:32 +02001311 if (buf == NULL)
1312 return;
Takashi Iwai763f3562005-06-03 11:25:34 +02001313
1314 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
1315 memset(buf, 0, n);
1316 buf += HDSPM_CHANNEL_BUFFER_BYTES;
1317 }
1318}
1319
Adrian Knoth0dca1792011-01-26 19:32:14 +01001320static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames)
Takashi Iwai763f3562005-06-03 11:25:34 +02001321{
1322 int n;
1323
1324 spin_lock_irq(&s->lock);
1325
1326 frames >>= 7;
1327 n = 0;
1328 while (frames) {
1329 n++;
1330 frames >>= 1;
1331 }
1332 s->control_register &= ~HDSPM_LatencyMask;
1333 s->control_register |= hdspm_encode_latency(n);
1334
1335 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1336
1337 hdspm_compute_period_size(s);
1338
1339 spin_unlock_irq(&s->lock);
1340
1341 return 0;
1342}
1343
Adrian Knoth0dca1792011-01-26 19:32:14 +01001344static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period)
1345{
1346 u64 freq_const;
1347
1348 if (period == 0)
1349 return 0;
1350
1351 switch (hdspm->io_type) {
1352 case MADI:
1353 case AES32:
1354 freq_const = 110069313433624ULL;
1355 break;
1356 case RayDAT:
1357 case AIO:
1358 freq_const = 104857600000000ULL;
1359 break;
1360 case MADIface:
1361 freq_const = 131072000000000ULL;
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001362 break;
1363 default:
1364 snd_BUG();
1365 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001366 }
1367
1368 return div_u64(freq_const, period);
1369}
1370
1371
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001372static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
1373{
1374 u64 n;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001375
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001376 if (rate >= 112000)
1377 rate /= 4;
1378 else if (rate >= 56000)
1379 rate /= 2;
1380
Adrian Knoth0dca1792011-01-26 19:32:14 +01001381 switch (hdspm->io_type) {
1382 case MADIface:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001383 n = 131072000000000ULL; /* 125 MHz */
1384 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001385 case MADI:
1386 case AES32:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001387 n = 110069313433624ULL; /* 105 MHz */
1388 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001389 case RayDAT:
1390 case AIO:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001391 n = 104857600000000ULL; /* 100 MHz */
1392 break;
1393 default:
1394 snd_BUG();
1395 return;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001396 }
1397
Takashi Iwai3f7440a2009-06-05 17:40:04 +02001398 n = div_u64(n, rate);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001399 /* n should be less than 2^32 for being written to FREQ register */
Takashi Iwaida3cec32008-08-08 17:12:14 +02001400 snd_BUG_ON(n >> 32);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001401 hdspm_write(hdspm, HDSPM_freqReg, (u32)n);
1402}
Takashi Iwai763f3562005-06-03 11:25:34 +02001403
1404/* dummy set rate lets see what happens */
Takashi Iwai98274f02005-11-17 14:52:34 +01001405static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
Takashi Iwai763f3562005-06-03 11:25:34 +02001406{
Takashi Iwai763f3562005-06-03 11:25:34 +02001407 int current_rate;
1408 int rate_bits;
1409 int not_set = 0;
Remy Bruno65345992007-08-31 12:21:08 +02001410 int current_speed, target_speed;
Takashi Iwai763f3562005-06-03 11:25:34 +02001411
1412 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
1413 it (e.g. during module initialization).
1414 */
1415
1416 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
1417
Adrian Knoth0dca1792011-01-26 19:32:14 +01001418 /* SLAVE --- */
Takashi Iwai763f3562005-06-03 11:25:34 +02001419 if (called_internally) {
1420
Adrian Knoth0dca1792011-01-26 19:32:14 +01001421 /* request from ctl or card initialization
1422 just make a warning an remember setting
1423 for future master mode switching */
1424
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001425 snd_printk(KERN_WARNING "HDSPM: "
1426 "Warning: device is not running "
1427 "as a clock master.\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001428 not_set = 1;
1429 } else {
1430
1431 /* hw_param request while in AutoSync mode */
1432 int external_freq =
1433 hdspm_external_sample_rate(hdspm);
1434
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001435 if (hdspm_autosync_ref(hdspm) ==
1436 HDSPM_AUTOSYNC_FROM_NONE) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001437
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001438 snd_printk(KERN_WARNING "HDSPM: "
1439 "Detected no Externel Sync \n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001440 not_set = 1;
1441
1442 } else if (rate != external_freq) {
1443
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001444 snd_printk(KERN_WARNING "HDSPM: "
1445 "Warning: No AutoSync source for "
1446 "requested rate\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001447 not_set = 1;
1448 }
1449 }
1450 }
1451
1452 current_rate = hdspm->system_sample_rate;
1453
1454 /* Changing between Singe, Double and Quad speed is not
1455 allowed if any substreams are open. This is because such a change
1456 causes a shift in the location of the DMA buffers and a reduction
1457 in the number of available buffers.
1458
1459 Note that a similar but essentially insoluble problem exists for
1460 externally-driven rate changes. All we can do is to flag rate
Adrian Knoth0dca1792011-01-26 19:32:14 +01001461 changes in the read/write routines.
Takashi Iwai763f3562005-06-03 11:25:34 +02001462 */
1463
Remy Bruno65345992007-08-31 12:21:08 +02001464 if (current_rate <= 48000)
1465 current_speed = HDSPM_SPEED_SINGLE;
1466 else if (current_rate <= 96000)
1467 current_speed = HDSPM_SPEED_DOUBLE;
1468 else
1469 current_speed = HDSPM_SPEED_QUAD;
1470
1471 if (rate <= 48000)
1472 target_speed = HDSPM_SPEED_SINGLE;
1473 else if (rate <= 96000)
1474 target_speed = HDSPM_SPEED_DOUBLE;
1475 else
1476 target_speed = HDSPM_SPEED_QUAD;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001477
Takashi Iwai763f3562005-06-03 11:25:34 +02001478 switch (rate) {
1479 case 32000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001480 rate_bits = HDSPM_Frequency32KHz;
1481 break;
1482 case 44100:
Takashi Iwai763f3562005-06-03 11:25:34 +02001483 rate_bits = HDSPM_Frequency44_1KHz;
1484 break;
1485 case 48000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001486 rate_bits = HDSPM_Frequency48KHz;
1487 break;
1488 case 64000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001489 rate_bits = HDSPM_Frequency64KHz;
1490 break;
1491 case 88200:
Takashi Iwai763f3562005-06-03 11:25:34 +02001492 rate_bits = HDSPM_Frequency88_2KHz;
1493 break;
1494 case 96000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001495 rate_bits = HDSPM_Frequency96KHz;
1496 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001497 case 128000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001498 rate_bits = HDSPM_Frequency128KHz;
1499 break;
1500 case 176400:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001501 rate_bits = HDSPM_Frequency176_4KHz;
1502 break;
1503 case 192000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001504 rate_bits = HDSPM_Frequency192KHz;
1505 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001506 default:
1507 return -EINVAL;
1508 }
1509
Remy Bruno65345992007-08-31 12:21:08 +02001510 if (current_speed != target_speed
Takashi Iwai763f3562005-06-03 11:25:34 +02001511 && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
1512 snd_printk
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001513 (KERN_ERR "HDSPM: "
Remy Bruno65345992007-08-31 12:21:08 +02001514 "cannot change from %s speed to %s speed mode "
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001515 "(capture PID = %d, playback PID = %d)\n",
Remy Bruno65345992007-08-31 12:21:08 +02001516 hdspm_speed_names[current_speed],
1517 hdspm_speed_names[target_speed],
Takashi Iwai763f3562005-06-03 11:25:34 +02001518 hdspm->capture_pid, hdspm->playback_pid);
1519 return -EBUSY;
1520 }
1521
1522 hdspm->control_register &= ~HDSPM_FrequencyMask;
1523 hdspm->control_register |= rate_bits;
1524 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1525
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001526 /* For AES32, need to set DDS value in FREQ register
1527 For MADI, also apparently */
1528 hdspm_set_dds_value(hdspm, rate);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001529
1530 if (AES32 == hdspm->io_type && rate != current_rate)
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001531 hdspm_write(hdspm, HDSPM_eeprom_wr, 0);
Takashi Iwai763f3562005-06-03 11:25:34 +02001532
1533 hdspm->system_sample_rate = rate;
1534
Adrian Knoth0dca1792011-01-26 19:32:14 +01001535 if (rate <= 48000) {
1536 hdspm->channel_map_in = hdspm->channel_map_in_ss;
1537 hdspm->channel_map_out = hdspm->channel_map_out_ss;
1538 hdspm->max_channels_in = hdspm->ss_in_channels;
1539 hdspm->max_channels_out = hdspm->ss_out_channels;
1540 hdspm->port_names_in = hdspm->port_names_in_ss;
1541 hdspm->port_names_out = hdspm->port_names_out_ss;
1542 } else if (rate <= 96000) {
1543 hdspm->channel_map_in = hdspm->channel_map_in_ds;
1544 hdspm->channel_map_out = hdspm->channel_map_out_ds;
1545 hdspm->max_channels_in = hdspm->ds_in_channels;
1546 hdspm->max_channels_out = hdspm->ds_out_channels;
1547 hdspm->port_names_in = hdspm->port_names_in_ds;
1548 hdspm->port_names_out = hdspm->port_names_out_ds;
1549 } else {
1550 hdspm->channel_map_in = hdspm->channel_map_in_qs;
1551 hdspm->channel_map_out = hdspm->channel_map_out_qs;
1552 hdspm->max_channels_in = hdspm->qs_in_channels;
1553 hdspm->max_channels_out = hdspm->qs_out_channels;
1554 hdspm->port_names_in = hdspm->port_names_in_qs;
1555 hdspm->port_names_out = hdspm->port_names_out_qs;
1556 }
1557
Takashi Iwai763f3562005-06-03 11:25:34 +02001558 if (not_set != 0)
1559 return -1;
1560
1561 return 0;
1562}
1563
1564/* mainly for init to 0 on load */
Takashi Iwai98274f02005-11-17 14:52:34 +01001565static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
Takashi Iwai763f3562005-06-03 11:25:34 +02001566{
1567 int i, j;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001568 unsigned int gain;
1569
1570 if (sgain > UNITY_GAIN)
1571 gain = UNITY_GAIN;
1572 else if (sgain < 0)
1573 gain = 0;
1574 else
1575 gain = sgain;
Takashi Iwai763f3562005-06-03 11:25:34 +02001576
1577 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
1578 for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
1579 hdspm_write_in_gain(hdspm, i, j, gain);
1580 hdspm_write_pb_gain(hdspm, i, j, gain);
1581 }
1582}
1583
1584/*----------------------------------------------------------------------------
1585 MIDI
1586 ----------------------------------------------------------------------------*/
1587
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001588static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm,
1589 int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001590{
1591 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001592 return hdspm_read(hdspm, hdspm->midi[id].dataIn);
Takashi Iwai763f3562005-06-03 11:25:34 +02001593}
1594
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001595static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
1596 int val)
Takashi Iwai763f3562005-06-03 11:25:34 +02001597{
1598 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001599 return hdspm_write(hdspm, hdspm->midi[id].dataOut, val);
Takashi Iwai763f3562005-06-03 11:25:34 +02001600}
1601
Takashi Iwai98274f02005-11-17 14:52:34 +01001602static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001603{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001604 return hdspm_read(hdspm, hdspm->midi[id].statusIn) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001605}
1606
Takashi Iwai98274f02005-11-17 14:52:34 +01001607static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001608{
1609 int fifo_bytes_used;
1610
Adrian Knoth0dca1792011-01-26 19:32:14 +01001611 fifo_bytes_used = hdspm_read(hdspm, hdspm->midi[id].statusOut) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001612
1613 if (fifo_bytes_used < 128)
1614 return 128 - fifo_bytes_used;
1615 else
1616 return 0;
1617}
1618
Denys Vlasenko62cef822008-04-14 13:04:18 +02001619static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001620{
1621 while (snd_hdspm_midi_input_available (hdspm, id))
1622 snd_hdspm_midi_read_byte (hdspm, id);
1623}
1624
Takashi Iwai98274f02005-11-17 14:52:34 +01001625static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001626{
1627 unsigned long flags;
1628 int n_pending;
1629 int to_write;
1630 int i;
1631 unsigned char buf[128];
1632
1633 /* Output is not interrupt driven */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001634
Takashi Iwai763f3562005-06-03 11:25:34 +02001635 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001636 if (hmidi->output &&
1637 !snd_rawmidi_transmit_empty (hmidi->output)) {
1638 n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm,
1639 hmidi->id);
1640 if (n_pending > 0) {
1641 if (n_pending > (int)sizeof (buf))
1642 n_pending = sizeof (buf);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001643
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001644 to_write = snd_rawmidi_transmit (hmidi->output, buf,
1645 n_pending);
1646 if (to_write > 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001647 for (i = 0; i < to_write; ++i)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001648 snd_hdspm_midi_write_byte (hmidi->hdspm,
1649 hmidi->id,
1650 buf[i]);
Takashi Iwai763f3562005-06-03 11:25:34 +02001651 }
1652 }
1653 }
1654 spin_unlock_irqrestore (&hmidi->lock, flags);
1655 return 0;
1656}
1657
Takashi Iwai98274f02005-11-17 14:52:34 +01001658static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001659{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001660 unsigned char buf[128]; /* this buffer is designed to match the MIDI
1661 * input FIFO size
1662 */
Takashi Iwai763f3562005-06-03 11:25:34 +02001663 unsigned long flags;
1664 int n_pending;
1665 int i;
1666
1667 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001668 n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id);
1669 if (n_pending > 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001670 if (hmidi->input) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001671 if (n_pending > (int)sizeof (buf))
Takashi Iwai763f3562005-06-03 11:25:34 +02001672 n_pending = sizeof (buf);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001673 for (i = 0; i < n_pending; ++i)
1674 buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm,
1675 hmidi->id);
1676 if (n_pending)
1677 snd_rawmidi_receive (hmidi->input, buf,
1678 n_pending);
Takashi Iwai763f3562005-06-03 11:25:34 +02001679 } else {
1680 /* flush the MIDI input FIFO */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001681 while (n_pending--)
1682 snd_hdspm_midi_read_byte (hmidi->hdspm,
1683 hmidi->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02001684 }
1685 }
1686 hmidi->pending = 0;
Adrian Knothc0da0012011-06-12 17:26:17 +02001687 spin_unlock_irqrestore(&hmidi->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001688
Adrian Knothc0da0012011-06-12 17:26:17 +02001689 spin_lock_irqsave(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001690 hmidi->hdspm->control_register |= hmidi->ie;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001691 hdspm_write(hmidi->hdspm, HDSPM_controlRegister,
1692 hmidi->hdspm->control_register);
Adrian Knothc0da0012011-06-12 17:26:17 +02001693 spin_unlock_irqrestore(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001694
Takashi Iwai763f3562005-06-03 11:25:34 +02001695 return snd_hdspm_midi_output_write (hmidi);
1696}
1697
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001698static void
1699snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001700{
Takashi Iwai98274f02005-11-17 14:52:34 +01001701 struct hdspm *hdspm;
1702 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001703 unsigned long flags;
Takashi Iwai763f3562005-06-03 11:25:34 +02001704
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001705 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001706 hdspm = hmidi->hdspm;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001707
Takashi Iwai763f3562005-06-03 11:25:34 +02001708 spin_lock_irqsave (&hdspm->lock, flags);
1709 if (up) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001710 if (!(hdspm->control_register & hmidi->ie)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001711 snd_hdspm_flush_midi_input (hdspm, hmidi->id);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001712 hdspm->control_register |= hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001713 }
1714 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001715 hdspm->control_register &= ~hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001716 }
1717
1718 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1719 spin_unlock_irqrestore (&hdspm->lock, flags);
1720}
1721
1722static void snd_hdspm_midi_output_timer(unsigned long data)
1723{
Takashi Iwai98274f02005-11-17 14:52:34 +01001724 struct hdspm_midi *hmidi = (struct hdspm_midi *) data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001725 unsigned long flags;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001726
Takashi Iwai763f3562005-06-03 11:25:34 +02001727 snd_hdspm_midi_output_write(hmidi);
1728 spin_lock_irqsave (&hmidi->lock, flags);
1729
1730 /* this does not bump hmidi->istimer, because the
1731 kernel automatically removed the timer when it
1732 expired, and we are now adding it back, thus
Adrian Knoth0dca1792011-01-26 19:32:14 +01001733 leaving istimer wherever it was set before.
Takashi Iwai763f3562005-06-03 11:25:34 +02001734 */
1735
1736 if (hmidi->istimer) {
1737 hmidi->timer.expires = 1 + jiffies;
1738 add_timer(&hmidi->timer);
1739 }
1740
1741 spin_unlock_irqrestore (&hmidi->lock, flags);
1742}
1743
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001744static void
1745snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001746{
Takashi Iwai98274f02005-11-17 14:52:34 +01001747 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001748 unsigned long flags;
1749
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001750 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001751 spin_lock_irqsave (&hmidi->lock, flags);
1752 if (up) {
1753 if (!hmidi->istimer) {
1754 init_timer(&hmidi->timer);
1755 hmidi->timer.function = snd_hdspm_midi_output_timer;
1756 hmidi->timer.data = (unsigned long) hmidi;
1757 hmidi->timer.expires = 1 + jiffies;
1758 add_timer(&hmidi->timer);
1759 hmidi->istimer++;
1760 }
1761 } else {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001762 if (hmidi->istimer && --hmidi->istimer <= 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02001763 del_timer (&hmidi->timer);
Takashi Iwai763f3562005-06-03 11:25:34 +02001764 }
1765 spin_unlock_irqrestore (&hmidi->lock, flags);
1766 if (up)
1767 snd_hdspm_midi_output_write(hmidi);
1768}
1769
Takashi Iwai98274f02005-11-17 14:52:34 +01001770static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001771{
Takashi Iwai98274f02005-11-17 14:52:34 +01001772 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001773
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001774 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001775 spin_lock_irq (&hmidi->lock);
1776 snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
1777 hmidi->input = substream;
1778 spin_unlock_irq (&hmidi->lock);
1779
1780 return 0;
1781}
1782
Takashi Iwai98274f02005-11-17 14:52:34 +01001783static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001784{
Takashi Iwai98274f02005-11-17 14:52:34 +01001785 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001786
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001787 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001788 spin_lock_irq (&hmidi->lock);
1789 hmidi->output = 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_input_close(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
1799 snd_hdspm_midi_input_trigger (substream, 0);
1800
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001801 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001802 spin_lock_irq (&hmidi->lock);
1803 hmidi->input = NULL;
1804 spin_unlock_irq (&hmidi->lock);
1805
1806 return 0;
1807}
1808
Takashi Iwai98274f02005-11-17 14:52:34 +01001809static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001810{
Takashi Iwai98274f02005-11-17 14:52:34 +01001811 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001812
1813 snd_hdspm_midi_output_trigger (substream, 0);
1814
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001815 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001816 spin_lock_irq (&hmidi->lock);
1817 hmidi->output = NULL;
1818 spin_unlock_irq (&hmidi->lock);
1819
1820 return 0;
1821}
1822
Takashi Iwai98274f02005-11-17 14:52:34 +01001823static struct snd_rawmidi_ops snd_hdspm_midi_output =
Takashi Iwai763f3562005-06-03 11:25:34 +02001824{
1825 .open = snd_hdspm_midi_output_open,
1826 .close = snd_hdspm_midi_output_close,
1827 .trigger = snd_hdspm_midi_output_trigger,
1828};
1829
Takashi Iwai98274f02005-11-17 14:52:34 +01001830static struct snd_rawmidi_ops snd_hdspm_midi_input =
Takashi Iwai763f3562005-06-03 11:25:34 +02001831{
1832 .open = snd_hdspm_midi_input_open,
1833 .close = snd_hdspm_midi_input_close,
1834 .trigger = snd_hdspm_midi_input_trigger,
1835};
1836
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001837static int __devinit snd_hdspm_create_midi (struct snd_card *card,
1838 struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001839{
1840 int err;
1841 char buf[32];
1842
1843 hdspm->midi[id].id = id;
Takashi Iwai763f3562005-06-03 11:25:34 +02001844 hdspm->midi[id].hdspm = hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +02001845 spin_lock_init (&hdspm->midi[id].lock);
1846
Adrian Knoth0dca1792011-01-26 19:32:14 +01001847 if (0 == id) {
1848 if (MADIface == hdspm->io_type) {
1849 /* MIDI-over-MADI on HDSPe MADIface */
1850 hdspm->midi[0].dataIn = HDSPM_midiDataIn2;
1851 hdspm->midi[0].statusIn = HDSPM_midiStatusIn2;
1852 hdspm->midi[0].dataOut = HDSPM_midiDataOut2;
1853 hdspm->midi[0].statusOut = HDSPM_midiStatusOut2;
1854 hdspm->midi[0].ie = HDSPM_Midi2InterruptEnable;
1855 hdspm->midi[0].irq = HDSPM_midi2IRQPending;
1856 } else {
1857 hdspm->midi[0].dataIn = HDSPM_midiDataIn0;
1858 hdspm->midi[0].statusIn = HDSPM_midiStatusIn0;
1859 hdspm->midi[0].dataOut = HDSPM_midiDataOut0;
1860 hdspm->midi[0].statusOut = HDSPM_midiStatusOut0;
1861 hdspm->midi[0].ie = HDSPM_Midi0InterruptEnable;
1862 hdspm->midi[0].irq = HDSPM_midi0IRQPending;
1863 }
1864 } else if (1 == id) {
1865 hdspm->midi[1].dataIn = HDSPM_midiDataIn1;
1866 hdspm->midi[1].statusIn = HDSPM_midiStatusIn1;
1867 hdspm->midi[1].dataOut = HDSPM_midiDataOut1;
1868 hdspm->midi[1].statusOut = HDSPM_midiStatusOut1;
1869 hdspm->midi[1].ie = HDSPM_Midi1InterruptEnable;
1870 hdspm->midi[1].irq = HDSPM_midi1IRQPending;
1871 } else if ((2 == id) && (MADI == hdspm->io_type)) {
1872 /* MIDI-over-MADI on HDSPe MADI */
1873 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1874 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1875 hdspm->midi[2].dataOut = HDSPM_midiDataOut2;
1876 hdspm->midi[2].statusOut = HDSPM_midiStatusOut2;
1877 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1878 hdspm->midi[2].irq = HDSPM_midi2IRQPending;
1879 } else if (2 == id) {
1880 /* TCO MTC, read only */
1881 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1882 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1883 hdspm->midi[2].dataOut = -1;
1884 hdspm->midi[2].statusOut = -1;
1885 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1886 hdspm->midi[2].irq = HDSPM_midi2IRQPendingAES;
1887 } else if (3 == id) {
1888 /* TCO MTC on HDSPe MADI */
1889 hdspm->midi[3].dataIn = HDSPM_midiDataIn3;
1890 hdspm->midi[3].statusIn = HDSPM_midiStatusIn3;
1891 hdspm->midi[3].dataOut = -1;
1892 hdspm->midi[3].statusOut = -1;
1893 hdspm->midi[3].ie = HDSPM_Midi3InterruptEnable;
1894 hdspm->midi[3].irq = HDSPM_midi3IRQPending;
1895 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001896
Adrian Knoth0dca1792011-01-26 19:32:14 +01001897 if ((id < 2) || ((2 == id) && ((MADI == hdspm->io_type) ||
1898 (MADIface == hdspm->io_type)))) {
1899 if ((id == 0) && (MADIface == hdspm->io_type)) {
1900 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1901 } else if ((id == 2) && (MADI == hdspm->io_type)) {
1902 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1903 } else {
1904 sprintf(buf, "%s MIDI %d", card->shortname, id+1);
1905 }
1906 err = snd_rawmidi_new(card, buf, id, 1, 1,
1907 &hdspm->midi[id].rmidi);
1908 if (err < 0)
1909 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02001910
Adrian Knoth0dca1792011-01-26 19:32:14 +01001911 sprintf(hdspm->midi[id].rmidi->name, "%s MIDI %d",
1912 card->id, id+1);
1913 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
Takashi Iwai763f3562005-06-03 11:25:34 +02001914
Adrian Knoth0dca1792011-01-26 19:32:14 +01001915 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1916 SNDRV_RAWMIDI_STREAM_OUTPUT,
1917 &snd_hdspm_midi_output);
1918 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1919 SNDRV_RAWMIDI_STREAM_INPUT,
1920 &snd_hdspm_midi_input);
1921
1922 hdspm->midi[id].rmidi->info_flags |=
1923 SNDRV_RAWMIDI_INFO_OUTPUT |
1924 SNDRV_RAWMIDI_INFO_INPUT |
1925 SNDRV_RAWMIDI_INFO_DUPLEX;
1926 } else {
1927 /* TCO MTC, read only */
1928 sprintf(buf, "%s MTC %d", card->shortname, id+1);
1929 err = snd_rawmidi_new(card, buf, id, 1, 1,
1930 &hdspm->midi[id].rmidi);
1931 if (err < 0)
1932 return err;
1933
1934 sprintf(hdspm->midi[id].rmidi->name,
1935 "%s MTC %d", card->id, id+1);
1936 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
1937
1938 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1939 SNDRV_RAWMIDI_STREAM_INPUT,
1940 &snd_hdspm_midi_input);
1941
1942 hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
1943 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001944
1945 return 0;
1946}
1947
1948
1949static void hdspm_midi_tasklet(unsigned long arg)
1950{
Takashi Iwai98274f02005-11-17 14:52:34 +01001951 struct hdspm *hdspm = (struct hdspm *)arg;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001952 int i = 0;
1953
1954 while (i < hdspm->midiPorts) {
1955 if (hdspm->midi[i].pending)
1956 snd_hdspm_midi_input_read(&hdspm->midi[i]);
1957
1958 i++;
1959 }
1960}
Takashi Iwai763f3562005-06-03 11:25:34 +02001961
1962
1963/*-----------------------------------------------------------------------------
1964 Status Interface
1965 ----------------------------------------------------------------------------*/
1966
1967/* get the system sample rate which is set */
1968
Adrian Knoth0dca1792011-01-26 19:32:14 +01001969
1970/**
1971 * Calculate the real sample rate from the
1972 * current DDS value.
1973 **/
1974static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
1975{
1976 unsigned int period, rate;
1977
1978 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
1979 rate = hdspm_calc_dds_value(hdspm, period);
1980
1981 return rate;
1982}
1983
1984
Takashi Iwai763f3562005-06-03 11:25:34 +02001985#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001986{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001987 .name = xname, \
1988 .index = xindex, \
1989 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1990 .info = snd_hdspm_info_system_sample_rate, \
1991 .get = snd_hdspm_get_system_sample_rate \
1992}
1993
Takashi Iwai98274f02005-11-17 14:52:34 +01001994static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
1995 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001996{
1997 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1998 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001999 uinfo->value.integer.min = 27000;
2000 uinfo->value.integer.max = 207000;
2001 uinfo->value.integer.step = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002002 return 0;
2003}
2004
Adrian Knoth0dca1792011-01-26 19:32:14 +01002005
Takashi Iwai98274f02005-11-17 14:52:34 +01002006static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
2007 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002008 ucontrol)
2009{
Takashi Iwai98274f02005-11-17 14:52:34 +01002010 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002011
Adrian Knoth0dca1792011-01-26 19:32:14 +01002012 ucontrol->value.integer.value[0] = hdspm_get_system_sample_rate(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002013 return 0;
2014}
2015
Adrian Knoth0dca1792011-01-26 19:32:14 +01002016
2017/**
2018 * Returns the WordClock sample rate class for the given card.
2019 **/
2020static int hdspm_get_wc_sample_rate(struct hdspm *hdspm)
2021{
2022 int status;
2023
2024 switch (hdspm->io_type) {
2025 case RayDAT:
2026 case AIO:
2027 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2028 return (status >> 16) & 0xF;
2029 break;
2030 default:
2031 break;
2032 }
2033
2034
2035 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002036}
2037
Adrian Knoth0dca1792011-01-26 19:32:14 +01002038
2039/**
2040 * Returns the TCO sample rate class for the given card.
2041 **/
2042static int hdspm_get_tco_sample_rate(struct hdspm *hdspm)
2043{
2044 int status;
2045
2046 if (hdspm->tco) {
2047 switch (hdspm->io_type) {
2048 case RayDAT:
2049 case AIO:
2050 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2051 return (status >> 20) & 0xF;
2052 break;
2053 default:
2054 break;
2055 }
2056 }
2057
2058 return 0;
2059}
2060
2061
2062/**
2063 * Returns the SYNC_IN sample rate class for the given card.
2064 **/
2065static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm)
2066{
2067 int status;
2068
2069 if (hdspm->tco) {
2070 switch (hdspm->io_type) {
2071 case RayDAT:
2072 case AIO:
2073 status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2074 return (status >> 12) & 0xF;
2075 break;
2076 default:
2077 break;
2078 }
2079 }
2080
2081 return 0;
2082}
2083
2084
2085/**
2086 * Returns the sample rate class for input source <idx> for
2087 * 'new style' cards like the AIO and RayDAT.
2088 **/
2089static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
2090{
2091 int status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2092
2093 return (status >> (idx*4)) & 0xF;
2094}
2095
2096
2097
2098#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
2099{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2100 .name = xname, \
2101 .private_value = xindex, \
2102 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2103 .info = snd_hdspm_info_autosync_sample_rate, \
2104 .get = snd_hdspm_get_autosync_sample_rate \
2105}
2106
2107
Takashi Iwai98274f02005-11-17 14:52:34 +01002108static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2109 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002110{
Takashi Iwai763f3562005-06-03 11:25:34 +02002111 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2112 uinfo->count = 1;
2113 uinfo->value.enumerated.items = 10;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002114
Takashi Iwai763f3562005-06-03 11:25:34 +02002115 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
Adrian Knoth0dca1792011-01-26 19:32:14 +01002116 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002117 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002118 texts_freq[uinfo->value.enumerated.item]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002119 return 0;
2120}
2121
Adrian Knoth0dca1792011-01-26 19:32:14 +01002122
Takashi Iwai98274f02005-11-17 14:52:34 +01002123static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2124 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002125 ucontrol)
2126{
Takashi Iwai98274f02005-11-17 14:52:34 +01002127 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002128
Adrian Knoth0dca1792011-01-26 19:32:14 +01002129 switch (hdspm->io_type) {
2130 case RayDAT:
2131 switch (kcontrol->private_value) {
2132 case 0:
2133 ucontrol->value.enumerated.item[0] =
2134 hdspm_get_wc_sample_rate(hdspm);
2135 break;
2136 case 7:
2137 ucontrol->value.enumerated.item[0] =
2138 hdspm_get_tco_sample_rate(hdspm);
2139 break;
2140 case 8:
2141 ucontrol->value.enumerated.item[0] =
2142 hdspm_get_sync_in_sample_rate(hdspm);
2143 break;
2144 default:
2145 ucontrol->value.enumerated.item[0] =
2146 hdspm_get_s1_sample_rate(hdspm,
2147 kcontrol->private_value-1);
2148 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002149
Adrian Knoth0dca1792011-01-26 19:32:14 +01002150 case AIO:
2151 switch (kcontrol->private_value) {
2152 case 0: /* WC */
2153 ucontrol->value.enumerated.item[0] =
2154 hdspm_get_wc_sample_rate(hdspm);
2155 break;
2156 case 4: /* TCO */
2157 ucontrol->value.enumerated.item[0] =
2158 hdspm_get_tco_sample_rate(hdspm);
2159 break;
2160 case 5: /* SYNC_IN */
2161 ucontrol->value.enumerated.item[0] =
2162 hdspm_get_sync_in_sample_rate(hdspm);
2163 break;
2164 default:
2165 ucontrol->value.enumerated.item[0] =
2166 hdspm_get_s1_sample_rate(hdspm,
2167 ucontrol->id.index-1);
2168 }
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002169
2170 case AES32:
2171
2172 switch (kcontrol->private_value) {
2173 case 0: /* WC */
2174 ucontrol->value.enumerated.item[0] =
2175 hdspm_get_wc_sample_rate(hdspm);
2176 break;
2177 case 9: /* TCO */
2178 ucontrol->value.enumerated.item[0] =
2179 hdspm_get_tco_sample_rate(hdspm);
2180 break;
2181 case 10: /* SYNC_IN */
2182 ucontrol->value.enumerated.item[0] =
2183 hdspm_get_sync_in_sample_rate(hdspm);
2184 break;
2185 default: /* AES1 to AES8 */
2186 ucontrol->value.enumerated.item[0] =
2187 hdspm_get_s1_sample_rate(hdspm,
2188 kcontrol->private_value-1);
2189 break;
2190
2191 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002192 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002193 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002194 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002195
Takashi Iwai763f3562005-06-03 11:25:34 +02002196 return 0;
2197}
2198
Adrian Knoth0dca1792011-01-26 19:32:14 +01002199
Takashi Iwai763f3562005-06-03 11:25:34 +02002200#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002201{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2202 .name = xname, \
2203 .index = xindex, \
2204 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2205 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2206 .info = snd_hdspm_info_system_clock_mode, \
2207 .get = snd_hdspm_get_system_clock_mode, \
2208 .put = snd_hdspm_put_system_clock_mode, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002209}
2210
2211
Adrian Knoth0dca1792011-01-26 19:32:14 +01002212/**
2213 * Returns the system clock mode for the given card.
2214 * @returns 0 - master, 1 - slave
2215 **/
2216static int hdspm_system_clock_mode(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002217{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002218 switch (hdspm->io_type) {
2219 case AIO:
2220 case RayDAT:
2221 if (hdspm->settings_register & HDSPM_c0Master)
2222 return 0;
2223 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002224
Adrian Knoth0dca1792011-01-26 19:32:14 +01002225 default:
2226 if (hdspm->control_register & HDSPM_ClockModeMaster)
2227 return 0;
2228 }
2229
Takashi Iwai763f3562005-06-03 11:25:34 +02002230 return 1;
2231}
2232
Adrian Knoth0dca1792011-01-26 19:32:14 +01002233
2234/**
2235 * Sets the system clock mode.
2236 * @param mode 0 - master, 1 - slave
2237 **/
2238static void hdspm_set_system_clock_mode(struct hdspm *hdspm, int mode)
2239{
2240 switch (hdspm->io_type) {
2241 case AIO:
2242 case RayDAT:
2243 if (0 == mode)
2244 hdspm->settings_register |= HDSPM_c0Master;
2245 else
2246 hdspm->settings_register &= ~HDSPM_c0Master;
2247
2248 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2249 break;
2250
2251 default:
2252 if (0 == mode)
2253 hdspm->control_register |= HDSPM_ClockModeMaster;
2254 else
2255 hdspm->control_register &= ~HDSPM_ClockModeMaster;
2256
2257 hdspm_write(hdspm, HDSPM_controlRegister,
2258 hdspm->control_register);
2259 }
2260}
2261
2262
Takashi Iwai98274f02005-11-17 14:52:34 +01002263static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
2264 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002265{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002266 static char *texts[] = { "Master", "AutoSync" };
Takashi Iwai763f3562005-06-03 11:25:34 +02002267
2268 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2269 uinfo->count = 1;
2270 uinfo->value.enumerated.items = 2;
2271 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2272 uinfo->value.enumerated.item =
2273 uinfo->value.enumerated.items - 1;
2274 strcpy(uinfo->value.enumerated.name,
2275 texts[uinfo->value.enumerated.item]);
2276 return 0;
2277}
2278
Takashi Iwai98274f02005-11-17 14:52:34 +01002279static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
2280 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002281{
Takashi Iwai98274f02005-11-17 14:52:34 +01002282 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002283
Adrian Knoth0dca1792011-01-26 19:32:14 +01002284 ucontrol->value.enumerated.item[0] = hdspm_system_clock_mode(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002285 return 0;
2286}
2287
Adrian Knoth0dca1792011-01-26 19:32:14 +01002288static int snd_hdspm_put_system_clock_mode(struct snd_kcontrol *kcontrol,
2289 struct snd_ctl_elem_value *ucontrol)
2290{
2291 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2292 int val;
2293
2294 if (!snd_hdspm_use_is_exclusive(hdspm))
2295 return -EBUSY;
2296
2297 val = ucontrol->value.enumerated.item[0];
2298 if (val < 0)
2299 val = 0;
2300 else if (val > 1)
2301 val = 1;
2302
2303 hdspm_set_system_clock_mode(hdspm, val);
2304
2305 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002306}
2307
Adrian Knoth0dca1792011-01-26 19:32:14 +01002308
2309#define HDSPM_INTERNAL_CLOCK(xname, xindex) \
2310{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2311 .name = xname, \
2312 .index = xindex, \
2313 .info = snd_hdspm_info_clock_source, \
2314 .get = snd_hdspm_get_clock_source, \
2315 .put = snd_hdspm_put_clock_source \
2316}
2317
2318
Takashi Iwai98274f02005-11-17 14:52:34 +01002319static int hdspm_clock_source(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002320{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002321 switch (hdspm->system_sample_rate) {
2322 case 32000: return 0;
2323 case 44100: return 1;
2324 case 48000: return 2;
2325 case 64000: return 3;
2326 case 88200: return 4;
2327 case 96000: return 5;
2328 case 128000: return 6;
2329 case 176400: return 7;
2330 case 192000: return 8;
Takashi Iwai763f3562005-06-03 11:25:34 +02002331 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002332
2333 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002334}
2335
Takashi Iwai98274f02005-11-17 14:52:34 +01002336static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
Takashi Iwai763f3562005-06-03 11:25:34 +02002337{
2338 int rate;
2339 switch (mode) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002340 case 0:
2341 rate = 32000; break;
2342 case 1:
2343 rate = 44100; break;
2344 case 2:
2345 rate = 48000; break;
2346 case 3:
2347 rate = 64000; break;
2348 case 4:
2349 rate = 88200; break;
2350 case 5:
2351 rate = 96000; break;
2352 case 6:
2353 rate = 128000; break;
2354 case 7:
2355 rate = 176400; break;
2356 case 8:
2357 rate = 192000; break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002358 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002359 rate = 48000;
Takashi Iwai763f3562005-06-03 11:25:34 +02002360 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002361 hdspm_set_rate(hdspm, rate, 1);
2362 return 0;
2363}
2364
Takashi Iwai98274f02005-11-17 14:52:34 +01002365static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
2366 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002367{
Takashi Iwai763f3562005-06-03 11:25:34 +02002368 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2369 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002370 uinfo->value.enumerated.items = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002371
2372 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2373 uinfo->value.enumerated.item =
2374 uinfo->value.enumerated.items - 1;
2375
2376 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002377 texts_freq[uinfo->value.enumerated.item+1]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002378
2379 return 0;
2380}
2381
Takashi Iwai98274f02005-11-17 14:52:34 +01002382static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
2383 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002384{
Takashi Iwai98274f02005-11-17 14:52:34 +01002385 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002386
2387 ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
2388 return 0;
2389}
2390
Takashi Iwai98274f02005-11-17 14:52:34 +01002391static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
2392 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002393{
Takashi Iwai98274f02005-11-17 14:52:34 +01002394 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002395 int change;
2396 int val;
2397
2398 if (!snd_hdspm_use_is_exclusive(hdspm))
2399 return -EBUSY;
2400 val = ucontrol->value.enumerated.item[0];
2401 if (val < 0)
2402 val = 0;
Remy Bruno65345992007-08-31 12:21:08 +02002403 if (val > 9)
2404 val = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002405 spin_lock_irq(&hdspm->lock);
2406 if (val != hdspm_clock_source(hdspm))
2407 change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
2408 else
2409 change = 0;
2410 spin_unlock_irq(&hdspm->lock);
2411 return change;
2412}
2413
Adrian Knoth0dca1792011-01-26 19:32:14 +01002414
Takashi Iwai763f3562005-06-03 11:25:34 +02002415#define HDSPM_PREF_SYNC_REF(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002416{.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2417 .name = xname, \
2418 .index = xindex, \
2419 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2420 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2421 .info = snd_hdspm_info_pref_sync_ref, \
2422 .get = snd_hdspm_get_pref_sync_ref, \
2423 .put = snd_hdspm_put_pref_sync_ref \
Takashi Iwai763f3562005-06-03 11:25:34 +02002424}
2425
Adrian Knoth0dca1792011-01-26 19:32:14 +01002426
2427/**
2428 * Returns the current preferred sync reference setting.
2429 * The semantics of the return value are depending on the
2430 * card, please see the comments for clarification.
2431 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002432static int hdspm_pref_sync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002433{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002434 switch (hdspm->io_type) {
2435 case AES32:
Remy Bruno3cee5a62006-10-16 12:46:32 +02002436 switch (hdspm->control_register & HDSPM_SyncRefMask) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002437 case 0: return 0; /* WC */
2438 case HDSPM_SyncRef0: return 1; /* AES 1 */
2439 case HDSPM_SyncRef1: return 2; /* AES 2 */
2440 case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; /* AES 3 */
2441 case HDSPM_SyncRef2: return 4; /* AES 4 */
2442 case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; /* AES 5 */
2443 case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; /* AES 6 */
2444 case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0:
2445 return 7; /* AES 7 */
2446 case HDSPM_SyncRef3: return 8; /* AES 8 */
2447 case HDSPM_SyncRef3+HDSPM_SyncRef0: return 9; /* TCO */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002448 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002449 break;
2450
2451 case MADI:
2452 case MADIface:
2453 if (hdspm->tco) {
2454 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2455 case 0: return 0; /* WC */
2456 case HDSPM_SyncRef0: return 1; /* MADI */
2457 case HDSPM_SyncRef1: return 2; /* TCO */
2458 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2459 return 3; /* SYNC_IN */
2460 }
2461 } else {
2462 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2463 case 0: return 0; /* WC */
2464 case HDSPM_SyncRef0: return 1; /* MADI */
2465 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2466 return 2; /* SYNC_IN */
2467 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02002468 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002469 break;
2470
2471 case RayDAT:
2472 if (hdspm->tco) {
2473 switch ((hdspm->settings_register &
2474 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2475 case 0: return 0; /* WC */
2476 case 3: return 1; /* ADAT 1 */
2477 case 4: return 2; /* ADAT 2 */
2478 case 5: return 3; /* ADAT 3 */
2479 case 6: return 4; /* ADAT 4 */
2480 case 1: return 5; /* AES */
2481 case 2: return 6; /* SPDIF */
2482 case 9: return 7; /* TCO */
2483 case 10: return 8; /* SYNC_IN */
2484 }
2485 } else {
2486 switch ((hdspm->settings_register &
2487 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2488 case 0: return 0; /* WC */
2489 case 3: return 1; /* ADAT 1 */
2490 case 4: return 2; /* ADAT 2 */
2491 case 5: return 3; /* ADAT 3 */
2492 case 6: return 4; /* ADAT 4 */
2493 case 1: return 5; /* AES */
2494 case 2: return 6; /* SPDIF */
2495 case 10: return 7; /* SYNC_IN */
2496 }
2497 }
2498
2499 break;
2500
2501 case AIO:
2502 if (hdspm->tco) {
2503 switch ((hdspm->settings_register &
2504 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2505 case 0: return 0; /* WC */
2506 case 3: return 1; /* ADAT */
2507 case 1: return 2; /* AES */
2508 case 2: return 3; /* SPDIF */
2509 case 9: return 4; /* TCO */
2510 case 10: return 5; /* SYNC_IN */
2511 }
2512 } else {
2513 switch ((hdspm->settings_register &
2514 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2515 case 0: return 0; /* WC */
2516 case 3: return 1; /* ADAT */
2517 case 1: return 2; /* AES */
2518 case 2: return 3; /* SPDIF */
2519 case 10: return 4; /* SYNC_IN */
2520 }
2521 }
2522
2523 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002524 }
2525
Adrian Knoth0dca1792011-01-26 19:32:14 +01002526 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002527}
2528
Adrian Knoth0dca1792011-01-26 19:32:14 +01002529
2530/**
2531 * Set the preferred sync reference to <pref>. The semantics
2532 * of <pref> are depending on the card type, see the comments
2533 * for clarification.
2534 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002535static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
Takashi Iwai763f3562005-06-03 11:25:34 +02002536{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002537 int p = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002538
Adrian Knoth0dca1792011-01-26 19:32:14 +01002539 switch (hdspm->io_type) {
2540 case AES32:
2541 hdspm->control_register &= ~HDSPM_SyncRefMask;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002542 switch (pref) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002543 case 0: /* WC */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002544 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002545 case 1: /* AES 1 */
2546 hdspm->control_register |= HDSPM_SyncRef0;
2547 break;
2548 case 2: /* AES 2 */
2549 hdspm->control_register |= HDSPM_SyncRef1;
2550 break;
2551 case 3: /* AES 3 */
2552 hdspm->control_register |=
2553 HDSPM_SyncRef1+HDSPM_SyncRef0;
2554 break;
2555 case 4: /* AES 4 */
2556 hdspm->control_register |= HDSPM_SyncRef2;
2557 break;
2558 case 5: /* AES 5 */
2559 hdspm->control_register |=
2560 HDSPM_SyncRef2+HDSPM_SyncRef0;
2561 break;
2562 case 6: /* AES 6 */
2563 hdspm->control_register |=
2564 HDSPM_SyncRef2+HDSPM_SyncRef1;
2565 break;
2566 case 7: /* AES 7 */
2567 hdspm->control_register |=
2568 HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
2569 break;
2570 case 8: /* AES 8 */
2571 hdspm->control_register |= HDSPM_SyncRef3;
2572 break;
2573 case 9: /* TCO */
2574 hdspm->control_register |=
2575 HDSPM_SyncRef3+HDSPM_SyncRef0;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002576 break;
2577 default:
2578 return -1;
2579 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002580
2581 break;
2582
2583 case MADI:
2584 case MADIface:
2585 hdspm->control_register &= ~HDSPM_SyncRefMask;
2586 if (hdspm->tco) {
2587 switch (pref) {
2588 case 0: /* WC */
2589 break;
2590 case 1: /* MADI */
2591 hdspm->control_register |= HDSPM_SyncRef0;
2592 break;
2593 case 2: /* TCO */
2594 hdspm->control_register |= HDSPM_SyncRef1;
2595 break;
2596 case 3: /* SYNC_IN */
2597 hdspm->control_register |=
2598 HDSPM_SyncRef0+HDSPM_SyncRef1;
2599 break;
2600 default:
2601 return -1;
2602 }
2603 } else {
2604 switch (pref) {
2605 case 0: /* WC */
2606 break;
2607 case 1: /* MADI */
2608 hdspm->control_register |= HDSPM_SyncRef0;
2609 break;
2610 case 2: /* SYNC_IN */
2611 hdspm->control_register |=
2612 HDSPM_SyncRef0+HDSPM_SyncRef1;
2613 break;
2614 default:
2615 return -1;
2616 }
2617 }
2618
2619 break;
2620
2621 case RayDAT:
2622 if (hdspm->tco) {
2623 switch (pref) {
2624 case 0: p = 0; break; /* WC */
2625 case 1: p = 3; break; /* ADAT 1 */
2626 case 2: p = 4; break; /* ADAT 2 */
2627 case 3: p = 5; break; /* ADAT 3 */
2628 case 4: p = 6; break; /* ADAT 4 */
2629 case 5: p = 1; break; /* AES */
2630 case 6: p = 2; break; /* SPDIF */
2631 case 7: p = 9; break; /* TCO */
2632 case 8: p = 10; break; /* SYNC_IN */
2633 default: return -1;
2634 }
2635 } else {
2636 switch (pref) {
2637 case 0: p = 0; break; /* WC */
2638 case 1: p = 3; break; /* ADAT 1 */
2639 case 2: p = 4; break; /* ADAT 2 */
2640 case 3: p = 5; break; /* ADAT 3 */
2641 case 4: p = 6; break; /* ADAT 4 */
2642 case 5: p = 1; break; /* AES */
2643 case 6: p = 2; break; /* SPDIF */
2644 case 7: p = 10; break; /* SYNC_IN */
2645 default: return -1;
2646 }
2647 }
2648 break;
2649
2650 case AIO:
2651 if (hdspm->tco) {
2652 switch (pref) {
2653 case 0: p = 0; break; /* WC */
2654 case 1: p = 3; break; /* ADAT */
2655 case 2: p = 1; break; /* AES */
2656 case 3: p = 2; break; /* SPDIF */
2657 case 4: p = 9; break; /* TCO */
2658 case 5: p = 10; break; /* SYNC_IN */
2659 default: return -1;
2660 }
2661 } else {
2662 switch (pref) {
2663 case 0: p = 0; break; /* WC */
2664 case 1: p = 3; break; /* ADAT */
2665 case 2: p = 1; break; /* AES */
2666 case 3: p = 2; break; /* SPDIF */
2667 case 4: p = 10; break; /* SYNC_IN */
2668 default: return -1;
2669 }
2670 }
2671 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002672 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002673
2674 switch (hdspm->io_type) {
2675 case RayDAT:
2676 case AIO:
2677 hdspm->settings_register &= ~HDSPM_c0_SyncRefMask;
2678 hdspm->settings_register |= HDSPM_c0_SyncRef0 * p;
2679 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2680 break;
2681
2682 case MADI:
2683 case MADIface:
2684 case AES32:
2685 hdspm_write(hdspm, HDSPM_controlRegister,
2686 hdspm->control_register);
2687 }
2688
Takashi Iwai763f3562005-06-03 11:25:34 +02002689 return 0;
2690}
2691
Adrian Knoth0dca1792011-01-26 19:32:14 +01002692
Takashi Iwai98274f02005-11-17 14:52:34 +01002693static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
2694 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002695{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002696 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002697
Adrian Knoth0dca1792011-01-26 19:32:14 +01002698 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2699 uinfo->count = 1;
2700 uinfo->value.enumerated.items = hdspm->texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +02002701
Adrian Knoth0dca1792011-01-26 19:32:14 +01002702 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2703 uinfo->value.enumerated.item =
2704 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002705
Adrian Knoth0dca1792011-01-26 19:32:14 +01002706 strcpy(uinfo->value.enumerated.name,
2707 hdspm->texts_autosync[uinfo->value.enumerated.item]);
Remy Bruno3cee5a62006-10-16 12:46:32 +02002708
Takashi Iwai763f3562005-06-03 11:25:34 +02002709 return 0;
2710}
2711
Takashi Iwai98274f02005-11-17 14:52:34 +01002712static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
2713 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002714{
Takashi Iwai98274f02005-11-17 14:52:34 +01002715 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002716 int psf = hdspm_pref_sync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002717
Adrian Knoth0dca1792011-01-26 19:32:14 +01002718 if (psf >= 0) {
2719 ucontrol->value.enumerated.item[0] = psf;
2720 return 0;
2721 }
2722
2723 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002724}
2725
Takashi Iwai98274f02005-11-17 14:52:34 +01002726static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
2727 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002728{
Takashi Iwai98274f02005-11-17 14:52:34 +01002729 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002730 int val, change = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002731
2732 if (!snd_hdspm_use_is_exclusive(hdspm))
2733 return -EBUSY;
2734
Adrian Knoth0dca1792011-01-26 19:32:14 +01002735 val = ucontrol->value.enumerated.item[0];
2736
2737 if (val < 0)
2738 val = 0;
2739 else if (val >= hdspm->texts_autosync_items)
2740 val = hdspm->texts_autosync_items-1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002741
2742 spin_lock_irq(&hdspm->lock);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002743 if (val != hdspm_pref_sync_ref(hdspm))
2744 change = (0 == hdspm_set_pref_sync_ref(hdspm, val)) ? 1 : 0;
2745
Takashi Iwai763f3562005-06-03 11:25:34 +02002746 spin_unlock_irq(&hdspm->lock);
2747 return change;
2748}
2749
Adrian Knoth0dca1792011-01-26 19:32:14 +01002750
Takashi Iwai763f3562005-06-03 11:25:34 +02002751#define HDSPM_AUTOSYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002752{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002753 .name = xname, \
2754 .index = xindex, \
2755 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2756 .info = snd_hdspm_info_autosync_ref, \
2757 .get = snd_hdspm_get_autosync_ref, \
2758}
2759
Adrian Knoth0dca1792011-01-26 19:32:14 +01002760static int hdspm_autosync_ref(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002761{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002762 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002763 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002764 unsigned int syncref =
2765 (status >> HDSPM_AES32_syncref_bit) & 0xF;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002766 if (syncref == 0)
2767 return HDSPM_AES32_AUTOSYNC_FROM_WORD;
2768 if (syncref <= 8)
2769 return syncref;
2770 return HDSPM_AES32_AUTOSYNC_FROM_NONE;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002771 } else if (MADI == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002772 /* This looks at the autosync selected sync reference */
2773 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Takashi Iwai763f3562005-06-03 11:25:34 +02002774
Remy Bruno3cee5a62006-10-16 12:46:32 +02002775 switch (status2 & HDSPM_SelSyncRefMask) {
2776 case HDSPM_SelSyncRef_WORD:
2777 return HDSPM_AUTOSYNC_FROM_WORD;
2778 case HDSPM_SelSyncRef_MADI:
2779 return HDSPM_AUTOSYNC_FROM_MADI;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002780 case HDSPM_SelSyncRef_TCO:
2781 return HDSPM_AUTOSYNC_FROM_TCO;
2782 case HDSPM_SelSyncRef_SyncIn:
2783 return HDSPM_AUTOSYNC_FROM_SYNC_IN;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002784 case HDSPM_SelSyncRef_NVALID:
2785 return HDSPM_AUTOSYNC_FROM_NONE;
2786 default:
2787 return 0;
2788 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002789
Takashi Iwai763f3562005-06-03 11:25:34 +02002790 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002791 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002792}
2793
Adrian Knoth0dca1792011-01-26 19:32:14 +01002794
Takashi Iwai98274f02005-11-17 14:52:34 +01002795static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
2796 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002797{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002798 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002799
Adrian Knoth0dca1792011-01-26 19:32:14 +01002800 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002801 static char *texts[] = { "WordClock", "AES1", "AES2", "AES3",
2802 "AES4", "AES5", "AES6", "AES7", "AES8", "None"};
2803
2804 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2805 uinfo->count = 1;
2806 uinfo->value.enumerated.items = 10;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002807 if (uinfo->value.enumerated.item >=
2808 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002809 uinfo->value.enumerated.item =
2810 uinfo->value.enumerated.items - 1;
2811 strcpy(uinfo->value.enumerated.name,
2812 texts[uinfo->value.enumerated.item]);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002813 } else if (MADI == hdspm->io_type) {
2814 static char *texts[] = {"Word Clock", "MADI", "TCO",
2815 "Sync In", "None" };
Remy Bruno3cee5a62006-10-16 12:46:32 +02002816
2817 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2818 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002819 uinfo->value.enumerated.items = 5;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002820 if (uinfo->value.enumerated.item >=
Adrian Knoth0dca1792011-01-26 19:32:14 +01002821 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002822 uinfo->value.enumerated.item =
2823 uinfo->value.enumerated.items - 1;
2824 strcpy(uinfo->value.enumerated.name,
2825 texts[uinfo->value.enumerated.item]);
2826 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002827 return 0;
2828}
2829
Takashi Iwai98274f02005-11-17 14:52:34 +01002830static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
2831 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002832{
Takashi Iwai98274f02005-11-17 14:52:34 +01002833 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002834
Remy Bruno65345992007-08-31 12:21:08 +02002835 ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002836 return 0;
2837}
2838
Adrian Knoth0dca1792011-01-26 19:32:14 +01002839
Takashi Iwai763f3562005-06-03 11:25:34 +02002840#define HDSPM_LINE_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002841{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002842 .name = xname, \
2843 .index = xindex, \
2844 .info = snd_hdspm_info_line_out, \
2845 .get = snd_hdspm_get_line_out, \
2846 .put = snd_hdspm_put_line_out \
2847}
2848
Takashi Iwai98274f02005-11-17 14:52:34 +01002849static int hdspm_line_out(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002850{
2851 return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0;
2852}
2853
2854
Takashi Iwai98274f02005-11-17 14:52:34 +01002855static int hdspm_set_line_output(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002856{
2857 if (out)
2858 hdspm->control_register |= HDSPM_LineOut;
2859 else
2860 hdspm->control_register &= ~HDSPM_LineOut;
2861 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2862
2863 return 0;
2864}
2865
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002866#define snd_hdspm_info_line_out snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002867
Takashi Iwai98274f02005-11-17 14:52:34 +01002868static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol,
2869 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002870{
Takashi Iwai98274f02005-11-17 14:52:34 +01002871 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002872
2873 spin_lock_irq(&hdspm->lock);
2874 ucontrol->value.integer.value[0] = hdspm_line_out(hdspm);
2875 spin_unlock_irq(&hdspm->lock);
2876 return 0;
2877}
2878
Takashi Iwai98274f02005-11-17 14:52:34 +01002879static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
2880 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002881{
Takashi Iwai98274f02005-11-17 14:52:34 +01002882 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002883 int change;
2884 unsigned int val;
2885
2886 if (!snd_hdspm_use_is_exclusive(hdspm))
2887 return -EBUSY;
2888 val = ucontrol->value.integer.value[0] & 1;
2889 spin_lock_irq(&hdspm->lock);
2890 change = (int) val != hdspm_line_out(hdspm);
2891 hdspm_set_line_output(hdspm, val);
2892 spin_unlock_irq(&hdspm->lock);
2893 return change;
2894}
2895
Adrian Knoth0dca1792011-01-26 19:32:14 +01002896
Takashi Iwai763f3562005-06-03 11:25:34 +02002897#define HDSPM_TX_64(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002898{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002899 .name = xname, \
2900 .index = xindex, \
2901 .info = snd_hdspm_info_tx_64, \
2902 .get = snd_hdspm_get_tx_64, \
2903 .put = snd_hdspm_put_tx_64 \
2904}
2905
Takashi Iwai98274f02005-11-17 14:52:34 +01002906static int hdspm_tx_64(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002907{
2908 return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0;
2909}
2910
Takashi Iwai98274f02005-11-17 14:52:34 +01002911static int hdspm_set_tx_64(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002912{
2913 if (out)
2914 hdspm->control_register |= HDSPM_TX_64ch;
2915 else
2916 hdspm->control_register &= ~HDSPM_TX_64ch;
2917 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2918
2919 return 0;
2920}
2921
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002922#define snd_hdspm_info_tx_64 snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002923
Takashi Iwai98274f02005-11-17 14:52:34 +01002924static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol,
2925 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002926{
Takashi Iwai98274f02005-11-17 14:52:34 +01002927 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002928
2929 spin_lock_irq(&hdspm->lock);
2930 ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm);
2931 spin_unlock_irq(&hdspm->lock);
2932 return 0;
2933}
2934
Takashi Iwai98274f02005-11-17 14:52:34 +01002935static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
2936 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002937{
Takashi Iwai98274f02005-11-17 14:52:34 +01002938 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002939 int change;
2940 unsigned int val;
2941
2942 if (!snd_hdspm_use_is_exclusive(hdspm))
2943 return -EBUSY;
2944 val = ucontrol->value.integer.value[0] & 1;
2945 spin_lock_irq(&hdspm->lock);
2946 change = (int) val != hdspm_tx_64(hdspm);
2947 hdspm_set_tx_64(hdspm, val);
2948 spin_unlock_irq(&hdspm->lock);
2949 return change;
2950}
2951
Adrian Knoth0dca1792011-01-26 19:32:14 +01002952
Takashi Iwai763f3562005-06-03 11:25:34 +02002953#define HDSPM_C_TMS(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002954{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002955 .name = xname, \
2956 .index = xindex, \
2957 .info = snd_hdspm_info_c_tms, \
2958 .get = snd_hdspm_get_c_tms, \
2959 .put = snd_hdspm_put_c_tms \
2960}
2961
Takashi Iwai98274f02005-11-17 14:52:34 +01002962static int hdspm_c_tms(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002963{
2964 return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0;
2965}
2966
Takashi Iwai98274f02005-11-17 14:52:34 +01002967static int hdspm_set_c_tms(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002968{
2969 if (out)
2970 hdspm->control_register |= HDSPM_clr_tms;
2971 else
2972 hdspm->control_register &= ~HDSPM_clr_tms;
2973 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2974
2975 return 0;
2976}
2977
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002978#define snd_hdspm_info_c_tms snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002979
Takashi Iwai98274f02005-11-17 14:52:34 +01002980static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol,
2981 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002982{
Takashi Iwai98274f02005-11-17 14:52:34 +01002983 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002984
2985 spin_lock_irq(&hdspm->lock);
2986 ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm);
2987 spin_unlock_irq(&hdspm->lock);
2988 return 0;
2989}
2990
Takashi Iwai98274f02005-11-17 14:52:34 +01002991static int snd_hdspm_put_c_tms(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 int change;
2996 unsigned int val;
2997
2998 if (!snd_hdspm_use_is_exclusive(hdspm))
2999 return -EBUSY;
3000 val = ucontrol->value.integer.value[0] & 1;
3001 spin_lock_irq(&hdspm->lock);
3002 change = (int) val != hdspm_c_tms(hdspm);
3003 hdspm_set_c_tms(hdspm, val);
3004 spin_unlock_irq(&hdspm->lock);
3005 return change;
3006}
3007
Adrian Knoth0dca1792011-01-26 19:32:14 +01003008
Takashi Iwai763f3562005-06-03 11:25:34 +02003009#define HDSPM_SAFE_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003010{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003011 .name = xname, \
3012 .index = xindex, \
3013 .info = snd_hdspm_info_safe_mode, \
3014 .get = snd_hdspm_get_safe_mode, \
3015 .put = snd_hdspm_put_safe_mode \
3016}
3017
Takashi Iwai98274f02005-11-17 14:52:34 +01003018static int hdspm_safe_mode(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003019{
3020 return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0;
3021}
3022
Takashi Iwai98274f02005-11-17 14:52:34 +01003023static int hdspm_set_safe_mode(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02003024{
3025 if (out)
3026 hdspm->control_register |= HDSPM_AutoInp;
3027 else
3028 hdspm->control_register &= ~HDSPM_AutoInp;
3029 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3030
3031 return 0;
3032}
3033
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003034#define snd_hdspm_info_safe_mode snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02003035
Takashi Iwai98274f02005-11-17 14:52:34 +01003036static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol,
3037 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003038{
Takashi Iwai98274f02005-11-17 14:52:34 +01003039 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003040
3041 spin_lock_irq(&hdspm->lock);
3042 ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm);
3043 spin_unlock_irq(&hdspm->lock);
3044 return 0;
3045}
3046
Takashi Iwai98274f02005-11-17 14:52:34 +01003047static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
3048 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003049{
Takashi Iwai98274f02005-11-17 14:52:34 +01003050 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003051 int change;
3052 unsigned int val;
3053
3054 if (!snd_hdspm_use_is_exclusive(hdspm))
3055 return -EBUSY;
3056 val = ucontrol->value.integer.value[0] & 1;
3057 spin_lock_irq(&hdspm->lock);
3058 change = (int) val != hdspm_safe_mode(hdspm);
3059 hdspm_set_safe_mode(hdspm, val);
3060 spin_unlock_irq(&hdspm->lock);
3061 return change;
3062}
3063
Adrian Knoth0dca1792011-01-26 19:32:14 +01003064
Remy Bruno3cee5a62006-10-16 12:46:32 +02003065#define HDSPM_EMPHASIS(xname, xindex) \
3066{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3067 .name = xname, \
3068 .index = xindex, \
3069 .info = snd_hdspm_info_emphasis, \
3070 .get = snd_hdspm_get_emphasis, \
3071 .put = snd_hdspm_put_emphasis \
3072}
3073
3074static int hdspm_emphasis(struct hdspm * hdspm)
3075{
3076 return (hdspm->control_register & HDSPM_Emphasis) ? 1 : 0;
3077}
3078
3079static int hdspm_set_emphasis(struct hdspm * hdspm, int emp)
3080{
3081 if (emp)
3082 hdspm->control_register |= HDSPM_Emphasis;
3083 else
3084 hdspm->control_register &= ~HDSPM_Emphasis;
3085 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3086
3087 return 0;
3088}
3089
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003090#define snd_hdspm_info_emphasis snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02003091
3092static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol,
3093 struct snd_ctl_elem_value *ucontrol)
3094{
3095 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3096
3097 spin_lock_irq(&hdspm->lock);
3098 ucontrol->value.enumerated.item[0] = hdspm_emphasis(hdspm);
3099 spin_unlock_irq(&hdspm->lock);
3100 return 0;
3101}
3102
3103static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
3104 struct snd_ctl_elem_value *ucontrol)
3105{
3106 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3107 int change;
3108 unsigned int val;
3109
3110 if (!snd_hdspm_use_is_exclusive(hdspm))
3111 return -EBUSY;
3112 val = ucontrol->value.integer.value[0] & 1;
3113 spin_lock_irq(&hdspm->lock);
3114 change = (int) val != hdspm_emphasis(hdspm);
3115 hdspm_set_emphasis(hdspm, val);
3116 spin_unlock_irq(&hdspm->lock);
3117 return change;
3118}
3119
Adrian Knoth0dca1792011-01-26 19:32:14 +01003120
Remy Bruno3cee5a62006-10-16 12:46:32 +02003121#define HDSPM_DOLBY(xname, xindex) \
3122{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3123 .name = xname, \
3124 .index = xindex, \
3125 .info = snd_hdspm_info_dolby, \
3126 .get = snd_hdspm_get_dolby, \
3127 .put = snd_hdspm_put_dolby \
3128}
3129
3130static int hdspm_dolby(struct hdspm * hdspm)
3131{
3132 return (hdspm->control_register & HDSPM_Dolby) ? 1 : 0;
3133}
3134
3135static int hdspm_set_dolby(struct hdspm * hdspm, int dol)
3136{
3137 if (dol)
3138 hdspm->control_register |= HDSPM_Dolby;
3139 else
3140 hdspm->control_register &= ~HDSPM_Dolby;
3141 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3142
3143 return 0;
3144}
3145
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003146#define snd_hdspm_info_dolby snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02003147
3148static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol,
3149 struct snd_ctl_elem_value *ucontrol)
3150{
3151 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3152
3153 spin_lock_irq(&hdspm->lock);
3154 ucontrol->value.enumerated.item[0] = hdspm_dolby(hdspm);
3155 spin_unlock_irq(&hdspm->lock);
3156 return 0;
3157}
3158
3159static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
3160 struct snd_ctl_elem_value *ucontrol)
3161{
3162 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3163 int change;
3164 unsigned int val;
3165
3166 if (!snd_hdspm_use_is_exclusive(hdspm))
3167 return -EBUSY;
3168 val = ucontrol->value.integer.value[0] & 1;
3169 spin_lock_irq(&hdspm->lock);
3170 change = (int) val != hdspm_dolby(hdspm);
3171 hdspm_set_dolby(hdspm, val);
3172 spin_unlock_irq(&hdspm->lock);
3173 return change;
3174}
3175
Adrian Knoth0dca1792011-01-26 19:32:14 +01003176
Remy Bruno3cee5a62006-10-16 12:46:32 +02003177#define HDSPM_PROFESSIONAL(xname, xindex) \
3178{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3179 .name = xname, \
3180 .index = xindex, \
3181 .info = snd_hdspm_info_professional, \
3182 .get = snd_hdspm_get_professional, \
3183 .put = snd_hdspm_put_professional \
3184}
3185
3186static int hdspm_professional(struct hdspm * hdspm)
3187{
3188 return (hdspm->control_register & HDSPM_Professional) ? 1 : 0;
3189}
3190
3191static int hdspm_set_professional(struct hdspm * hdspm, int dol)
3192{
3193 if (dol)
3194 hdspm->control_register |= HDSPM_Professional;
3195 else
3196 hdspm->control_register &= ~HDSPM_Professional;
3197 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3198
3199 return 0;
3200}
3201
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003202#define snd_hdspm_info_professional snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02003203
3204static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol,
3205 struct snd_ctl_elem_value *ucontrol)
3206{
3207 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3208
3209 spin_lock_irq(&hdspm->lock);
3210 ucontrol->value.enumerated.item[0] = hdspm_professional(hdspm);
3211 spin_unlock_irq(&hdspm->lock);
3212 return 0;
3213}
3214
3215static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,
3216 struct snd_ctl_elem_value *ucontrol)
3217{
3218 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3219 int change;
3220 unsigned int val;
3221
3222 if (!snd_hdspm_use_is_exclusive(hdspm))
3223 return -EBUSY;
3224 val = ucontrol->value.integer.value[0] & 1;
3225 spin_lock_irq(&hdspm->lock);
3226 change = (int) val != hdspm_professional(hdspm);
3227 hdspm_set_professional(hdspm, val);
3228 spin_unlock_irq(&hdspm->lock);
3229 return change;
3230}
3231
Takashi Iwai763f3562005-06-03 11:25:34 +02003232#define HDSPM_INPUT_SELECT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003233{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003234 .name = xname, \
3235 .index = xindex, \
3236 .info = snd_hdspm_info_input_select, \
3237 .get = snd_hdspm_get_input_select, \
3238 .put = snd_hdspm_put_input_select \
3239}
3240
Takashi Iwai98274f02005-11-17 14:52:34 +01003241static int hdspm_input_select(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003242{
3243 return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
3244}
3245
Takashi Iwai98274f02005-11-17 14:52:34 +01003246static int hdspm_set_input_select(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02003247{
3248 if (out)
3249 hdspm->control_register |= HDSPM_InputSelect0;
3250 else
3251 hdspm->control_register &= ~HDSPM_InputSelect0;
3252 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3253
3254 return 0;
3255}
3256
Takashi Iwai98274f02005-11-17 14:52:34 +01003257static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
3258 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003259{
3260 static char *texts[] = { "optical", "coaxial" };
3261
3262 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3263 uinfo->count = 1;
3264 uinfo->value.enumerated.items = 2;
3265
3266 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3267 uinfo->value.enumerated.item =
3268 uinfo->value.enumerated.items - 1;
3269 strcpy(uinfo->value.enumerated.name,
3270 texts[uinfo->value.enumerated.item]);
3271
3272 return 0;
3273}
3274
Takashi Iwai98274f02005-11-17 14:52:34 +01003275static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
3276 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003277{
Takashi Iwai98274f02005-11-17 14:52:34 +01003278 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003279
3280 spin_lock_irq(&hdspm->lock);
3281 ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
3282 spin_unlock_irq(&hdspm->lock);
3283 return 0;
3284}
3285
Takashi Iwai98274f02005-11-17 14:52:34 +01003286static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
3287 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003288{
Takashi Iwai98274f02005-11-17 14:52:34 +01003289 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003290 int change;
3291 unsigned int val;
3292
3293 if (!snd_hdspm_use_is_exclusive(hdspm))
3294 return -EBUSY;
3295 val = ucontrol->value.integer.value[0] & 1;
3296 spin_lock_irq(&hdspm->lock);
3297 change = (int) val != hdspm_input_select(hdspm);
3298 hdspm_set_input_select(hdspm, val);
3299 spin_unlock_irq(&hdspm->lock);
3300 return change;
3301}
3302
Adrian Knoth0dca1792011-01-26 19:32:14 +01003303
Remy Bruno3cee5a62006-10-16 12:46:32 +02003304#define HDSPM_DS_WIRE(xname, xindex) \
3305{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3306 .name = xname, \
3307 .index = xindex, \
3308 .info = snd_hdspm_info_ds_wire, \
3309 .get = snd_hdspm_get_ds_wire, \
3310 .put = snd_hdspm_put_ds_wire \
3311}
3312
3313static int hdspm_ds_wire(struct hdspm * hdspm)
3314{
3315 return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
3316}
3317
3318static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
3319{
3320 if (ds)
3321 hdspm->control_register |= HDSPM_DS_DoubleWire;
3322 else
3323 hdspm->control_register &= ~HDSPM_DS_DoubleWire;
3324 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3325
3326 return 0;
3327}
3328
3329static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
3330 struct snd_ctl_elem_info *uinfo)
3331{
3332 static char *texts[] = { "Single", "Double" };
3333
3334 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3335 uinfo->count = 1;
3336 uinfo->value.enumerated.items = 2;
3337
3338 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3339 uinfo->value.enumerated.item =
3340 uinfo->value.enumerated.items - 1;
3341 strcpy(uinfo->value.enumerated.name,
3342 texts[uinfo->value.enumerated.item]);
3343
3344 return 0;
3345}
3346
3347static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
3348 struct snd_ctl_elem_value *ucontrol)
3349{
3350 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3351
3352 spin_lock_irq(&hdspm->lock);
3353 ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
3354 spin_unlock_irq(&hdspm->lock);
3355 return 0;
3356}
3357
3358static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
3359 struct snd_ctl_elem_value *ucontrol)
3360{
3361 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3362 int change;
3363 unsigned int val;
3364
3365 if (!snd_hdspm_use_is_exclusive(hdspm))
3366 return -EBUSY;
3367 val = ucontrol->value.integer.value[0] & 1;
3368 spin_lock_irq(&hdspm->lock);
3369 change = (int) val != hdspm_ds_wire(hdspm);
3370 hdspm_set_ds_wire(hdspm, val);
3371 spin_unlock_irq(&hdspm->lock);
3372 return change;
3373}
3374
Adrian Knoth0dca1792011-01-26 19:32:14 +01003375
Remy Bruno3cee5a62006-10-16 12:46:32 +02003376#define HDSPM_QS_WIRE(xname, xindex) \
3377{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3378 .name = xname, \
3379 .index = xindex, \
3380 .info = snd_hdspm_info_qs_wire, \
3381 .get = snd_hdspm_get_qs_wire, \
3382 .put = snd_hdspm_put_qs_wire \
3383}
3384
3385static int hdspm_qs_wire(struct hdspm * hdspm)
3386{
3387 if (hdspm->control_register & HDSPM_QS_DoubleWire)
3388 return 1;
3389 if (hdspm->control_register & HDSPM_QS_QuadWire)
3390 return 2;
3391 return 0;
3392}
3393
3394static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
3395{
3396 hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
3397 switch (mode) {
3398 case 0:
3399 break;
3400 case 1:
3401 hdspm->control_register |= HDSPM_QS_DoubleWire;
3402 break;
3403 case 2:
3404 hdspm->control_register |= HDSPM_QS_QuadWire;
3405 break;
3406 }
3407 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3408
3409 return 0;
3410}
3411
3412static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
3413 struct snd_ctl_elem_info *uinfo)
3414{
3415 static char *texts[] = { "Single", "Double", "Quad" };
3416
3417 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3418 uinfo->count = 1;
3419 uinfo->value.enumerated.items = 3;
3420
3421 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3422 uinfo->value.enumerated.item =
3423 uinfo->value.enumerated.items - 1;
3424 strcpy(uinfo->value.enumerated.name,
3425 texts[uinfo->value.enumerated.item]);
3426
3427 return 0;
3428}
3429
3430static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
3431 struct snd_ctl_elem_value *ucontrol)
3432{
3433 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3434
3435 spin_lock_irq(&hdspm->lock);
3436 ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
3437 spin_unlock_irq(&hdspm->lock);
3438 return 0;
3439}
3440
3441static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
3442 struct snd_ctl_elem_value *ucontrol)
3443{
3444 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3445 int change;
3446 int val;
3447
3448 if (!snd_hdspm_use_is_exclusive(hdspm))
3449 return -EBUSY;
3450 val = ucontrol->value.integer.value[0];
3451 if (val < 0)
3452 val = 0;
3453 if (val > 2)
3454 val = 2;
3455 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003456 change = val != hdspm_qs_wire(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003457 hdspm_set_qs_wire(hdspm, val);
3458 spin_unlock_irq(&hdspm->lock);
3459 return change;
3460}
3461
Adrian Knoth700d1ef2011-07-29 03:11:02 +02003462#define HDSPM_MADI_SPEEDMODE(xname, xindex) \
3463{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3464 .name = xname, \
3465 .index = xindex, \
3466 .info = snd_hdspm_info_madi_speedmode, \
3467 .get = snd_hdspm_get_madi_speedmode, \
3468 .put = snd_hdspm_put_madi_speedmode \
3469}
3470
3471static int hdspm_madi_speedmode(struct hdspm *hdspm)
3472{
3473 if (hdspm->control_register & HDSPM_QuadSpeed)
3474 return 2;
3475 if (hdspm->control_register & HDSPM_DoubleSpeed)
3476 return 1;
3477 return 0;
3478}
3479
3480static int hdspm_set_madi_speedmode(struct hdspm *hdspm, int mode)
3481{
3482 hdspm->control_register &= ~(HDSPM_DoubleSpeed | HDSPM_QuadSpeed);
3483 switch (mode) {
3484 case 0:
3485 break;
3486 case 1:
3487 hdspm->control_register |= HDSPM_DoubleSpeed;
3488 break;
3489 case 2:
3490 hdspm->control_register |= HDSPM_QuadSpeed;
3491 break;
3492 }
3493 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3494
3495 return 0;
3496}
3497
3498static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol,
3499 struct snd_ctl_elem_info *uinfo)
3500{
3501 static char *texts[] = { "Single", "Double", "Quad" };
3502
3503 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3504 uinfo->count = 1;
3505 uinfo->value.enumerated.items = 3;
3506
3507 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3508 uinfo->value.enumerated.item =
3509 uinfo->value.enumerated.items - 1;
3510 strcpy(uinfo->value.enumerated.name,
3511 texts[uinfo->value.enumerated.item]);
3512
3513 return 0;
3514}
3515
3516static int snd_hdspm_get_madi_speedmode(struct snd_kcontrol *kcontrol,
3517 struct snd_ctl_elem_value *ucontrol)
3518{
3519 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3520
3521 spin_lock_irq(&hdspm->lock);
3522 ucontrol->value.enumerated.item[0] = hdspm_madi_speedmode(hdspm);
3523 spin_unlock_irq(&hdspm->lock);
3524 return 0;
3525}
3526
3527static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol,
3528 struct snd_ctl_elem_value *ucontrol)
3529{
3530 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3531 int change;
3532 int val;
3533
3534 if (!snd_hdspm_use_is_exclusive(hdspm))
3535 return -EBUSY;
3536 val = ucontrol->value.integer.value[0];
3537 if (val < 0)
3538 val = 0;
3539 if (val > 2)
3540 val = 2;
3541 spin_lock_irq(&hdspm->lock);
3542 change = val != hdspm_madi_speedmode(hdspm);
3543 hdspm_set_madi_speedmode(hdspm, val);
3544 spin_unlock_irq(&hdspm->lock);
3545 return change;
3546}
Takashi Iwai763f3562005-06-03 11:25:34 +02003547
3548#define HDSPM_MIXER(xname, xindex) \
3549{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
3550 .name = xname, \
3551 .index = xindex, \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003552 .device = 0, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003553 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
3554 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3555 .info = snd_hdspm_info_mixer, \
3556 .get = snd_hdspm_get_mixer, \
3557 .put = snd_hdspm_put_mixer \
3558}
3559
Takashi Iwai98274f02005-11-17 14:52:34 +01003560static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
3561 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003562{
3563 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3564 uinfo->count = 3;
3565 uinfo->value.integer.min = 0;
3566 uinfo->value.integer.max = 65535;
3567 uinfo->value.integer.step = 1;
3568 return 0;
3569}
3570
Takashi Iwai98274f02005-11-17 14:52:34 +01003571static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
3572 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003573{
Takashi Iwai98274f02005-11-17 14:52:34 +01003574 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003575 int source;
3576 int destination;
3577
3578 source = ucontrol->value.integer.value[0];
3579 if (source < 0)
3580 source = 0;
3581 else if (source >= 2 * HDSPM_MAX_CHANNELS)
3582 source = 2 * HDSPM_MAX_CHANNELS - 1;
3583
3584 destination = ucontrol->value.integer.value[1];
3585 if (destination < 0)
3586 destination = 0;
3587 else if (destination >= HDSPM_MAX_CHANNELS)
3588 destination = HDSPM_MAX_CHANNELS - 1;
3589
3590 spin_lock_irq(&hdspm->lock);
3591 if (source >= HDSPM_MAX_CHANNELS)
3592 ucontrol->value.integer.value[2] =
3593 hdspm_read_pb_gain(hdspm, destination,
3594 source - HDSPM_MAX_CHANNELS);
3595 else
3596 ucontrol->value.integer.value[2] =
3597 hdspm_read_in_gain(hdspm, destination, source);
3598
3599 spin_unlock_irq(&hdspm->lock);
3600
3601 return 0;
3602}
3603
Takashi Iwai98274f02005-11-17 14:52:34 +01003604static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
3605 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003606{
Takashi Iwai98274f02005-11-17 14:52:34 +01003607 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003608 int change;
3609 int source;
3610 int destination;
3611 int gain;
3612
3613 if (!snd_hdspm_use_is_exclusive(hdspm))
3614 return -EBUSY;
3615
3616 source = ucontrol->value.integer.value[0];
3617 destination = ucontrol->value.integer.value[1];
3618
3619 if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
3620 return -1;
3621 if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
3622 return -1;
3623
3624 gain = ucontrol->value.integer.value[2];
3625
3626 spin_lock_irq(&hdspm->lock);
3627
3628 if (source >= HDSPM_MAX_CHANNELS)
3629 change = gain != hdspm_read_pb_gain(hdspm, destination,
3630 source -
3631 HDSPM_MAX_CHANNELS);
3632 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003633 change = gain != hdspm_read_in_gain(hdspm, destination,
3634 source);
Takashi Iwai763f3562005-06-03 11:25:34 +02003635
3636 if (change) {
3637 if (source >= HDSPM_MAX_CHANNELS)
3638 hdspm_write_pb_gain(hdspm, destination,
3639 source - HDSPM_MAX_CHANNELS,
3640 gain);
3641 else
3642 hdspm_write_in_gain(hdspm, destination, source,
3643 gain);
3644 }
3645 spin_unlock_irq(&hdspm->lock);
3646
3647 return change;
3648}
3649
3650/* The simple mixer control(s) provide gain control for the
3651 basic 1:1 mappings of playback streams to output
Adrian Knoth0dca1792011-01-26 19:32:14 +01003652 streams.
Takashi Iwai763f3562005-06-03 11:25:34 +02003653*/
3654
3655#define HDSPM_PLAYBACK_MIXER \
3656{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3657 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
3658 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3659 .info = snd_hdspm_info_playback_mixer, \
3660 .get = snd_hdspm_get_playback_mixer, \
3661 .put = snd_hdspm_put_playback_mixer \
3662}
3663
Takashi Iwai98274f02005-11-17 14:52:34 +01003664static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
3665 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003666{
3667 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3668 uinfo->count = 1;
3669 uinfo->value.integer.min = 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003670 uinfo->value.integer.max = 64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003671 uinfo->value.integer.step = 1;
3672 return 0;
3673}
3674
Takashi Iwai98274f02005-11-17 14:52:34 +01003675static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
3676 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003677{
Takashi Iwai98274f02005-11-17 14:52:34 +01003678 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003679 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003680
3681 channel = ucontrol->id.index - 1;
3682
Takashi Iwaida3cec32008-08-08 17:12:14 +02003683 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3684 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003685
Takashi Iwai763f3562005-06-03 11:25:34 +02003686 spin_lock_irq(&hdspm->lock);
3687 ucontrol->value.integer.value[0] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003688 (hdspm_read_pb_gain(hdspm, channel, channel)*64)/UNITY_GAIN;
Takashi Iwai763f3562005-06-03 11:25:34 +02003689 spin_unlock_irq(&hdspm->lock);
3690
Takashi Iwai763f3562005-06-03 11:25:34 +02003691 return 0;
3692}
3693
Takashi Iwai98274f02005-11-17 14:52:34 +01003694static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
3695 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003696{
Takashi Iwai98274f02005-11-17 14:52:34 +01003697 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003698 int change;
3699 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003700 int gain;
3701
3702 if (!snd_hdspm_use_is_exclusive(hdspm))
3703 return -EBUSY;
3704
3705 channel = ucontrol->id.index - 1;
3706
Takashi Iwaida3cec32008-08-08 17:12:14 +02003707 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3708 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003709
Adrian Knoth0dca1792011-01-26 19:32:14 +01003710 gain = ucontrol->value.integer.value[0]*UNITY_GAIN/64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003711
3712 spin_lock_irq(&hdspm->lock);
3713 change =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003714 gain != hdspm_read_pb_gain(hdspm, channel,
3715 channel);
Takashi Iwai763f3562005-06-03 11:25:34 +02003716 if (change)
Adrian Knoth0dca1792011-01-26 19:32:14 +01003717 hdspm_write_pb_gain(hdspm, channel, channel,
Takashi Iwai763f3562005-06-03 11:25:34 +02003718 gain);
3719 spin_unlock_irq(&hdspm->lock);
3720 return change;
3721}
3722
Adrian Knoth0dca1792011-01-26 19:32:14 +01003723#define HDSPM_SYNC_CHECK(xname, xindex) \
3724{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3725 .name = xname, \
3726 .private_value = xindex, \
3727 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3728 .info = snd_hdspm_info_sync_check, \
3729 .get = snd_hdspm_get_sync_check \
Takashi Iwai763f3562005-06-03 11:25:34 +02003730}
3731
Adrian Knoth0dca1792011-01-26 19:32:14 +01003732
Takashi Iwai98274f02005-11-17 14:52:34 +01003733static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
3734 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003735{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003736 static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" };
Takashi Iwai763f3562005-06-03 11:25:34 +02003737 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3738 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003739 uinfo->value.enumerated.items = 4;
Takashi Iwai763f3562005-06-03 11:25:34 +02003740 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3741 uinfo->value.enumerated.item =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003742 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02003743 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01003744 texts[uinfo->value.enumerated.item]);
Takashi Iwai763f3562005-06-03 11:25:34 +02003745 return 0;
3746}
3747
Adrian Knoth0dca1792011-01-26 19:32:14 +01003748static int hdspm_wc_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003749{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003750 int status, status2;
3751
3752 switch (hdspm->io_type) {
3753 case AES32:
3754 status = hdspm_read(hdspm, HDSPM_statusRegister);
3755 if (status & HDSPM_wcSync)
Takashi Iwai763f3562005-06-03 11:25:34 +02003756 return 2;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003757 else if (status & HDSPM_wcLock)
3758 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003759 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003760 break;
3761
3762 case MADI:
3763 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003764 if (status2 & HDSPM_wcLock) {
3765 if (status2 & HDSPM_wcSync)
3766 return 2;
3767 else
3768 return 1;
3769 }
3770 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003771 break;
3772
3773 case RayDAT:
3774 case AIO:
3775 status = hdspm_read(hdspm, HDSPM_statusRegister);
3776
3777 if (status & 0x2000000)
3778 return 2;
3779 else if (status & 0x1000000)
3780 return 1;
3781 return 0;
3782
3783 break;
3784
3785 case MADIface:
3786 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02003787 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003788
Takashi Iwai763f3562005-06-03 11:25:34 +02003789
Adrian Knoth0dca1792011-01-26 19:32:14 +01003790 return 3;
Takashi Iwai763f3562005-06-03 11:25:34 +02003791}
3792
3793
Adrian Knoth0dca1792011-01-26 19:32:14 +01003794static int hdspm_madi_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003795{
3796 int status = hdspm_read(hdspm, HDSPM_statusRegister);
3797 if (status & HDSPM_madiLock) {
3798 if (status & HDSPM_madiSync)
3799 return 2;
3800 else
3801 return 1;
3802 }
3803 return 0;
3804}
3805
Adrian Knoth0dca1792011-01-26 19:32:14 +01003806
3807static int hdspm_s1_sync_check(struct hdspm *hdspm, int idx)
3808{
3809 int status, lock, sync;
3810
3811 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3812
3813 lock = (status & (0x1<<idx)) ? 1 : 0;
3814 sync = (status & (0x100<<idx)) ? 1 : 0;
3815
3816 if (lock && sync)
3817 return 2;
3818 else if (lock)
3819 return 1;
3820 return 0;
3821}
3822
3823
3824static int hdspm_sync_in_sync_check(struct hdspm *hdspm)
3825{
3826 int status, lock = 0, sync = 0;
3827
3828 switch (hdspm->io_type) {
3829 case RayDAT:
3830 case AIO:
3831 status = hdspm_read(hdspm, HDSPM_RD_STATUS_3);
3832 lock = (status & 0x400) ? 1 : 0;
3833 sync = (status & 0x800) ? 1 : 0;
3834 break;
3835
3836 case MADI:
3837 case AES32:
3838 status = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knotha7edbd52011-02-23 11:43:15 +01003839 lock = (status & HDSPM_syncInLock) ? 1 : 0;
3840 sync = (status & HDSPM_syncInSync) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003841 break;
3842
3843 case MADIface:
3844 break;
3845 }
3846
3847 if (lock && sync)
3848 return 2;
3849 else if (lock)
3850 return 1;
3851
3852 return 0;
3853}
3854
3855static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx)
3856{
3857 int status2, lock, sync;
3858 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
3859
3860 lock = (status2 & (0x0080 >> idx)) ? 1 : 0;
3861 sync = (status2 & (0x8000 >> idx)) ? 1 : 0;
3862
3863 if (sync)
3864 return 2;
3865 else if (lock)
3866 return 1;
3867 return 0;
3868}
3869
3870
3871static int hdspm_tco_sync_check(struct hdspm *hdspm)
3872{
3873 int status;
3874
3875 if (hdspm->tco) {
3876 switch (hdspm->io_type) {
3877 case MADI:
3878 case AES32:
3879 status = hdspm_read(hdspm, HDSPM_statusRegister);
3880 if (status & HDSPM_tcoLock) {
3881 if (status & HDSPM_tcoSync)
3882 return 2;
3883 else
3884 return 1;
3885 }
3886 return 0;
3887
3888 break;
3889
3890 case RayDAT:
3891 case AIO:
3892 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3893
3894 if (status & 0x8000000)
3895 return 2; /* Sync */
3896 if (status & 0x4000000)
3897 return 1; /* Lock */
3898 return 0; /* No signal */
3899 break;
3900
3901 default:
3902 break;
3903 }
3904 }
3905
3906 return 3; /* N/A */
3907}
3908
3909
3910static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
3911 struct snd_ctl_elem_value *ucontrol)
3912{
3913 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3914 int val = -1;
3915
3916 switch (hdspm->io_type) {
3917 case RayDAT:
3918 switch (kcontrol->private_value) {
3919 case 0: /* WC */
3920 val = hdspm_wc_sync_check(hdspm); break;
3921 case 7: /* TCO */
3922 val = hdspm_tco_sync_check(hdspm); break;
3923 case 8: /* SYNC IN */
3924 val = hdspm_sync_in_sync_check(hdspm); break;
3925 default:
3926 val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
3927 }
3928
3929 case AIO:
3930 switch (kcontrol->private_value) {
3931 case 0: /* WC */
3932 val = hdspm_wc_sync_check(hdspm); break;
3933 case 4: /* TCO */
3934 val = hdspm_tco_sync_check(hdspm); break;
3935 case 5: /* SYNC IN */
3936 val = hdspm_sync_in_sync_check(hdspm); break;
3937 default:
3938 val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
3939 }
3940
3941 case MADI:
3942 switch (kcontrol->private_value) {
3943 case 0: /* WC */
3944 val = hdspm_wc_sync_check(hdspm); break;
3945 case 1: /* MADI */
3946 val = hdspm_madi_sync_check(hdspm); break;
3947 case 2: /* TCO */
3948 val = hdspm_tco_sync_check(hdspm); break;
3949 case 3: /* SYNC_IN */
3950 val = hdspm_sync_in_sync_check(hdspm); break;
3951 }
3952
3953 case MADIface:
3954 val = hdspm_madi_sync_check(hdspm); /* MADI */
3955 break;
3956
3957 case AES32:
3958 switch (kcontrol->private_value) {
3959 case 0: /* WC */
3960 val = hdspm_wc_sync_check(hdspm); break;
3961 case 9: /* TCO */
3962 val = hdspm_tco_sync_check(hdspm); break;
3963 case 10 /* SYNC IN */:
3964 val = hdspm_sync_in_sync_check(hdspm); break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01003965 default: /* AES1 to AES8 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01003966 val = hdspm_aes_sync_check(hdspm,
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01003967 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003968 }
3969
3970 }
3971
3972 if (-1 == val)
3973 val = 3;
3974
3975 ucontrol->value.enumerated.item[0] = val;
3976 return 0;
3977}
3978
3979
3980
3981/**
3982 * TCO controls
3983 **/
3984static void hdspm_tco_write(struct hdspm *hdspm)
3985{
3986 unsigned int tc[4] = { 0, 0, 0, 0};
3987
3988 switch (hdspm->tco->input) {
3989 case 0:
3990 tc[2] |= HDSPM_TCO2_set_input_MSB;
3991 break;
3992 case 1:
3993 tc[2] |= HDSPM_TCO2_set_input_LSB;
3994 break;
3995 default:
3996 break;
3997 }
3998
3999 switch (hdspm->tco->framerate) {
4000 case 1:
4001 tc[1] |= HDSPM_TCO1_LTC_Format_LSB;
4002 break;
4003 case 2:
4004 tc[1] |= HDSPM_TCO1_LTC_Format_MSB;
4005 break;
4006 case 3:
4007 tc[1] |= HDSPM_TCO1_LTC_Format_MSB +
4008 HDSPM_TCO1_set_drop_frame_flag;
4009 break;
4010 case 4:
4011 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
4012 HDSPM_TCO1_LTC_Format_MSB;
4013 break;
4014 case 5:
4015 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
4016 HDSPM_TCO1_LTC_Format_MSB +
4017 HDSPM_TCO1_set_drop_frame_flag;
4018 break;
4019 default:
4020 break;
4021 }
4022
4023 switch (hdspm->tco->wordclock) {
4024 case 1:
4025 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_LSB;
4026 break;
4027 case 2:
4028 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_MSB;
4029 break;
4030 default:
4031 break;
4032 }
4033
4034 switch (hdspm->tco->samplerate) {
4035 case 1:
4036 tc[2] |= HDSPM_TCO2_set_freq;
4037 break;
4038 case 2:
4039 tc[2] |= HDSPM_TCO2_set_freq_from_app;
4040 break;
4041 default:
4042 break;
4043 }
4044
4045 switch (hdspm->tco->pull) {
4046 case 1:
4047 tc[2] |= HDSPM_TCO2_set_pull_up;
4048 break;
4049 case 2:
4050 tc[2] |= HDSPM_TCO2_set_pull_down;
4051 break;
4052 case 3:
4053 tc[2] |= HDSPM_TCO2_set_pull_up + HDSPM_TCO2_set_01_4;
4054 break;
4055 case 4:
4056 tc[2] |= HDSPM_TCO2_set_pull_down + HDSPM_TCO2_set_01_4;
4057 break;
4058 default:
4059 break;
4060 }
4061
4062 if (1 == hdspm->tco->term) {
4063 tc[2] |= HDSPM_TCO2_set_term_75R;
4064 }
4065
4066 hdspm_write(hdspm, HDSPM_WR_TCO, tc[0]);
4067 hdspm_write(hdspm, HDSPM_WR_TCO+4, tc[1]);
4068 hdspm_write(hdspm, HDSPM_WR_TCO+8, tc[2]);
4069 hdspm_write(hdspm, HDSPM_WR_TCO+12, tc[3]);
4070}
4071
4072
4073#define HDSPM_TCO_SAMPLE_RATE(xname, xindex) \
4074{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4075 .name = xname, \
4076 .index = xindex, \
4077 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4078 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4079 .info = snd_hdspm_info_tco_sample_rate, \
4080 .get = snd_hdspm_get_tco_sample_rate, \
4081 .put = snd_hdspm_put_tco_sample_rate \
4082}
4083
4084static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol,
4085 struct snd_ctl_elem_info *uinfo)
4086{
4087 static char *texts[] = { "44.1 kHz", "48 kHz" };
4088 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4089 uinfo->count = 1;
4090 uinfo->value.enumerated.items = 2;
4091
4092 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4093 uinfo->value.enumerated.item =
4094 uinfo->value.enumerated.items - 1;
4095
4096 strcpy(uinfo->value.enumerated.name,
4097 texts[uinfo->value.enumerated.item]);
4098
4099 return 0;
4100}
4101
4102static int snd_hdspm_get_tco_sample_rate(struct snd_kcontrol *kcontrol,
4103 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02004104{
Takashi Iwai98274f02005-11-17 14:52:34 +01004105 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02004106
Adrian Knoth0dca1792011-01-26 19:32:14 +01004107 ucontrol->value.enumerated.item[0] = hdspm->tco->samplerate;
4108
Takashi Iwai763f3562005-06-03 11:25:34 +02004109 return 0;
4110}
4111
Adrian Knoth0dca1792011-01-26 19:32:14 +01004112static int snd_hdspm_put_tco_sample_rate(struct snd_kcontrol *kcontrol,
4113 struct snd_ctl_elem_value *ucontrol)
Remy Bruno3cee5a62006-10-16 12:46:32 +02004114{
Adrian Knoth0dca1792011-01-26 19:32:14 +01004115 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4116
4117 if (hdspm->tco->samplerate != ucontrol->value.enumerated.item[0]) {
4118 hdspm->tco->samplerate = ucontrol->value.enumerated.item[0];
4119
4120 hdspm_tco_write(hdspm);
4121
4122 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004123 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01004124
Remy Bruno3cee5a62006-10-16 12:46:32 +02004125 return 0;
4126}
4127
Adrian Knoth0dca1792011-01-26 19:32:14 +01004128
4129#define HDSPM_TCO_PULL(xname, xindex) \
4130{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4131 .name = xname, \
4132 .index = xindex, \
4133 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4134 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4135 .info = snd_hdspm_info_tco_pull, \
4136 .get = snd_hdspm_get_tco_pull, \
4137 .put = snd_hdspm_put_tco_pull \
4138}
4139
4140static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol,
4141 struct snd_ctl_elem_info *uinfo)
4142{
4143 static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" };
4144 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4145 uinfo->count = 1;
4146 uinfo->value.enumerated.items = 5;
4147
4148 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4149 uinfo->value.enumerated.item =
4150 uinfo->value.enumerated.items - 1;
4151
4152 strcpy(uinfo->value.enumerated.name,
4153 texts[uinfo->value.enumerated.item]);
4154
4155 return 0;
4156}
4157
4158static int snd_hdspm_get_tco_pull(struct snd_kcontrol *kcontrol,
4159 struct snd_ctl_elem_value *ucontrol)
4160{
4161 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4162
4163 ucontrol->value.enumerated.item[0] = hdspm->tco->pull;
4164
4165 return 0;
4166}
4167
4168static int snd_hdspm_put_tco_pull(struct snd_kcontrol *kcontrol,
4169 struct snd_ctl_elem_value *ucontrol)
4170{
4171 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4172
4173 if (hdspm->tco->pull != ucontrol->value.enumerated.item[0]) {
4174 hdspm->tco->pull = ucontrol->value.enumerated.item[0];
4175
4176 hdspm_tco_write(hdspm);
4177
4178 return 1;
4179 }
4180
4181 return 0;
4182}
4183
4184#define HDSPM_TCO_WCK_CONVERSION(xname, xindex) \
4185{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4186 .name = xname, \
4187 .index = xindex, \
4188 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4189 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4190 .info = snd_hdspm_info_tco_wck_conversion, \
4191 .get = snd_hdspm_get_tco_wck_conversion, \
4192 .put = snd_hdspm_put_tco_wck_conversion \
4193}
4194
4195static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4196 struct snd_ctl_elem_info *uinfo)
4197{
4198 static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
4199 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4200 uinfo->count = 1;
4201 uinfo->value.enumerated.items = 3;
4202
4203 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4204 uinfo->value.enumerated.item =
4205 uinfo->value.enumerated.items - 1;
4206
4207 strcpy(uinfo->value.enumerated.name,
4208 texts[uinfo->value.enumerated.item]);
4209
4210 return 0;
4211}
4212
4213static int snd_hdspm_get_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4214 struct snd_ctl_elem_value *ucontrol)
4215{
4216 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4217
4218 ucontrol->value.enumerated.item[0] = hdspm->tco->wordclock;
4219
4220 return 0;
4221}
4222
4223static int snd_hdspm_put_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4224 struct snd_ctl_elem_value *ucontrol)
4225{
4226 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4227
4228 if (hdspm->tco->wordclock != ucontrol->value.enumerated.item[0]) {
4229 hdspm->tco->wordclock = ucontrol->value.enumerated.item[0];
4230
4231 hdspm_tco_write(hdspm);
4232
4233 return 1;
4234 }
4235
4236 return 0;
4237}
4238
4239
4240#define HDSPM_TCO_FRAME_RATE(xname, xindex) \
4241{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4242 .name = xname, \
4243 .index = xindex, \
4244 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4245 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4246 .info = snd_hdspm_info_tco_frame_rate, \
4247 .get = snd_hdspm_get_tco_frame_rate, \
4248 .put = snd_hdspm_put_tco_frame_rate \
4249}
4250
4251static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol,
4252 struct snd_ctl_elem_info *uinfo)
4253{
4254 static char *texts[] = { "24 fps", "25 fps", "29.97fps",
4255 "29.97 dfps", "30 fps", "30 dfps" };
4256 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4257 uinfo->count = 1;
4258 uinfo->value.enumerated.items = 6;
4259
4260 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4261 uinfo->value.enumerated.item =
4262 uinfo->value.enumerated.items - 1;
4263
4264 strcpy(uinfo->value.enumerated.name,
4265 texts[uinfo->value.enumerated.item]);
4266
4267 return 0;
4268}
4269
4270static int snd_hdspm_get_tco_frame_rate(struct snd_kcontrol *kcontrol,
Remy Bruno3cee5a62006-10-16 12:46:32 +02004271 struct snd_ctl_elem_value *ucontrol)
4272{
Remy Bruno3cee5a62006-10-16 12:46:32 +02004273 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4274
Adrian Knoth0dca1792011-01-26 19:32:14 +01004275 ucontrol->value.enumerated.item[0] = hdspm->tco->framerate;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004276
Remy Bruno3cee5a62006-10-16 12:46:32 +02004277 return 0;
4278}
Takashi Iwai763f3562005-06-03 11:25:34 +02004279
Adrian Knoth0dca1792011-01-26 19:32:14 +01004280static int snd_hdspm_put_tco_frame_rate(struct snd_kcontrol *kcontrol,
4281 struct snd_ctl_elem_value *ucontrol)
4282{
4283 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4284
4285 if (hdspm->tco->framerate != ucontrol->value.enumerated.item[0]) {
4286 hdspm->tco->framerate = ucontrol->value.enumerated.item[0];
4287
4288 hdspm_tco_write(hdspm);
4289
4290 return 1;
4291 }
4292
4293 return 0;
4294}
4295
4296
4297#define HDSPM_TCO_SYNC_SOURCE(xname, xindex) \
4298{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4299 .name = xname, \
4300 .index = xindex, \
4301 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4302 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4303 .info = snd_hdspm_info_tco_sync_source, \
4304 .get = snd_hdspm_get_tco_sync_source, \
4305 .put = snd_hdspm_put_tco_sync_source \
4306}
4307
4308static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol,
4309 struct snd_ctl_elem_info *uinfo)
4310{
4311 static char *texts[] = { "LTC", "Video", "WCK" };
4312 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4313 uinfo->count = 1;
4314 uinfo->value.enumerated.items = 3;
4315
4316 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4317 uinfo->value.enumerated.item =
4318 uinfo->value.enumerated.items - 1;
4319
4320 strcpy(uinfo->value.enumerated.name,
4321 texts[uinfo->value.enumerated.item]);
4322
4323 return 0;
4324}
4325
4326static int snd_hdspm_get_tco_sync_source(struct snd_kcontrol *kcontrol,
4327 struct snd_ctl_elem_value *ucontrol)
4328{
4329 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4330
4331 ucontrol->value.enumerated.item[0] = hdspm->tco->input;
4332
4333 return 0;
4334}
4335
4336static int snd_hdspm_put_tco_sync_source(struct snd_kcontrol *kcontrol,
4337 struct snd_ctl_elem_value *ucontrol)
4338{
4339 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4340
4341 if (hdspm->tco->input != ucontrol->value.enumerated.item[0]) {
4342 hdspm->tco->input = ucontrol->value.enumerated.item[0];
4343
4344 hdspm_tco_write(hdspm);
4345
4346 return 1;
4347 }
4348
4349 return 0;
4350}
4351
4352
4353#define HDSPM_TCO_WORD_TERM(xname, xindex) \
4354{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4355 .name = xname, \
4356 .index = xindex, \
4357 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4358 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4359 .info = snd_hdspm_info_tco_word_term, \
4360 .get = snd_hdspm_get_tco_word_term, \
4361 .put = snd_hdspm_put_tco_word_term \
4362}
4363
4364static int snd_hdspm_info_tco_word_term(struct snd_kcontrol *kcontrol,
4365 struct snd_ctl_elem_info *uinfo)
4366{
4367 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
4368 uinfo->count = 1;
4369 uinfo->value.integer.min = 0;
4370 uinfo->value.integer.max = 1;
4371
4372 return 0;
4373}
4374
4375
4376static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol,
4377 struct snd_ctl_elem_value *ucontrol)
4378{
4379 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4380
4381 ucontrol->value.enumerated.item[0] = hdspm->tco->term;
4382
4383 return 0;
4384}
4385
4386
4387static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol,
4388 struct snd_ctl_elem_value *ucontrol)
4389{
4390 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4391
4392 if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) {
4393 hdspm->tco->term = ucontrol->value.enumerated.item[0];
4394
4395 hdspm_tco_write(hdspm);
4396
4397 return 1;
4398 }
4399
4400 return 0;
4401}
4402
4403
4404
Takashi Iwai763f3562005-06-03 11:25:34 +02004405
Remy Bruno3cee5a62006-10-16 12:46:32 +02004406static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004407 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004408 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Takashi Iwai763f3562005-06-03 11:25:34 +02004409 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4410 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4411 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4412 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004413 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4414 HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
4415 HDSPM_SYNC_CHECK("TCO SyncCHeck", 2),
4416 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
Takashi Iwai763f3562005-06-03 11:25:34 +02004417 HDSPM_LINE_OUT("Line Out", 0),
4418 HDSPM_TX_64("TX 64 channels mode", 0),
4419 HDSPM_C_TMS("Clear Track Marker", 0),
4420 HDSPM_SAFE_MODE("Safe Mode", 0),
Adrian Knoth700d1ef2011-07-29 03:11:02 +02004421 HDSPM_INPUT_SELECT("Input Select", 0),
4422 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004423};
4424
4425
4426static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
4427 HDSPM_MIXER("Mixer", 0),
4428 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4429 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4430 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4431 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4432 HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
4433 HDSPM_TX_64("TX 64 channels mode", 0),
4434 HDSPM_C_TMS("Clear Track Marker", 0),
Adrian Knoth700d1ef2011-07-29 03:11:02 +02004435 HDSPM_SAFE_MODE("Safe Mode", 0),
4436 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004437};
4438
Adrian Knoth0dca1792011-01-26 19:32:14 +01004439static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004440 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004441 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004442 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4443 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4444 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4445 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004446 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004447 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4448 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4449 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4450 HDSPM_SYNC_CHECK("ADAT SyncCheck", 3),
4451 HDSPM_SYNC_CHECK("TCO SyncCheck", 4),
4452 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 5),
4453 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4454 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4455 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4456 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT Frequency", 3),
4457 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 4),
4458 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5)
4459
4460 /*
4461 HDSPM_INPUT_SELECT("Input Select", 0),
4462 HDSPM_SPDIF_OPTICAL("SPDIF Out Optical", 0),
4463 HDSPM_PROFESSIONAL("SPDIF Out Professional", 0);
4464 HDSPM_SPDIF_IN("SPDIF In", 0);
4465 HDSPM_BREAKOUT_CABLE("Breakout Cable", 0);
4466 HDSPM_INPUT_LEVEL("Input Level", 0);
4467 HDSPM_OUTPUT_LEVEL("Output Level", 0);
4468 HDSPM_PHONES("Phones", 0);
4469 */
4470};
4471
4472static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = {
4473 HDSPM_MIXER("Mixer", 0),
4474 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4475 HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0),
4476 HDSPM_PREF_SYNC_REF("Pref Sync Ref", 0),
4477 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4478 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4479 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4480 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4481 HDSPM_SYNC_CHECK("ADAT1 SyncCheck", 3),
4482 HDSPM_SYNC_CHECK("ADAT2 SyncCheck", 4),
4483 HDSPM_SYNC_CHECK("ADAT3 SyncCheck", 5),
4484 HDSPM_SYNC_CHECK("ADAT4 SyncCheck", 6),
4485 HDSPM_SYNC_CHECK("TCO SyncCheck", 7),
4486 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 8),
4487 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4488 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4489 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4490 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT1 Frequency", 3),
4491 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT2 Frequency", 4),
4492 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT3 Frequency", 5),
4493 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT4 Frequency", 6),
4494 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 7),
4495 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8)
4496};
4497
4498static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
4499 HDSPM_MIXER("Mixer", 0),
4500 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4501 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4502 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4503 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4504 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4505 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4506 HDSPM_SYNC_CHECK("WC Sync Check", 0),
4507 HDSPM_SYNC_CHECK("AES1 Sync Check", 1),
4508 HDSPM_SYNC_CHECK("AES2 Sync Check", 2),
4509 HDSPM_SYNC_CHECK("AES3 Sync Check", 3),
4510 HDSPM_SYNC_CHECK("AES4 Sync Check", 4),
4511 HDSPM_SYNC_CHECK("AES5 Sync Check", 5),
4512 HDSPM_SYNC_CHECK("AES6 Sync Check", 6),
4513 HDSPM_SYNC_CHECK("AES7 Sync Check", 7),
4514 HDSPM_SYNC_CHECK("AES8 Sync Check", 8),
4515 HDSPM_SYNC_CHECK("TCO Sync Check", 9),
4516 HDSPM_SYNC_CHECK("SYNC IN Sync Check", 10),
4517 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4518 HDSPM_AUTOSYNC_SAMPLE_RATE("AES1 Frequency", 1),
4519 HDSPM_AUTOSYNC_SAMPLE_RATE("AES2 Frequency", 2),
4520 HDSPM_AUTOSYNC_SAMPLE_RATE("AES3 Frequency", 3),
4521 HDSPM_AUTOSYNC_SAMPLE_RATE("AES4 Frequency", 4),
4522 HDSPM_AUTOSYNC_SAMPLE_RATE("AES5 Frequency", 5),
4523 HDSPM_AUTOSYNC_SAMPLE_RATE("AES6 Frequency", 6),
4524 HDSPM_AUTOSYNC_SAMPLE_RATE("AES7 Frequency", 7),
4525 HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8),
4526 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9),
4527 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004528 HDSPM_LINE_OUT("Line Out", 0),
4529 HDSPM_EMPHASIS("Emphasis", 0),
4530 HDSPM_DOLBY("Non Audio", 0),
4531 HDSPM_PROFESSIONAL("Professional", 0),
4532 HDSPM_C_TMS("Clear Track Marker", 0),
4533 HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
4534 HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
4535};
4536
Adrian Knoth0dca1792011-01-26 19:32:14 +01004537
4538
4539/* Control elements for the optional TCO module */
4540static struct snd_kcontrol_new snd_hdspm_controls_tco[] = {
4541 HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0),
4542 HDSPM_TCO_PULL("TCO Pull", 0),
4543 HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0),
4544 HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0),
4545 HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0),
4546 HDSPM_TCO_WORD_TERM("TCO Word Term", 0)
4547};
4548
4549
Takashi Iwai98274f02005-11-17 14:52:34 +01004550static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
Takashi Iwai763f3562005-06-03 11:25:34 +02004551
4552
Takashi Iwai98274f02005-11-17 14:52:34 +01004553static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004554{
4555 int i;
4556
Adrian Knoth0dca1792011-01-26 19:32:14 +01004557 for (i = hdspm->ds_out_channels; i < hdspm->ss_out_channels; ++i) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004558 if (hdspm->system_sample_rate > 48000) {
4559 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004560 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
4561 SNDRV_CTL_ELEM_ACCESS_READ |
4562 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004563 } else {
4564 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004565 SNDRV_CTL_ELEM_ACCESS_READWRITE |
4566 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004567 }
4568 snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
Adrian Knoth0dca1792011-01-26 19:32:14 +01004569 SNDRV_CTL_EVENT_MASK_INFO,
4570 &hdspm->playback_mixer_ctls[i]->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02004571 }
4572
4573 return 0;
4574}
4575
4576
Adrian Knoth0dca1792011-01-26 19:32:14 +01004577static int snd_hdspm_create_controls(struct snd_card *card,
4578 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004579{
4580 unsigned int idx, limit;
4581 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01004582 struct snd_kcontrol *kctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004583 struct snd_kcontrol_new *list = NULL;
Takashi Iwai763f3562005-06-03 11:25:34 +02004584
Adrian Knoth0dca1792011-01-26 19:32:14 +01004585 switch (hdspm->io_type) {
4586 case MADI:
4587 list = snd_hdspm_controls_madi;
4588 limit = ARRAY_SIZE(snd_hdspm_controls_madi);
4589 break;
4590 case MADIface:
4591 list = snd_hdspm_controls_madiface;
4592 limit = ARRAY_SIZE(snd_hdspm_controls_madiface);
4593 break;
4594 case AIO:
4595 list = snd_hdspm_controls_aio;
4596 limit = ARRAY_SIZE(snd_hdspm_controls_aio);
4597 break;
4598 case RayDAT:
4599 list = snd_hdspm_controls_raydat;
4600 limit = ARRAY_SIZE(snd_hdspm_controls_raydat);
4601 break;
4602 case AES32:
4603 list = snd_hdspm_controls_aes32;
4604 limit = ARRAY_SIZE(snd_hdspm_controls_aes32);
4605 break;
4606 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004607
Adrian Knoth0dca1792011-01-26 19:32:14 +01004608 if (NULL != list) {
4609 for (idx = 0; idx < limit; idx++) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004610 err = snd_ctl_add(card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004611 snd_ctl_new1(&list[idx], hdspm));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004612 if (err < 0)
4613 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004614 }
4615 }
4616
Takashi Iwai763f3562005-06-03 11:25:34 +02004617
Adrian Knoth0dca1792011-01-26 19:32:14 +01004618 /* create simple 1:1 playback mixer controls */
Takashi Iwai763f3562005-06-03 11:25:34 +02004619 snd_hdspm_playback_mixer.name = "Chn";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004620 if (hdspm->system_sample_rate >= 128000) {
4621 limit = hdspm->qs_out_channels;
4622 } else if (hdspm->system_sample_rate >= 64000) {
4623 limit = hdspm->ds_out_channels;
4624 } else {
4625 limit = hdspm->ss_out_channels;
4626 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004627 for (idx = 0; idx < limit; ++idx) {
4628 snd_hdspm_playback_mixer.index = idx + 1;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004629 kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm);
4630 err = snd_ctl_add(card, kctl);
4631 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004632 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004633 hdspm->playback_mixer_ctls[idx] = kctl;
4634 }
4635
Adrian Knoth0dca1792011-01-26 19:32:14 +01004636
4637 if (hdspm->tco) {
4638 /* add tco control elements */
4639 list = snd_hdspm_controls_tco;
4640 limit = ARRAY_SIZE(snd_hdspm_controls_tco);
4641 for (idx = 0; idx < limit; idx++) {
4642 err = snd_ctl_add(card,
4643 snd_ctl_new1(&list[idx], hdspm));
4644 if (err < 0)
4645 return err;
4646 }
4647 }
4648
Takashi Iwai763f3562005-06-03 11:25:34 +02004649 return 0;
4650}
4651
4652/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01004653 /proc interface
Takashi Iwai763f3562005-06-03 11:25:34 +02004654 ------------------------------------------------------------*/
4655
4656static void
Remy Bruno3cee5a62006-10-16 12:46:32 +02004657snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
4658 struct snd_info_buffer *buffer)
Takashi Iwai763f3562005-06-03 11:25:34 +02004659{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004660 struct hdspm *hdspm = entry->private_data;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004661 unsigned int status, status2, control, freq;
4662
Takashi Iwai763f3562005-06-03 11:25:34 +02004663 char *pref_sync_ref;
4664 char *autosync_ref;
4665 char *system_clock_mode;
Takashi Iwai763f3562005-06-03 11:25:34 +02004666 char *insel;
Takashi Iwai763f3562005-06-03 11:25:34 +02004667 int x, x2;
4668
Adrian Knoth0dca1792011-01-26 19:32:14 +01004669 /* TCO stuff */
4670 int a, ltc, frames, seconds, minutes, hours;
4671 unsigned int period;
4672 u64 freq_const = 0;
4673 u32 rate;
4674
Takashi Iwai763f3562005-06-03 11:25:34 +02004675 status = hdspm_read(hdspm, HDSPM_statusRegister);
4676 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004677 control = hdspm->control_register;
4678 freq = hdspm_read(hdspm, HDSPM_timecodeRegister);
Takashi Iwai763f3562005-06-03 11:25:34 +02004679
4680 snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004681 hdspm->card_name, hdspm->card->number + 1,
4682 hdspm->firmware_rev,
4683 (status2 & HDSPM_version0) |
4684 (status2 & HDSPM_version1) | (status2 &
4685 HDSPM_version2));
4686
4687 snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n",
4688 (hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF,
4689 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF);
Takashi Iwai763f3562005-06-03 11:25:34 +02004690
4691 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004692 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
Takashi Iwai763f3562005-06-03 11:25:34 +02004693
4694 snd_iprintf(buffer, "--- System ---\n");
4695
4696 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004697 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4698 status & HDSPM_audioIRQPending,
4699 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4700 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4701 hdspm->irq_count);
Takashi Iwai763f3562005-06-03 11:25:34 +02004702 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004703 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4704 "estimated= %ld (bytes)\n",
4705 ((status & HDSPM_BufferID) ? 1 : 0),
4706 (status & HDSPM_BufferPositionMask),
4707 (status & HDSPM_BufferPositionMask) %
4708 (2 * (int)hdspm->period_bytes),
4709 ((status & HDSPM_BufferPositionMask) - 64) %
4710 (2 * (int)hdspm->period_bytes),
4711 (long) hdspm_hw_pointer(hdspm) * 4);
Takashi Iwai763f3562005-06-03 11:25:34 +02004712
4713 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004714 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4715 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4716 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4717 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4718 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
Takashi Iwai763f3562005-06-03 11:25:34 +02004719 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004720 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4721 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4722 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4723 snd_iprintf(buffer,
4724 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4725 "status2=0x%x\n",
4726 hdspm->control_register, hdspm->control2_register,
4727 status, status2);
4728 if (status & HDSPM_tco_detect) {
4729 snd_iprintf(buffer, "TCO module detected.\n");
4730 a = hdspm_read(hdspm, HDSPM_RD_TCO+4);
4731 if (a & HDSPM_TCO1_LTC_Input_valid) {
4732 snd_iprintf(buffer, " LTC valid, ");
4733 switch (a & (HDSPM_TCO1_LTC_Format_LSB |
4734 HDSPM_TCO1_LTC_Format_MSB)) {
4735 case 0:
4736 snd_iprintf(buffer, "24 fps, ");
4737 break;
4738 case HDSPM_TCO1_LTC_Format_LSB:
4739 snd_iprintf(buffer, "25 fps, ");
4740 break;
4741 case HDSPM_TCO1_LTC_Format_MSB:
4742 snd_iprintf(buffer, "29.97 fps, ");
4743 break;
4744 default:
4745 snd_iprintf(buffer, "30 fps, ");
4746 break;
4747 }
4748 if (a & HDSPM_TCO1_set_drop_frame_flag) {
4749 snd_iprintf(buffer, "drop frame\n");
4750 } else {
4751 snd_iprintf(buffer, "full frame\n");
4752 }
4753 } else {
4754 snd_iprintf(buffer, " no LTC\n");
4755 }
4756 if (a & HDSPM_TCO1_Video_Input_Format_NTSC) {
4757 snd_iprintf(buffer, " Video: NTSC\n");
4758 } else if (a & HDSPM_TCO1_Video_Input_Format_PAL) {
4759 snd_iprintf(buffer, " Video: PAL\n");
4760 } else {
4761 snd_iprintf(buffer, " No video\n");
4762 }
4763 if (a & HDSPM_TCO1_TCO_lock) {
4764 snd_iprintf(buffer, " Sync: lock\n");
4765 } else {
4766 snd_iprintf(buffer, " Sync: no lock\n");
4767 }
4768
4769 switch (hdspm->io_type) {
4770 case MADI:
4771 case AES32:
4772 freq_const = 110069313433624ULL;
4773 break;
4774 case RayDAT:
4775 case AIO:
4776 freq_const = 104857600000000ULL;
4777 break;
4778 case MADIface:
4779 break; /* no TCO possible */
4780 }
4781
4782 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
4783 snd_iprintf(buffer, " period: %u\n", period);
4784
4785
4786 /* rate = freq_const/period; */
4787 rate = div_u64(freq_const, period);
4788
4789 if (control & HDSPM_QuadSpeed) {
4790 rate *= 4;
4791 } else if (control & HDSPM_DoubleSpeed) {
4792 rate *= 2;
4793 }
4794
4795 snd_iprintf(buffer, " Frequency: %u Hz\n",
4796 (unsigned int) rate);
4797
4798 ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
4799 frames = ltc & 0xF;
4800 ltc >>= 4;
4801 frames += (ltc & 0x3) * 10;
4802 ltc >>= 4;
4803 seconds = ltc & 0xF;
4804 ltc >>= 4;
4805 seconds += (ltc & 0x7) * 10;
4806 ltc >>= 4;
4807 minutes = ltc & 0xF;
4808 ltc >>= 4;
4809 minutes += (ltc & 0x7) * 10;
4810 ltc >>= 4;
4811 hours = ltc & 0xF;
4812 ltc >>= 4;
4813 hours += (ltc & 0x3) * 10;
4814 snd_iprintf(buffer,
4815 " LTC In: %02d:%02d:%02d:%02d\n",
4816 hours, minutes, seconds, frames);
4817
4818 } else {
4819 snd_iprintf(buffer, "No TCO module detected.\n");
4820 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004821
4822 snd_iprintf(buffer, "--- Settings ---\n");
4823
Adrian Knoth7cb155f2011-08-15 00:22:53 +02004824 x = hdspm_get_latency(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02004825
4826 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004827 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4828 x, (unsigned long) hdspm->period_bytes);
Takashi Iwai763f3562005-06-03 11:25:34 +02004829
Adrian Knoth0dca1792011-01-26 19:32:14 +01004830 snd_iprintf(buffer, "Line out: %s\n",
4831 (hdspm->control_register & HDSPM_LineOut) ? "on " : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004832
4833 switch (hdspm->control_register & HDSPM_InputMask) {
4834 case HDSPM_InputOptical:
4835 insel = "Optical";
4836 break;
4837 case HDSPM_InputCoaxial:
4838 insel = "Coaxial";
4839 break;
4840 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01004841 insel = "Unkown";
Takashi Iwai763f3562005-06-03 11:25:34 +02004842 }
4843
Takashi Iwai763f3562005-06-03 11:25:34 +02004844 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004845 "ClearTrackMarker = %s, Transmit in %s Channel Mode, "
4846 "Auto Input %s\n",
4847 (hdspm->control_register & HDSPM_clr_tms) ? "on" : "off",
4848 (hdspm->control_register & HDSPM_TX_64ch) ? "64" : "56",
4849 (hdspm->control_register & HDSPM_AutoInp) ? "on" : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004850
Adrian Knoth0dca1792011-01-26 19:32:14 +01004851
Remy Bruno3cee5a62006-10-16 12:46:32 +02004852 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
Adrian Knoth0dca1792011-01-26 19:32:14 +01004853 system_clock_mode = "AutoSync";
Remy Bruno3cee5a62006-10-16 12:46:32 +02004854 else
Takashi Iwai763f3562005-06-03 11:25:34 +02004855 system_clock_mode = "Master";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004856 snd_iprintf(buffer, "AutoSync Reference: %s\n", system_clock_mode);
Takashi Iwai763f3562005-06-03 11:25:34 +02004857
4858 switch (hdspm_pref_sync_ref(hdspm)) {
4859 case HDSPM_SYNC_FROM_WORD:
4860 pref_sync_ref = "Word Clock";
4861 break;
4862 case HDSPM_SYNC_FROM_MADI:
4863 pref_sync_ref = "MADI Sync";
4864 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004865 case HDSPM_SYNC_FROM_TCO:
4866 pref_sync_ref = "TCO";
4867 break;
4868 case HDSPM_SYNC_FROM_SYNC_IN:
4869 pref_sync_ref = "Sync In";
4870 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004871 default:
4872 pref_sync_ref = "XXXX Clock";
4873 break;
4874 }
4875 snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004876 pref_sync_ref);
Takashi Iwai763f3562005-06-03 11:25:34 +02004877
4878 snd_iprintf(buffer, "System Clock Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004879 hdspm->system_sample_rate);
Takashi Iwai763f3562005-06-03 11:25:34 +02004880
4881
4882 snd_iprintf(buffer, "--- Status:\n");
4883
4884 x = status & HDSPM_madiSync;
4885 x2 = status2 & HDSPM_wcSync;
4886
4887 snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004888 (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
4889 "NoLock",
4890 (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
4891 "NoLock");
Takashi Iwai763f3562005-06-03 11:25:34 +02004892
4893 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004894 case HDSPM_AUTOSYNC_FROM_SYNC_IN:
4895 autosync_ref = "Sync In";
4896 break;
4897 case HDSPM_AUTOSYNC_FROM_TCO:
4898 autosync_ref = "TCO";
4899 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004900 case HDSPM_AUTOSYNC_FROM_WORD:
4901 autosync_ref = "Word Clock";
4902 break;
4903 case HDSPM_AUTOSYNC_FROM_MADI:
4904 autosync_ref = "MADI Sync";
4905 break;
4906 case HDSPM_AUTOSYNC_FROM_NONE:
4907 autosync_ref = "Input not valid";
4908 break;
4909 default:
4910 autosync_ref = "---";
4911 break;
4912 }
4913 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004914 "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
4915 autosync_ref, hdspm_external_sample_rate(hdspm),
4916 (status & HDSPM_madiFreqMask) >> 22,
4917 (status2 & HDSPM_wcFreqMask) >> 5);
Takashi Iwai763f3562005-06-03 11:25:34 +02004918
4919 snd_iprintf(buffer, "Input: %s, Mode=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004920 (status & HDSPM_AB_int) ? "Coax" : "Optical",
4921 (status & HDSPM_RX_64ch) ? "64 channels" :
4922 "56 channels");
Takashi Iwai763f3562005-06-03 11:25:34 +02004923
4924 snd_iprintf(buffer, "\n");
4925}
4926
Remy Bruno3cee5a62006-10-16 12:46:32 +02004927static void
4928snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
4929 struct snd_info_buffer *buffer)
4930{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004931 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004932 unsigned int status;
4933 unsigned int status2;
4934 unsigned int timecode;
4935 int pref_syncref;
4936 char *autosync_ref;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004937 int x;
4938
4939 status = hdspm_read(hdspm, HDSPM_statusRegister);
4940 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
4941 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
4942
4943 snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
4944 hdspm->card_name, hdspm->card->number + 1,
4945 hdspm->firmware_rev);
4946
4947 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
4948 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
4949
4950 snd_iprintf(buffer, "--- System ---\n");
4951
4952 snd_iprintf(buffer,
4953 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4954 status & HDSPM_audioIRQPending,
4955 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4956 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4957 hdspm->irq_count);
4958 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004959 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4960 "estimated= %ld (bytes)\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004961 ((status & HDSPM_BufferID) ? 1 : 0),
4962 (status & HDSPM_BufferPositionMask),
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004963 (status & HDSPM_BufferPositionMask) %
4964 (2 * (int)hdspm->period_bytes),
4965 ((status & HDSPM_BufferPositionMask) - 64) %
4966 (2 * (int)hdspm->period_bytes),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004967 (long) hdspm_hw_pointer(hdspm) * 4);
4968
4969 snd_iprintf(buffer,
4970 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4971 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4972 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4973 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4974 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
4975 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004976 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4977 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4978 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4979 snd_iprintf(buffer,
4980 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4981 "status2=0x%x\n",
4982 hdspm->control_register, hdspm->control2_register,
4983 status, status2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02004984
4985 snd_iprintf(buffer, "--- Settings ---\n");
4986
Adrian Knoth7cb155f2011-08-15 00:22:53 +02004987 x = hdspm_get_latency(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02004988
4989 snd_iprintf(buffer,
4990 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4991 x, (unsigned long) hdspm->period_bytes);
4992
Adrian Knoth0dca1792011-01-26 19:32:14 +01004993 snd_iprintf(buffer, "Line out: %s\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004994 (hdspm->
Adrian Knoth0dca1792011-01-26 19:32:14 +01004995 control_register & HDSPM_LineOut) ? "on " : "off");
Remy Bruno3cee5a62006-10-16 12:46:32 +02004996
4997 snd_iprintf(buffer,
4998 "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
4999 (hdspm->
5000 control_register & HDSPM_clr_tms) ? "on" : "off",
5001 (hdspm->
5002 control_register & HDSPM_Emphasis) ? "on" : "off",
5003 (hdspm->
5004 control_register & HDSPM_Dolby) ? "on" : "off");
5005
Remy Bruno3cee5a62006-10-16 12:46:32 +02005006
5007 pref_syncref = hdspm_pref_sync_ref(hdspm);
5008 if (pref_syncref == 0)
5009 snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
5010 else
5011 snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
5012 pref_syncref);
5013
5014 snd_iprintf(buffer, "System Clock Frequency: %d\n",
5015 hdspm->system_sample_rate);
5016
5017 snd_iprintf(buffer, "Double speed: %s\n",
5018 hdspm->control_register & HDSPM_DS_DoubleWire?
5019 "Double wire" : "Single wire");
5020 snd_iprintf(buffer, "Quad speed: %s\n",
5021 hdspm->control_register & HDSPM_QS_DoubleWire?
5022 "Double wire" :
5023 hdspm->control_register & HDSPM_QS_QuadWire?
5024 "Quad wire" : "Single wire");
5025
5026 snd_iprintf(buffer, "--- Status:\n");
5027
5028 snd_iprintf(buffer, "Word: %s Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01005029 (status & HDSPM_AES32_wcLock) ? "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005030 HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02005031
5032 for (x = 0; x < 8; x++) {
5033 snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005034 x+1,
5035 (status2 & (HDSPM_LockAES >> x)) ?
Adrian Knoth0dca1792011-01-26 19:32:14 +01005036 "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005037 HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02005038 }
5039
5040 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005041 case HDSPM_AES32_AUTOSYNC_FROM_NONE:
5042 autosync_ref = "None"; break;
5043 case HDSPM_AES32_AUTOSYNC_FROM_WORD:
5044 autosync_ref = "Word Clock"; break;
5045 case HDSPM_AES32_AUTOSYNC_FROM_AES1:
5046 autosync_ref = "AES1"; break;
5047 case HDSPM_AES32_AUTOSYNC_FROM_AES2:
5048 autosync_ref = "AES2"; break;
5049 case HDSPM_AES32_AUTOSYNC_FROM_AES3:
5050 autosync_ref = "AES3"; break;
5051 case HDSPM_AES32_AUTOSYNC_FROM_AES4:
5052 autosync_ref = "AES4"; break;
5053 case HDSPM_AES32_AUTOSYNC_FROM_AES5:
5054 autosync_ref = "AES5"; break;
5055 case HDSPM_AES32_AUTOSYNC_FROM_AES6:
5056 autosync_ref = "AES6"; break;
5057 case HDSPM_AES32_AUTOSYNC_FROM_AES7:
5058 autosync_ref = "AES7"; break;
5059 case HDSPM_AES32_AUTOSYNC_FROM_AES8:
5060 autosync_ref = "AES8"; break;
5061 default:
5062 autosync_ref = "---"; break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005063 }
5064 snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
5065
5066 snd_iprintf(buffer, "\n");
5067}
5068
Adrian Knoth0dca1792011-01-26 19:32:14 +01005069static void
5070snd_hdspm_proc_read_raydat(struct snd_info_entry *entry,
5071 struct snd_info_buffer *buffer)
5072{
5073 struct hdspm *hdspm = entry->private_data;
5074 unsigned int status1, status2, status3, control, i;
5075 unsigned int lock, sync;
5076
5077 status1 = hdspm_read(hdspm, HDSPM_RD_STATUS_1); /* s1 */
5078 status2 = hdspm_read(hdspm, HDSPM_RD_STATUS_2); /* freq */
5079 status3 = hdspm_read(hdspm, HDSPM_RD_STATUS_3); /* s2 */
5080
5081 control = hdspm->control_register;
5082
5083 snd_iprintf(buffer, "STATUS1: 0x%08x\n", status1);
5084 snd_iprintf(buffer, "STATUS2: 0x%08x\n", status2);
5085 snd_iprintf(buffer, "STATUS3: 0x%08x\n", status3);
5086
5087
5088 snd_iprintf(buffer, "\n*** CLOCK MODE\n\n");
5089
5090 snd_iprintf(buffer, "Clock mode : %s\n",
5091 (hdspm_system_clock_mode(hdspm) == 0) ? "master" : "slave");
5092 snd_iprintf(buffer, "System frequency: %d Hz\n",
5093 hdspm_get_system_sample_rate(hdspm));
5094
5095 snd_iprintf(buffer, "\n*** INPUT STATUS\n\n");
5096
5097 lock = 0x1;
5098 sync = 0x100;
5099
5100 for (i = 0; i < 8; i++) {
5101 snd_iprintf(buffer, "s1_input %d: Lock %d, Sync %d, Freq %s\n",
5102 i,
5103 (status1 & lock) ? 1 : 0,
5104 (status1 & sync) ? 1 : 0,
5105 texts_freq[(status2 >> (i * 4)) & 0xF]);
5106
5107 lock = lock<<1;
5108 sync = sync<<1;
5109 }
5110
5111 snd_iprintf(buffer, "WC input: Lock %d, Sync %d, Freq %s\n",
5112 (status1 & 0x1000000) ? 1 : 0,
5113 (status1 & 0x2000000) ? 1 : 0,
5114 texts_freq[(status1 >> 16) & 0xF]);
5115
5116 snd_iprintf(buffer, "TCO input: Lock %d, Sync %d, Freq %s\n",
5117 (status1 & 0x4000000) ? 1 : 0,
5118 (status1 & 0x8000000) ? 1 : 0,
5119 texts_freq[(status1 >> 20) & 0xF]);
5120
5121 snd_iprintf(buffer, "SYNC IN: Lock %d, Sync %d, Freq %s\n",
5122 (status3 & 0x400) ? 1 : 0,
5123 (status3 & 0x800) ? 1 : 0,
5124 texts_freq[(status2 >> 12) & 0xF]);
5125
5126}
5127
Remy Bruno3cee5a62006-10-16 12:46:32 +02005128#ifdef CONFIG_SND_DEBUG
5129static void
Adrian Knoth0dca1792011-01-26 19:32:14 +01005130snd_hdspm_proc_read_debug(struct snd_info_entry *entry,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005131 struct snd_info_buffer *buffer)
5132{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005133 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005134
5135 int j,i;
5136
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005137 for (i = 0; i < 256 /* 1024*64 */; i += j) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02005138 snd_iprintf(buffer, "0x%08X: ", i);
5139 for (j = 0; j < 16; j += 4)
5140 snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
5141 snd_iprintf(buffer, "\n");
5142 }
5143}
5144#endif
5145
5146
Adrian Knoth0dca1792011-01-26 19:32:14 +01005147static void snd_hdspm_proc_ports_in(struct snd_info_entry *entry,
5148 struct snd_info_buffer *buffer)
5149{
5150 struct hdspm *hdspm = entry->private_data;
5151 int i;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005152
Adrian Knoth0dca1792011-01-26 19:32:14 +01005153 snd_iprintf(buffer, "# generated by hdspm\n");
5154
5155 for (i = 0; i < hdspm->max_channels_in; i++) {
5156 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_in[i]);
5157 }
5158}
5159
5160static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry,
5161 struct snd_info_buffer *buffer)
5162{
5163 struct hdspm *hdspm = entry->private_data;
5164 int i;
5165
5166 snd_iprintf(buffer, "# generated by hdspm\n");
5167
5168 for (i = 0; i < hdspm->max_channels_out; i++) {
5169 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_out[i]);
5170 }
5171}
5172
5173
5174static void __devinit snd_hdspm_proc_init(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005175{
Takashi Iwai98274f02005-11-17 14:52:34 +01005176 struct snd_info_entry *entry;
Takashi Iwai763f3562005-06-03 11:25:34 +02005177
Adrian Knoth0dca1792011-01-26 19:32:14 +01005178 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) {
5179 switch (hdspm->io_type) {
5180 case AES32:
5181 snd_info_set_text_ops(entry, hdspm,
5182 snd_hdspm_proc_read_aes32);
5183 break;
5184 case MADI:
5185 snd_info_set_text_ops(entry, hdspm,
5186 snd_hdspm_proc_read_madi);
5187 break;
5188 case MADIface:
5189 /* snd_info_set_text_ops(entry, hdspm,
5190 snd_hdspm_proc_read_madiface); */
5191 break;
5192 case RayDAT:
5193 snd_info_set_text_ops(entry, hdspm,
5194 snd_hdspm_proc_read_raydat);
5195 break;
5196 case AIO:
5197 break;
5198 }
5199 }
5200
5201 if (!snd_card_proc_new(hdspm->card, "ports.in", &entry)) {
5202 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_in);
5203 }
5204
5205 if (!snd_card_proc_new(hdspm->card, "ports.out", &entry)) {
5206 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_out);
5207 }
5208
Remy Bruno3cee5a62006-10-16 12:46:32 +02005209#ifdef CONFIG_SND_DEBUG
5210 /* debug file to read all hdspm registers */
5211 if (!snd_card_proc_new(hdspm->card, "debug", &entry))
5212 snd_info_set_text_ops(entry, hdspm,
5213 snd_hdspm_proc_read_debug);
5214#endif
Takashi Iwai763f3562005-06-03 11:25:34 +02005215}
5216
5217/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005218 hdspm intitialize
Takashi Iwai763f3562005-06-03 11:25:34 +02005219 ------------------------------------------------------------*/
5220
Takashi Iwai98274f02005-11-17 14:52:34 +01005221static int snd_hdspm_set_defaults(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005222{
Takashi Iwai763f3562005-06-03 11:25:34 +02005223 /* ASSUMPTION: hdspm->lock is either held, or there is no need to
Joe Perches561de312007-12-18 13:13:47 +01005224 hold it (e.g. during module initialization).
Adrian Knoth0dca1792011-01-26 19:32:14 +01005225 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005226
5227 /* set defaults: */
5228
Adrian Knoth0dca1792011-01-26 19:32:14 +01005229 hdspm->settings_register = 0;
5230
5231 switch (hdspm->io_type) {
5232 case MADI:
5233 case MADIface:
5234 hdspm->control_register =
5235 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5236 break;
5237
5238 case RayDAT:
5239 case AIO:
5240 hdspm->settings_register = 0x1 + 0x1000;
5241 /* Magic values are: LAT_0, LAT_2, Master, freq1, tx64ch, inp_0,
5242 * line_out */
5243 hdspm->control_register =
5244 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5245 break;
5246
5247 case AES32:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005248 hdspm->control_register =
5249 HDSPM_ClockModeMaster | /* Master Cloack Mode on */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005250 hdspm_encode_latency(7) | /* latency max=8192samples */
Remy Bruno3cee5a62006-10-16 12:46:32 +02005251 HDSPM_SyncRef0 | /* AES1 is syncclock */
5252 HDSPM_LineOut | /* Analog output in */
5253 HDSPM_Professional; /* Professional mode */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005254 break;
5255 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005256
5257 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5258
Adrian Knoth0dca1792011-01-26 19:32:14 +01005259 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005260 /* No control2 register for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005261#ifdef SNDRV_BIG_ENDIAN
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005262 hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
Takashi Iwai763f3562005-06-03 11:25:34 +02005263#else
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005264 hdspm->control2_register = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005265#endif
5266
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005267 hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
5268 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005269 hdspm_compute_period_size(hdspm);
5270
5271 /* silence everything */
5272
5273 all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
5274
Adrian Knoth0dca1792011-01-26 19:32:14 +01005275 if (hdspm->io_type == AIO || hdspm->io_type == RayDAT) {
5276 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
Takashi Iwai763f3562005-06-03 11:25:34 +02005277 }
5278
5279 /* set a default rate so that the channel map is set up. */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005280 hdspm_set_rate(hdspm, 48000, 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02005281
5282 return 0;
5283}
5284
5285
5286/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005287 interrupt
Takashi Iwai763f3562005-06-03 11:25:34 +02005288 ------------------------------------------------------------*/
5289
David Howells7d12e782006-10-05 14:55:46 +01005290static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02005291{
Takashi Iwai98274f02005-11-17 14:52:34 +01005292 struct hdspm *hdspm = (struct hdspm *) dev_id;
Takashi Iwai763f3562005-06-03 11:25:34 +02005293 unsigned int status;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005294 int i, audio, midi, schedule = 0;
5295 /* cycles_t now; */
Takashi Iwai763f3562005-06-03 11:25:34 +02005296
5297 status = hdspm_read(hdspm, HDSPM_statusRegister);
5298
5299 audio = status & HDSPM_audioIRQPending;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005300 midi = status & (HDSPM_midi0IRQPending | HDSPM_midi1IRQPending |
5301 HDSPM_midi2IRQPending | HDSPM_midi3IRQPending);
Takashi Iwai763f3562005-06-03 11:25:34 +02005302
Adrian Knoth0dca1792011-01-26 19:32:14 +01005303 /* now = get_cycles(); */
5304 /**
5305 * LAT_2..LAT_0 period counter (win) counter (mac)
5306 * 6 4096 ~256053425 ~514672358
5307 * 5 2048 ~128024983 ~257373821
5308 * 4 1024 ~64023706 ~128718089
5309 * 3 512 ~32005945 ~64385999
5310 * 2 256 ~16003039 ~32260176
5311 * 1 128 ~7998738 ~16194507
5312 * 0 64 ~3998231 ~8191558
5313 **/
5314 /*
5315 snd_printk(KERN_INFO "snd_hdspm_interrupt %llu @ %llx\n",
5316 now-hdspm->last_interrupt, status & 0xFFC0);
5317 hdspm->last_interrupt = now;
5318 */
5319
5320 if (!audio && !midi)
Takashi Iwai763f3562005-06-03 11:25:34 +02005321 return IRQ_NONE;
5322
5323 hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
5324 hdspm->irq_count++;
5325
Takashi Iwai763f3562005-06-03 11:25:34 +02005326
5327 if (audio) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005328 if (hdspm->capture_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005329 snd_pcm_period_elapsed(hdspm->capture_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005330
5331 if (hdspm->playback_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005332 snd_pcm_period_elapsed(hdspm->playback_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005333 }
5334
Adrian Knoth0dca1792011-01-26 19:32:14 +01005335 if (midi) {
5336 i = 0;
5337 while (i < hdspm->midiPorts) {
5338 if ((hdspm_read(hdspm,
5339 hdspm->midi[i].statusIn) & 0xff) &&
5340 (status & hdspm->midi[i].irq)) {
5341 /* we disable interrupts for this input until
5342 * processing is done
5343 */
5344 hdspm->control_register &= ~hdspm->midi[i].ie;
5345 hdspm_write(hdspm, HDSPM_controlRegister,
5346 hdspm->control_register);
5347 hdspm->midi[i].pending = 1;
5348 schedule = 1;
5349 }
5350
5351 i++;
5352 }
5353
5354 if (schedule)
5355 tasklet_hi_schedule(&hdspm->midi_tasklet);
Takashi Iwai763f3562005-06-03 11:25:34 +02005356 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005357
Takashi Iwai763f3562005-06-03 11:25:34 +02005358 return IRQ_HANDLED;
5359}
5360
5361/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005362 pcm interface
Takashi Iwai763f3562005-06-03 11:25:34 +02005363 ------------------------------------------------------------*/
5364
5365
Adrian Knoth0dca1792011-01-26 19:32:14 +01005366static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream
5367 *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005368{
Takashi Iwai98274f02005-11-17 14:52:34 +01005369 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005370 return hdspm_hw_pointer(hdspm);
5371}
5372
Takashi Iwai763f3562005-06-03 11:25:34 +02005373
Takashi Iwai98274f02005-11-17 14:52:34 +01005374static int snd_hdspm_reset(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005375{
Takashi Iwai98274f02005-11-17 14:52:34 +01005376 struct snd_pcm_runtime *runtime = substream->runtime;
5377 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5378 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005379
5380 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5381 other = hdspm->capture_substream;
5382 else
5383 other = hdspm->playback_substream;
5384
5385 if (hdspm->running)
5386 runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
5387 else
5388 runtime->status->hw_ptr = 0;
5389 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005390 struct snd_pcm_substream *s;
5391 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01005392 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005393 if (s == other) {
5394 oruntime->status->hw_ptr =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005395 runtime->status->hw_ptr;
Takashi Iwai763f3562005-06-03 11:25:34 +02005396 break;
5397 }
5398 }
5399 }
5400 return 0;
5401}
5402
Takashi Iwai98274f02005-11-17 14:52:34 +01005403static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
5404 struct snd_pcm_hw_params *params)
Takashi Iwai763f3562005-06-03 11:25:34 +02005405{
Takashi Iwai98274f02005-11-17 14:52:34 +01005406 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005407 int err;
5408 int i;
5409 pid_t this_pid;
5410 pid_t other_pid;
Takashi Iwai763f3562005-06-03 11:25:34 +02005411
5412 spin_lock_irq(&hdspm->lock);
5413
5414 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5415 this_pid = hdspm->playback_pid;
5416 other_pid = hdspm->capture_pid;
5417 } else {
5418 this_pid = hdspm->capture_pid;
5419 other_pid = hdspm->playback_pid;
5420 }
5421
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005422 if (other_pid > 0 && this_pid != other_pid) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005423
5424 /* The other stream is open, and not by the same
5425 task as this one. Make sure that the parameters
5426 that matter are the same.
Adrian Knoth0dca1792011-01-26 19:32:14 +01005427 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005428
5429 if (params_rate(params) != hdspm->system_sample_rate) {
5430 spin_unlock_irq(&hdspm->lock);
5431 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005432 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005433 return -EBUSY;
5434 }
5435
5436 if (params_period_size(params) != hdspm->period_bytes / 4) {
5437 spin_unlock_irq(&hdspm->lock);
5438 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005439 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005440 return -EBUSY;
5441 }
5442
5443 }
5444 /* We're fine. */
5445 spin_unlock_irq(&hdspm->lock);
5446
5447 /* how to make sure that the rate matches an externally-set one ? */
5448
5449 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005450 err = hdspm_set_rate(hdspm, params_rate(params), 0);
5451 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005452 snd_printk(KERN_INFO "err on hdspm_set_rate: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005453 spin_unlock_irq(&hdspm->lock);
5454 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005455 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005456 return err;
5457 }
5458 spin_unlock_irq(&hdspm->lock);
5459
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005460 err = hdspm_set_interrupt_interval(hdspm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005461 params_period_size(params));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005462 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005463 snd_printk(KERN_INFO "err on hdspm_set_interrupt_interval: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005464 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005465 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005466 return err;
5467 }
5468
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005469 /* Memory allocation, takashi's method, dont know if we should
5470 * spinlock
5471 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005472 /* malloc all buffer even if not enabled to get sure */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005473 /* Update for MADI rev 204: we need to allocate for all channels,
5474 * otherwise it doesn't work at 96kHz */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005475
Takashi Iwai763f3562005-06-03 11:25:34 +02005476 err =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005477 snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
5478 if (err < 0) {
5479 snd_printk(KERN_INFO "err on snd_pcm_lib_malloc_pages: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005480 return err;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005481 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005482
Takashi Iwai763f3562005-06-03 11:25:34 +02005483 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5484
Takashi Iwai77a23f22008-08-21 13:00:13 +02005485 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferOut,
Takashi Iwai763f3562005-06-03 11:25:34 +02005486 params_channels(params));
5487
5488 for (i = 0; i < params_channels(params); ++i)
5489 snd_hdspm_enable_out(hdspm, i, 1);
5490
5491 hdspm->playback_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005492 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005493 snd_printdd("Allocated sample buffer for playback at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005494 hdspm->playback_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005495 } else {
Takashi Iwai77a23f22008-08-21 13:00:13 +02005496 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn,
Takashi Iwai763f3562005-06-03 11:25:34 +02005497 params_channels(params));
5498
5499 for (i = 0; i < params_channels(params); ++i)
5500 snd_hdspm_enable_in(hdspm, i, 1);
5501
5502 hdspm->capture_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005503 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005504 snd_printdd("Allocated sample buffer for capture at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005505 hdspm->capture_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005506 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005507
Remy Bruno3cee5a62006-10-16 12:46:32 +02005508 /*
5509 snd_printdd("Allocated sample buffer for %s at 0x%08X\n",
5510 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5511 "playback" : "capture",
Takashi Iwai77a23f22008-08-21 13:00:13 +02005512 snd_pcm_sgbuf_get_addr(substream, 0));
Adrian Knoth0dca1792011-01-26 19:32:14 +01005513 */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005514 /*
Adrian Knoth0dca1792011-01-26 19:32:14 +01005515 snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n",
5516 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5517 "playback" : "capture",
5518 params_rate(params), params_channels(params),
5519 params_buffer_size(params));
5520 */
5521
5522
5523 /* Switch to native float format if requested */
5524 if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) {
5525 if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT))
5526 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE float format.\n");
5527
5528 hdspm->control_register |= HDSPe_FLOAT_FORMAT;
5529 } else if (SNDRV_PCM_FORMAT_S32_LE == params_format(params)) {
5530 if (hdspm->control_register & HDSPe_FLOAT_FORMAT)
5531 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE integer format.\n");
5532
5533 hdspm->control_register &= ~HDSPe_FLOAT_FORMAT;
5534 }
5535 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5536
Takashi Iwai763f3562005-06-03 11:25:34 +02005537 return 0;
5538}
5539
Takashi Iwai98274f02005-11-17 14:52:34 +01005540static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005541{
5542 int i;
Takashi Iwai98274f02005-11-17 14:52:34 +01005543 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005544
5545 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5546
Adrian Knoth0dca1792011-01-26 19:32:14 +01005547 /* params_channels(params) should be enough,
Takashi Iwai763f3562005-06-03 11:25:34 +02005548 but to get sure in case of error */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005549 for (i = 0; i < hdspm->max_channels_out; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005550 snd_hdspm_enable_out(hdspm, i, 0);
5551
5552 hdspm->playback_buffer = NULL;
5553 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005554 for (i = 0; i < hdspm->max_channels_in; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005555 snd_hdspm_enable_in(hdspm, i, 0);
5556
5557 hdspm->capture_buffer = NULL;
5558
5559 }
5560
5561 snd_pcm_lib_free_pages(substream);
5562
5563 return 0;
5564}
5565
Adrian Knoth0dca1792011-01-26 19:32:14 +01005566
Takashi Iwai98274f02005-11-17 14:52:34 +01005567static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005568 struct snd_pcm_channel_info *info)
Takashi Iwai763f3562005-06-03 11:25:34 +02005569{
Takashi Iwai98274f02005-11-17 14:52:34 +01005570 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005571
Adrian Knoth0dca1792011-01-26 19:32:14 +01005572 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5573 if (snd_BUG_ON(info->channel >= hdspm->max_channels_out)) {
5574 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel out of range (%d)\n", info->channel);
5575 return -EINVAL;
5576 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005577
Adrian Knoth0dca1792011-01-26 19:32:14 +01005578 if (hdspm->channel_map_out[info->channel] < 0) {
5579 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel %d mapped out\n", info->channel);
5580 return -EINVAL;
5581 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005582
Adrian Knoth0dca1792011-01-26 19:32:14 +01005583 info->offset = hdspm->channel_map_out[info->channel] *
5584 HDSPM_CHANNEL_BUFFER_BYTES;
5585 } else {
5586 if (snd_BUG_ON(info->channel >= hdspm->max_channels_in)) {
5587 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel out of range (%d)\n", info->channel);
5588 return -EINVAL;
5589 }
5590
5591 if (hdspm->channel_map_in[info->channel] < 0) {
5592 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel %d mapped out\n", info->channel);
5593 return -EINVAL;
5594 }
5595
5596 info->offset = hdspm->channel_map_in[info->channel] *
5597 HDSPM_CHANNEL_BUFFER_BYTES;
5598 }
5599
Takashi Iwai763f3562005-06-03 11:25:34 +02005600 info->first = 0;
5601 info->step = 32;
5602 return 0;
5603}
5604
Adrian Knoth0dca1792011-01-26 19:32:14 +01005605
Takashi Iwai98274f02005-11-17 14:52:34 +01005606static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005607 unsigned int cmd, void *arg)
Takashi Iwai763f3562005-06-03 11:25:34 +02005608{
5609 switch (cmd) {
5610 case SNDRV_PCM_IOCTL1_RESET:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005611 return snd_hdspm_reset(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005612
5613 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Adrian Knoth0dca1792011-01-26 19:32:14 +01005614 {
5615 struct snd_pcm_channel_info *info = arg;
5616 return snd_hdspm_channel_info(substream, info);
5617 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005618 default:
5619 break;
5620 }
5621
5622 return snd_pcm_lib_ioctl(substream, cmd, arg);
5623}
5624
Takashi Iwai98274f02005-11-17 14:52:34 +01005625static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
Takashi Iwai763f3562005-06-03 11:25:34 +02005626{
Takashi Iwai98274f02005-11-17 14:52:34 +01005627 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5628 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005629 int running;
5630
5631 spin_lock(&hdspm->lock);
5632 running = hdspm->running;
5633 switch (cmd) {
5634 case SNDRV_PCM_TRIGGER_START:
5635 running |= 1 << substream->stream;
5636 break;
5637 case SNDRV_PCM_TRIGGER_STOP:
5638 running &= ~(1 << substream->stream);
5639 break;
5640 default:
5641 snd_BUG();
5642 spin_unlock(&hdspm->lock);
5643 return -EINVAL;
5644 }
5645 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5646 other = hdspm->capture_substream;
5647 else
5648 other = hdspm->playback_substream;
5649
5650 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005651 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01005652 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005653 if (s == other) {
5654 snd_pcm_trigger_done(s, substream);
5655 if (cmd == SNDRV_PCM_TRIGGER_START)
5656 running |= 1 << s->stream;
5657 else
5658 running &= ~(1 << s->stream);
5659 goto _ok;
5660 }
5661 }
5662 if (cmd == SNDRV_PCM_TRIGGER_START) {
5663 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005664 && substream->stream ==
5665 SNDRV_PCM_STREAM_CAPTURE)
Takashi Iwai763f3562005-06-03 11:25:34 +02005666 hdspm_silence_playback(hdspm);
5667 } else {
5668 if (running &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01005669 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Takashi Iwai763f3562005-06-03 11:25:34 +02005670 hdspm_silence_playback(hdspm);
5671 }
5672 } else {
5673 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
5674 hdspm_silence_playback(hdspm);
5675 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005676_ok:
Takashi Iwai763f3562005-06-03 11:25:34 +02005677 snd_pcm_trigger_done(substream, substream);
5678 if (!hdspm->running && running)
5679 hdspm_start_audio(hdspm);
5680 else if (hdspm->running && !running)
5681 hdspm_stop_audio(hdspm);
5682 hdspm->running = running;
5683 spin_unlock(&hdspm->lock);
5684
5685 return 0;
5686}
5687
Takashi Iwai98274f02005-11-17 14:52:34 +01005688static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005689{
5690 return 0;
5691}
5692
Adrian Knoth0dca1792011-01-26 19:32:14 +01005693static unsigned int period_sizes_old[] = {
Adrian Knoth135d1532011-08-15 00:22:50 +02005694 64, 128, 256, 512, 1024, 2048, 4096, 8192
Adrian Knoth0dca1792011-01-26 19:32:14 +01005695};
5696
5697static unsigned int period_sizes_new[] = {
Adrian Knoth1ad59722011-08-15 00:22:52 +02005698 64, 128, 256, 512, 1024, 2048, 4096, 32
Adrian Knoth0dca1792011-01-26 19:32:14 +01005699};
5700
5701/* RayDAT and AIO always have a buffer of 16384 samples per channel */
5702static unsigned int raydat_aio_buffer_sizes[] = {
5703 16384
5704};
Takashi Iwai763f3562005-06-03 11:25:34 +02005705
Takashi Iwai98274f02005-11-17 14:52:34 +01005706static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005707 .info = (SNDRV_PCM_INFO_MMAP |
5708 SNDRV_PCM_INFO_MMAP_VALID |
5709 SNDRV_PCM_INFO_NONINTERLEAVED |
5710 SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
5711 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5712 .rates = (SNDRV_PCM_RATE_32000 |
5713 SNDRV_PCM_RATE_44100 |
5714 SNDRV_PCM_RATE_48000 |
5715 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005716 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5717 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ),
Takashi Iwai763f3562005-06-03 11:25:34 +02005718 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005719 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005720 .channels_min = 1,
5721 .channels_max = HDSPM_MAX_CHANNELS,
5722 .buffer_bytes_max =
5723 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
Adrian Knoth1b6fa102011-08-15 00:22:51 +02005724 .period_bytes_min = (32 * 4),
Adrian Knoth0dca1792011-01-26 19:32:14 +01005725 .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005726 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005727 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005728 .fifo_size = 0
5729};
5730
Takashi Iwai98274f02005-11-17 14:52:34 +01005731static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005732 .info = (SNDRV_PCM_INFO_MMAP |
5733 SNDRV_PCM_INFO_MMAP_VALID |
5734 SNDRV_PCM_INFO_NONINTERLEAVED |
5735 SNDRV_PCM_INFO_SYNC_START),
5736 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5737 .rates = (SNDRV_PCM_RATE_32000 |
5738 SNDRV_PCM_RATE_44100 |
5739 SNDRV_PCM_RATE_48000 |
5740 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005741 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5742 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
Takashi Iwai763f3562005-06-03 11:25:34 +02005743 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005744 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005745 .channels_min = 1,
5746 .channels_max = HDSPM_MAX_CHANNELS,
5747 .buffer_bytes_max =
5748 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
Adrian Knoth1b6fa102011-08-15 00:22:51 +02005749 .period_bytes_min = (32 * 4),
Adrian Knoth0dca1792011-01-26 19:32:14 +01005750 .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005751 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005752 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005753 .fifo_size = 0
5754};
5755
Adrian Knoth0dca1792011-01-26 19:32:14 +01005756static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_old = {
5757 .count = ARRAY_SIZE(period_sizes_old),
5758 .list = period_sizes_old,
Takashi Iwai763f3562005-06-03 11:25:34 +02005759 .mask = 0
5760};
5761
Adrian Knoth0dca1792011-01-26 19:32:14 +01005762static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_new = {
5763 .count = ARRAY_SIZE(period_sizes_new),
5764 .list = period_sizes_new,
5765 .mask = 0
5766};
Takashi Iwai763f3562005-06-03 11:25:34 +02005767
Adrian Knoth0dca1792011-01-26 19:32:14 +01005768static struct snd_pcm_hw_constraint_list hw_constraints_raydat_io_buffer = {
5769 .count = ARRAY_SIZE(raydat_aio_buffer_sizes),
5770 .list = raydat_aio_buffer_sizes,
5771 .mask = 0
5772};
5773
5774static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
5775 struct snd_pcm_hw_rule *rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005776{
Takashi Iwai98274f02005-11-17 14:52:34 +01005777 struct hdspm *hdspm = rule->private;
5778 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005779 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005780 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005781 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5782
Adrian Knoth0dca1792011-01-26 19:32:14 +01005783 if (r->min > 96000 && r->max <= 192000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005784 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005785 .min = hdspm->qs_in_channels,
5786 .max = hdspm->qs_in_channels,
5787 .integer = 1,
5788 };
5789 return snd_interval_refine(c, &t);
5790 } else if (r->min > 48000 && r->max <= 96000) {
5791 struct snd_interval t = {
5792 .min = hdspm->ds_in_channels,
5793 .max = hdspm->ds_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005794 .integer = 1,
5795 };
5796 return snd_interval_refine(c, &t);
5797 } else if (r->max < 64000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005798 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005799 .min = hdspm->ss_in_channels,
5800 .max = hdspm->ss_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005801 .integer = 1,
5802 };
5803 return snd_interval_refine(c, &t);
5804 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005805
Takashi Iwai763f3562005-06-03 11:25:34 +02005806 return 0;
5807}
5808
Adrian Knoth0dca1792011-01-26 19:32:14 +01005809static int snd_hdspm_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
Takashi Iwai98274f02005-11-17 14:52:34 +01005810 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005811{
Takashi Iwai98274f02005-11-17 14:52:34 +01005812 struct hdspm *hdspm = rule->private;
5813 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005814 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005815 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005816 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5817
Adrian Knoth0dca1792011-01-26 19:32:14 +01005818 if (r->min > 96000 && r->max <= 192000) {
5819 struct snd_interval t = {
5820 .min = hdspm->qs_out_channels,
5821 .max = hdspm->qs_out_channels,
5822 .integer = 1,
5823 };
5824 return snd_interval_refine(c, &t);
5825 } else if (r->min > 48000 && r->max <= 96000) {
5826 struct snd_interval t = {
5827 .min = hdspm->ds_out_channels,
5828 .max = hdspm->ds_out_channels,
5829 .integer = 1,
5830 };
5831 return snd_interval_refine(c, &t);
5832 } else if (r->max < 64000) {
5833 struct snd_interval t = {
5834 .min = hdspm->ss_out_channels,
5835 .max = hdspm->ss_out_channels,
5836 .integer = 1,
5837 };
5838 return snd_interval_refine(c, &t);
5839 } else {
5840 }
5841 return 0;
5842}
5843
5844static int snd_hdspm_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
5845 struct snd_pcm_hw_rule * rule)
5846{
5847 struct hdspm *hdspm = rule->private;
5848 struct snd_interval *c =
5849 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5850 struct snd_interval *r =
5851 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5852
5853 if (c->min >= hdspm->ss_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005854 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005855 .min = 32000,
5856 .max = 48000,
5857 .integer = 1,
5858 };
5859 return snd_interval_refine(r, &t);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005860 } else if (c->max <= hdspm->qs_in_channels) {
5861 struct snd_interval t = {
5862 .min = 128000,
5863 .max = 192000,
5864 .integer = 1,
5865 };
5866 return snd_interval_refine(r, &t);
5867 } else if (c->max <= hdspm->ds_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005868 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005869 .min = 64000,
5870 .max = 96000,
5871 .integer = 1,
5872 };
Takashi Iwai763f3562005-06-03 11:25:34 +02005873 return snd_interval_refine(r, &t);
5874 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005875
5876 return 0;
5877}
5878static int snd_hdspm_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
5879 struct snd_pcm_hw_rule *rule)
5880{
5881 struct hdspm *hdspm = rule->private;
5882 struct snd_interval *c =
5883 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5884 struct snd_interval *r =
5885 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5886
5887 if (c->min >= hdspm->ss_out_channels) {
5888 struct snd_interval t = {
5889 .min = 32000,
5890 .max = 48000,
5891 .integer = 1,
5892 };
5893 return snd_interval_refine(r, &t);
5894 } else if (c->max <= hdspm->qs_out_channels) {
5895 struct snd_interval t = {
5896 .min = 128000,
5897 .max = 192000,
5898 .integer = 1,
5899 };
5900 return snd_interval_refine(r, &t);
5901 } else if (c->max <= hdspm->ds_out_channels) {
5902 struct snd_interval t = {
5903 .min = 64000,
5904 .max = 96000,
5905 .integer = 1,
5906 };
5907 return snd_interval_refine(r, &t);
5908 }
5909
Takashi Iwai763f3562005-06-03 11:25:34 +02005910 return 0;
5911}
5912
Adrian Knoth0dca1792011-01-26 19:32:14 +01005913static int snd_hdspm_hw_rule_in_channels(struct snd_pcm_hw_params *params,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005914 struct snd_pcm_hw_rule *rule)
5915{
5916 unsigned int list[3];
5917 struct hdspm *hdspm = rule->private;
5918 struct snd_interval *c = hw_param_interval(params,
5919 SNDRV_PCM_HW_PARAM_CHANNELS);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005920
5921 list[0] = hdspm->qs_in_channels;
5922 list[1] = hdspm->ds_in_channels;
5923 list[2] = hdspm->ss_in_channels;
5924 return snd_interval_list(c, 3, list, 0);
5925}
5926
5927static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params,
5928 struct snd_pcm_hw_rule *rule)
5929{
5930 unsigned int list[3];
5931 struct hdspm *hdspm = rule->private;
5932 struct snd_interval *c = hw_param_interval(params,
5933 SNDRV_PCM_HW_PARAM_CHANNELS);
5934
5935 list[0] = hdspm->qs_out_channels;
5936 list[1] = hdspm->ds_out_channels;
5937 list[2] = hdspm->ss_out_channels;
5938 return snd_interval_list(c, 3, list, 0);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005939}
5940
5941
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005942static unsigned int hdspm_aes32_sample_rates[] = {
5943 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000
5944};
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005945
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005946static struct snd_pcm_hw_constraint_list
5947hdspm_hw_constraints_aes32_sample_rates = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005948 .count = ARRAY_SIZE(hdspm_aes32_sample_rates),
5949 .list = hdspm_aes32_sample_rates,
5950 .mask = 0
5951};
5952
Takashi Iwai98274f02005-11-17 14:52:34 +01005953static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005954{
Takashi Iwai98274f02005-11-17 14:52:34 +01005955 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5956 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02005957
Takashi Iwai763f3562005-06-03 11:25:34 +02005958 spin_lock_irq(&hdspm->lock);
5959
5960 snd_pcm_set_sync(substream);
5961
Adrian Knoth0dca1792011-01-26 19:32:14 +01005962
Takashi Iwai763f3562005-06-03 11:25:34 +02005963 runtime->hw = snd_hdspm_playback_subinfo;
5964
5965 if (hdspm->capture_substream == NULL)
5966 hdspm_stop_audio(hdspm);
5967
5968 hdspm->playback_pid = current->pid;
5969 hdspm->playback_substream = substream;
5970
5971 spin_unlock_irq(&hdspm->lock);
5972
5973 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
5974
Adrian Knoth0dca1792011-01-26 19:32:14 +01005975 switch (hdspm->io_type) {
5976 case AIO:
5977 case RayDAT:
5978 snd_pcm_hw_constraint_list(runtime, 0,
5979 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5980 &hw_constraints_period_sizes_new);
5981 snd_pcm_hw_constraint_list(runtime, 0,
5982 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
5983 &hw_constraints_raydat_io_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005984
Adrian Knoth0dca1792011-01-26 19:32:14 +01005985 break;
5986
5987 default:
5988 snd_pcm_hw_constraint_list(runtime, 0,
5989 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5990 &hw_constraints_period_sizes_old);
5991 }
5992
5993 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005994 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
5995 &hdspm_hw_constraints_aes32_sample_rates);
5996 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005997 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005998 snd_hdspm_hw_rule_rate_out_channels, hdspm,
5999 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006000 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01006001
6002 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
6003 snd_hdspm_hw_rule_out_channels, hdspm,
6004 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
6005
6006 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
6007 snd_hdspm_hw_rule_out_channels_rate, hdspm,
6008 SNDRV_PCM_HW_PARAM_RATE, -1);
6009
Takashi Iwai763f3562005-06-03 11:25:34 +02006010 return 0;
6011}
6012
Takashi Iwai98274f02005-11-17 14:52:34 +01006013static int snd_hdspm_playback_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02006014{
Takashi Iwai98274f02005-11-17 14:52:34 +01006015 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02006016
6017 spin_lock_irq(&hdspm->lock);
6018
6019 hdspm->playback_pid = -1;
6020 hdspm->playback_substream = NULL;
6021
6022 spin_unlock_irq(&hdspm->lock);
6023
6024 return 0;
6025}
6026
6027
Takashi Iwai98274f02005-11-17 14:52:34 +01006028static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02006029{
Takashi Iwai98274f02005-11-17 14:52:34 +01006030 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
6031 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02006032
6033 spin_lock_irq(&hdspm->lock);
6034 snd_pcm_set_sync(substream);
6035 runtime->hw = snd_hdspm_capture_subinfo;
6036
6037 if (hdspm->playback_substream == NULL)
6038 hdspm_stop_audio(hdspm);
6039
6040 hdspm->capture_pid = current->pid;
6041 hdspm->capture_substream = substream;
6042
6043 spin_unlock_irq(&hdspm->lock);
6044
6045 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006046 switch (hdspm->io_type) {
6047 case AIO:
6048 case RayDAT:
6049 snd_pcm_hw_constraint_list(runtime, 0,
6050 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
6051 &hw_constraints_period_sizes_new);
6052 snd_pcm_hw_constraint_list(runtime, 0,
6053 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
6054 &hw_constraints_raydat_io_buffer);
6055 break;
6056
6057 default:
6058 snd_pcm_hw_constraint_list(runtime, 0,
6059 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
6060 &hw_constraints_period_sizes_old);
6061 }
6062
6063 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006064 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
6065 &hdspm_hw_constraints_aes32_sample_rates);
6066 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006067 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth88fabbf2011-02-23 11:43:10 +01006068 snd_hdspm_hw_rule_rate_in_channels, hdspm,
6069 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006070 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01006071
6072 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
6073 snd_hdspm_hw_rule_in_channels, hdspm,
6074 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
6075
6076 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
6077 snd_hdspm_hw_rule_in_channels_rate, hdspm,
6078 SNDRV_PCM_HW_PARAM_RATE, -1);
6079
Takashi Iwai763f3562005-06-03 11:25:34 +02006080 return 0;
6081}
6082
Takashi Iwai98274f02005-11-17 14:52:34 +01006083static int snd_hdspm_capture_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02006084{
Takashi Iwai98274f02005-11-17 14:52:34 +01006085 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02006086
6087 spin_lock_irq(&hdspm->lock);
6088
6089 hdspm->capture_pid = -1;
6090 hdspm->capture_substream = NULL;
6091
6092 spin_unlock_irq(&hdspm->lock);
6093 return 0;
6094}
6095
Adrian Knoth0dca1792011-01-26 19:32:14 +01006096static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
Takashi Iwai763f3562005-06-03 11:25:34 +02006097{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006098 /* we have nothing to initialize but the call is required */
6099 return 0;
6100}
6101
6102static inline int copy_u32_le(void __user *dest, void __iomem *src)
6103{
6104 u32 val = readl(src);
6105 return copy_to_user(dest, &val, 4);
6106}
6107
6108static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
6109 unsigned int cmd, unsigned long __user arg)
6110{
6111 void __user *argp = (void __user *)arg;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006112 struct hdspm *hdspm = hw->private_data;
Takashi Iwai98274f02005-11-17 14:52:34 +01006113 struct hdspm_mixer_ioctl mixer;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006114 struct hdspm_config info;
6115 struct hdspm_status status;
Takashi Iwai98274f02005-11-17 14:52:34 +01006116 struct hdspm_version hdspm_version;
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006117 struct hdspm_peak_rms *levels;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006118 struct hdspm_ltc ltc;
6119 unsigned int statusregister;
6120 long unsigned int s;
6121 int i = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02006122
6123 switch (cmd) {
6124
Takashi Iwai763f3562005-06-03 11:25:34 +02006125 case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006126 levels = &hdspm->peak_rms;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006127 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006128 levels->input_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006129 readl(hdspm->iobase +
6130 HDSPM_MADI_INPUT_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006131 levels->playback_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006132 readl(hdspm->iobase +
6133 HDSPM_MADI_PLAYBACK_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006134 levels->output_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006135 readl(hdspm->iobase +
6136 HDSPM_MADI_OUTPUT_PEAK + i*4);
6137
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006138 levels->input_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006139 ((uint64_t) readl(hdspm->iobase +
6140 HDSPM_MADI_INPUT_RMS_H + i*4) << 32) |
6141 (uint64_t) readl(hdspm->iobase +
6142 HDSPM_MADI_INPUT_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006143 levels->playback_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006144 ((uint64_t)readl(hdspm->iobase +
6145 HDSPM_MADI_PLAYBACK_RMS_H+i*4) << 32) |
6146 (uint64_t)readl(hdspm->iobase +
6147 HDSPM_MADI_PLAYBACK_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006148 levels->output_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006149 ((uint64_t)readl(hdspm->iobase +
6150 HDSPM_MADI_OUTPUT_RMS_H + i*4) << 32) |
6151 (uint64_t)readl(hdspm->iobase +
6152 HDSPM_MADI_OUTPUT_RMS_L + i*4);
6153 }
6154
6155 if (hdspm->system_sample_rate > 96000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006156 levels->speed = qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006157 } else if (hdspm->system_sample_rate > 48000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006158 levels->speed = ds;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006159 } else {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006160 levels->speed = ss;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006161 }
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006162 levels->status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006163
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006164 s = copy_to_user(argp, levels, sizeof(struct hdspm_peak_rms));
Adrian Knoth0dca1792011-01-26 19:32:14 +01006165 if (0 != s) {
6166 /* snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu
6167 [Levels]\n", sizeof(struct hdspm_peak_rms), s);
6168 */
Takashi Iwai763f3562005-06-03 11:25:34 +02006169 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006170 }
6171 break;
6172
6173 case SNDRV_HDSPM_IOCTL_GET_LTC:
6174 ltc.ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
6175 i = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
6176 if (i & HDSPM_TCO1_LTC_Input_valid) {
6177 switch (i & (HDSPM_TCO1_LTC_Format_LSB |
6178 HDSPM_TCO1_LTC_Format_MSB)) {
6179 case 0:
6180 ltc.format = fps_24;
6181 break;
6182 case HDSPM_TCO1_LTC_Format_LSB:
6183 ltc.format = fps_25;
6184 break;
6185 case HDSPM_TCO1_LTC_Format_MSB:
6186 ltc.format = fps_2997;
6187 break;
6188 default:
6189 ltc.format = 30;
6190 break;
6191 }
6192 if (i & HDSPM_TCO1_set_drop_frame_flag) {
6193 ltc.frame = drop_frame;
6194 } else {
6195 ltc.frame = full_frame;
6196 }
6197 } else {
6198 ltc.format = format_invalid;
6199 ltc.frame = frame_invalid;
6200 }
6201 if (i & HDSPM_TCO1_Video_Input_Format_NTSC) {
6202 ltc.input_format = ntsc;
6203 } else if (i & HDSPM_TCO1_Video_Input_Format_PAL) {
6204 ltc.input_format = pal;
6205 } else {
6206 ltc.input_format = no_video;
6207 }
6208
6209 s = copy_to_user(argp, &ltc, sizeof(struct hdspm_ltc));
6210 if (0 != s) {
6211 /*
6212 snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */
Takashi Iwai763f3562005-06-03 11:25:34 +02006213 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006214 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006215
6216 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02006217
Adrian Knoth0dca1792011-01-26 19:32:14 +01006218 case SNDRV_HDSPM_IOCTL_GET_CONFIG:
Takashi Iwai763f3562005-06-03 11:25:34 +02006219
Adrian Knoth4ab69a22011-02-23 11:43:14 +01006220 memset(&info, 0, sizeof(info));
Takashi Iwai763f3562005-06-03 11:25:34 +02006221 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006222 info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
6223 info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006224
6225 info.system_sample_rate = hdspm->system_sample_rate;
6226 info.autosync_sample_rate =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006227 hdspm_external_sample_rate(hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006228 info.system_clock_mode = hdspm_system_clock_mode(hdspm);
6229 info.clock_source = hdspm_clock_source(hdspm);
6230 info.autosync_ref = hdspm_autosync_ref(hdspm);
6231 info.line_out = hdspm_line_out(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006232 info.passthru = 0;
6233 spin_unlock_irq(&hdspm->lock);
6234 if (copy_to_user((void __user *) arg, &info, sizeof(info)))
6235 return -EFAULT;
6236 break;
6237
Adrian Knoth0dca1792011-01-26 19:32:14 +01006238 case SNDRV_HDSPM_IOCTL_GET_STATUS:
6239 status.card_type = hdspm->io_type;
6240
6241 status.autosync_source = hdspm_autosync_ref(hdspm);
6242
6243 status.card_clock = 110069313433624ULL;
6244 status.master_period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
6245
6246 switch (hdspm->io_type) {
6247 case MADI:
6248 case MADIface:
6249 status.card_specific.madi.sync_wc =
6250 hdspm_wc_sync_check(hdspm);
6251 status.card_specific.madi.sync_madi =
6252 hdspm_madi_sync_check(hdspm);
6253 status.card_specific.madi.sync_tco =
6254 hdspm_tco_sync_check(hdspm);
6255 status.card_specific.madi.sync_in =
6256 hdspm_sync_in_sync_check(hdspm);
6257
6258 statusregister =
6259 hdspm_read(hdspm, HDSPM_statusRegister);
6260 status.card_specific.madi.madi_input =
6261 (statusregister & HDSPM_AB_int) ? 1 : 0;
6262 status.card_specific.madi.channel_format =
6263 (statusregister & HDSPM_TX_64ch) ? 1 : 0;
6264 /* TODO: Mac driver sets it when f_s>48kHz */
6265 status.card_specific.madi.frame_format = 0;
6266
6267 default:
6268 break;
6269 }
6270
6271 if (copy_to_user((void __user *) arg, &status, sizeof(status)))
6272 return -EFAULT;
6273
6274
6275 break;
6276
Takashi Iwai763f3562005-06-03 11:25:34 +02006277 case SNDRV_HDSPM_IOCTL_GET_VERSION:
Adrian Knoth0dca1792011-01-26 19:32:14 +01006278 hdspm_version.card_type = hdspm->io_type;
6279 strncpy(hdspm_version.cardname, hdspm->card_name,
6280 sizeof(hdspm_version.cardname));
6281 hdspm_version.serial = (hdspm_read(hdspm,
6282 HDSPM_midiStatusIn0)>>8) & 0xFFFFFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02006283 hdspm_version.firmware_rev = hdspm->firmware_rev;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006284 hdspm_version.addons = 0;
6285 if (hdspm->tco)
6286 hdspm_version.addons |= HDSPM_ADDON_TCO;
6287
Takashi Iwai763f3562005-06-03 11:25:34 +02006288 if (copy_to_user((void __user *) arg, &hdspm_version,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006289 sizeof(hdspm_version)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006290 return -EFAULT;
6291 break;
6292
6293 case SNDRV_HDSPM_IOCTL_GET_MIXER:
6294 if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer)))
6295 return -EFAULT;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006296 if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006297 sizeof(struct hdspm_mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006298 return -EFAULT;
6299 break;
6300
6301 default:
6302 return -EINVAL;
6303 }
6304 return 0;
6305}
6306
Takashi Iwai98274f02005-11-17 14:52:34 +01006307static struct snd_pcm_ops snd_hdspm_playback_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006308 .open = snd_hdspm_playback_open,
6309 .close = snd_hdspm_playback_release,
6310 .ioctl = snd_hdspm_ioctl,
6311 .hw_params = snd_hdspm_hw_params,
6312 .hw_free = snd_hdspm_hw_free,
6313 .prepare = snd_hdspm_prepare,
6314 .trigger = snd_hdspm_trigger,
6315 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006316 .page = snd_pcm_sgbuf_ops_page,
6317};
6318
Takashi Iwai98274f02005-11-17 14:52:34 +01006319static struct snd_pcm_ops snd_hdspm_capture_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006320 .open = snd_hdspm_capture_open,
6321 .close = snd_hdspm_capture_release,
6322 .ioctl = snd_hdspm_ioctl,
6323 .hw_params = snd_hdspm_hw_params,
6324 .hw_free = snd_hdspm_hw_free,
6325 .prepare = snd_hdspm_prepare,
6326 .trigger = snd_hdspm_trigger,
6327 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006328 .page = snd_pcm_sgbuf_ops_page,
6329};
6330
Takashi Iwai98274f02005-11-17 14:52:34 +01006331static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
6332 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006333{
Takashi Iwai98274f02005-11-17 14:52:34 +01006334 struct snd_hwdep *hw;
Takashi Iwai763f3562005-06-03 11:25:34 +02006335 int err;
6336
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006337 err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw);
6338 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006339 return err;
6340
6341 hdspm->hwdep = hw;
6342 hw->private_data = hdspm;
6343 strcpy(hw->name, "HDSPM hwdep interface");
6344
Adrian Knoth0dca1792011-01-26 19:32:14 +01006345 hw->ops.open = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006346 hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006347 hw->ops.release = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006348
6349 return 0;
6350}
6351
6352
6353/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01006354 memory interface
Takashi Iwai763f3562005-06-03 11:25:34 +02006355 ------------------------------------------------------------*/
Adrian Knoth0dca1792011-01-26 19:32:14 +01006356static int __devinit snd_hdspm_preallocate_memory(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006357{
6358 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01006359 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006360 size_t wanted;
6361
6362 pcm = hdspm->pcm;
6363
Remy Bruno3cee5a62006-10-16 12:46:32 +02006364 wanted = HDSPM_DMA_AREA_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02006365
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006366 err =
Takashi Iwai763f3562005-06-03 11:25:34 +02006367 snd_pcm_lib_preallocate_pages_for_all(pcm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006368 SNDRV_DMA_TYPE_DEV_SG,
Takashi Iwai763f3562005-06-03 11:25:34 +02006369 snd_dma_pci_data(hdspm->pci),
6370 wanted,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006371 wanted);
6372 if (err < 0) {
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006373 snd_printdd("Could not preallocate %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006374
6375 return err;
6376 } else
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006377 snd_printdd(" Preallocated %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006378
6379 return 0;
6380}
6381
Adrian Knoth0dca1792011-01-26 19:32:14 +01006382
6383static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +02006384 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02006385 unsigned int reg, int channels)
6386{
6387 int i;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006388
6389 /* continuous memory segment */
Takashi Iwai763f3562005-06-03 11:25:34 +02006390 for (i = 0; i < (channels * 16); i++)
6391 hdspm_write(hdspm, reg + 4 * i,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006392 snd_pcm_sgbuf_get_addr(substream, 4096 * i));
Takashi Iwai763f3562005-06-03 11:25:34 +02006393}
6394
Adrian Knoth0dca1792011-01-26 19:32:14 +01006395
Takashi Iwai763f3562005-06-03 11:25:34 +02006396/* ------------- ALSA Devices ---------------------------- */
Takashi Iwai98274f02005-11-17 14:52:34 +01006397static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006398 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006399{
Takashi Iwai98274f02005-11-17 14:52:34 +01006400 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006401 int err;
6402
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006403 err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm);
6404 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006405 return err;
6406
6407 hdspm->pcm = pcm;
6408 pcm->private_data = hdspm;
6409 strcpy(pcm->name, hdspm->card_name);
6410
6411 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
6412 &snd_hdspm_playback_ops);
6413 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
6414 &snd_hdspm_capture_ops);
6415
6416 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
6417
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006418 err = snd_hdspm_preallocate_memory(hdspm);
6419 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006420 return err;
6421
6422 return 0;
6423}
6424
Takashi Iwai98274f02005-11-17 14:52:34 +01006425static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006426{
Adrian Knoth7c7102b2011-02-28 15:14:50 +01006427 int i;
6428
6429 for (i = 0; i < hdspm->midiPorts; i++)
6430 snd_hdspm_flush_midi_input(hdspm, i);
Takashi Iwai763f3562005-06-03 11:25:34 +02006431}
6432
Takashi Iwai98274f02005-11-17 14:52:34 +01006433static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
6434 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006435{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006436 int err, i;
Takashi Iwai763f3562005-06-03 11:25:34 +02006437
6438 snd_printdd("Create card...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006439 err = snd_hdspm_create_pcm(card, hdspm);
6440 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006441 return err;
6442
Adrian Knoth0dca1792011-01-26 19:32:14 +01006443 i = 0;
6444 while (i < hdspm->midiPorts) {
6445 err = snd_hdspm_create_midi(card, hdspm, i);
6446 if (err < 0) {
6447 return err;
6448 }
6449 i++;
6450 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006451
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006452 err = snd_hdspm_create_controls(card, hdspm);
6453 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006454 return err;
6455
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006456 err = snd_hdspm_create_hwdep(card, hdspm);
6457 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006458 return err;
6459
6460 snd_printdd("proc init...\n");
6461 snd_hdspm_proc_init(hdspm);
6462
6463 hdspm->system_sample_rate = -1;
6464 hdspm->last_external_sample_rate = -1;
6465 hdspm->last_internal_sample_rate = -1;
6466 hdspm->playback_pid = -1;
6467 hdspm->capture_pid = -1;
6468 hdspm->capture_substream = NULL;
6469 hdspm->playback_substream = NULL;
6470
6471 snd_printdd("Set defaults...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006472 err = snd_hdspm_set_defaults(hdspm);
6473 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006474 return err;
6475
6476 snd_printdd("Update mixer controls...\n");
6477 hdspm_update_simple_mixer_controls(hdspm);
6478
6479 snd_printdd("Initializeing complete ???\n");
6480
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006481 err = snd_card_register(card);
6482 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006483 snd_printk(KERN_ERR "HDSPM: error registering card\n");
6484 return err;
6485 }
6486
6487 snd_printdd("... yes now\n");
6488
6489 return 0;
6490}
6491
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006492static int __devinit snd_hdspm_create(struct snd_card *card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006493 struct hdspm *hdspm) {
6494
Takashi Iwai763f3562005-06-03 11:25:34 +02006495 struct pci_dev *pci = hdspm->pci;
6496 int err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006497 unsigned long io_extent;
6498
6499 hdspm->irq = -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02006500 hdspm->card = card;
6501
6502 spin_lock_init(&hdspm->lock);
6503
Takashi Iwai763f3562005-06-03 11:25:34 +02006504 pci_read_config_word(hdspm->pci,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006505 PCI_CLASS_REVISION, &hdspm->firmware_rev);
Remy Bruno3cee5a62006-10-16 12:46:32 +02006506
Takashi Iwai763f3562005-06-03 11:25:34 +02006507 strcpy(card->mixername, "Xilinx FPGA");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006508 strcpy(card->driver, "HDSPM");
6509
6510 switch (hdspm->firmware_rev) {
6511 case HDSPM_MADI_REV:
Adrian Knothefef0542011-06-12 17:26:19 +02006512 case HDSPM_MADI_OLD_REV:
Adrian Knoth5f8b4d52011-07-29 03:11:04 +02006513 case HDSPM_MADI_ANCIENT_REV:
Adrian Knoth0dca1792011-01-26 19:32:14 +01006514 hdspm->io_type = MADI;
6515 hdspm->card_name = "RME MADI";
6516 hdspm->midiPorts = 3;
6517 break;
6518 case HDSPM_RAYDAT_REV:
6519 hdspm->io_type = RayDAT;
6520 hdspm->card_name = "RME RayDAT";
6521 hdspm->midiPorts = 2;
6522 break;
6523 case HDSPM_AIO_REV:
6524 hdspm->io_type = AIO;
6525 hdspm->card_name = "RME AIO";
6526 hdspm->midiPorts = 1;
6527 break;
6528 case HDSPM_MADIFACE_REV:
6529 hdspm->io_type = MADIface;
6530 hdspm->card_name = "RME MADIface";
6531 hdspm->midiPorts = 1;
6532 break;
6533 case HDSPM_AES_REV:
Adrian Knoth526ea862011-02-28 15:14:48 +01006534 case HDSPM_AES32_REV:
Adrian Knothbdd32552011-03-07 19:10:11 +01006535 case HDSPM_AES32_OLD_REV:
Adrian Knoth0dca1792011-01-26 19:32:14 +01006536 hdspm->io_type = AES32;
6537 hdspm->card_name = "RME AES32";
6538 hdspm->midiPorts = 2;
6539 break;
Adrian Knoth5027f342011-02-28 15:14:49 +01006540 default:
6541 snd_printk(KERN_ERR "HDSPM: unknown firmware revision %x\n",
6542 hdspm->firmware_rev);
6543 return -ENODEV;
Remy Bruno3cee5a62006-10-16 12:46:32 +02006544 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006545
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006546 err = pci_enable_device(pci);
6547 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006548 return err;
6549
6550 pci_set_master(hdspm->pci);
6551
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006552 err = pci_request_regions(pci, "hdspm");
6553 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006554 return err;
6555
6556 hdspm->port = pci_resource_start(pci, 0);
6557 io_extent = pci_resource_len(pci, 0);
6558
6559 snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006560 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006561
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006562 hdspm->iobase = ioremap_nocache(hdspm->port, io_extent);
6563 if (!hdspm->iobase) {
6564 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006565 "unable to remap region 0x%lx-0x%lx\n",
6566 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006567 return -EBUSY;
6568 }
6569 snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006570 (unsigned long)hdspm->iobase, hdspm->port,
6571 hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006572
6573 if (request_irq(pci->irq, snd_hdspm_interrupt,
Takashi Iwai934c2b62011-06-10 16:36:37 +02006574 IRQF_SHARED, KBUILD_MODNAME, hdspm)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006575 snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
6576 return -EBUSY;
6577 }
6578
6579 snd_printdd("use IRQ %d\n", pci->irq);
6580
6581 hdspm->irq = pci->irq;
Takashi Iwai763f3562005-06-03 11:25:34 +02006582
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006583 snd_printdd("kmalloc Mixer memory of %zd Bytes\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006584 sizeof(struct hdspm_mixer));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006585 hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL);
6586 if (!hdspm->mixer) {
6587 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006588 "unable to kmalloc Mixer memory of %d Bytes\n",
6589 (int)sizeof(struct hdspm_mixer));
Takashi Iwai763f3562005-06-03 11:25:34 +02006590 return err;
6591 }
6592
Adrian Knoth0dca1792011-01-26 19:32:14 +01006593 hdspm->port_names_in = NULL;
6594 hdspm->port_names_out = NULL;
6595
6596 switch (hdspm->io_type) {
6597 case AES32:
Adrian Knothd2d10a22011-02-28 15:14:47 +01006598 hdspm->ss_in_channels = hdspm->ss_out_channels = AES32_CHANNELS;
6599 hdspm->ds_in_channels = hdspm->ds_out_channels = AES32_CHANNELS;
6600 hdspm->qs_in_channels = hdspm->qs_out_channels = AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006601
6602 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6603 channel_map_aes32;
6604 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6605 channel_map_aes32;
6606 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6607 channel_map_aes32;
6608 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6609 texts_ports_aes32;
6610 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6611 texts_ports_aes32;
6612 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6613 texts_ports_aes32;
6614
Adrian Knothd2d10a22011-02-28 15:14:47 +01006615 hdspm->max_channels_out = hdspm->max_channels_in =
6616 AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006617 hdspm->port_names_in = hdspm->port_names_out =
6618 texts_ports_aes32;
6619 hdspm->channel_map_in = hdspm->channel_map_out =
6620 channel_map_aes32;
6621
Adrian Knoth0dca1792011-01-26 19:32:14 +01006622 break;
6623
6624 case MADI:
6625 case MADIface:
6626 hdspm->ss_in_channels = hdspm->ss_out_channels =
6627 MADI_SS_CHANNELS;
6628 hdspm->ds_in_channels = hdspm->ds_out_channels =
6629 MADI_DS_CHANNELS;
6630 hdspm->qs_in_channels = hdspm->qs_out_channels =
6631 MADI_QS_CHANNELS;
6632
6633 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6634 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006635 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006636 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006637 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006638 channel_map_unity_ss;
6639
6640 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6641 texts_ports_madi;
6642 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6643 texts_ports_madi;
6644 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6645 texts_ports_madi;
6646 break;
6647
6648 case AIO:
6649 if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) {
6650 snd_printk(KERN_INFO "HDSPM: AEB input board found, but not supported\n");
6651 }
6652
6653 hdspm->ss_in_channels = AIO_IN_SS_CHANNELS;
6654 hdspm->ds_in_channels = AIO_IN_DS_CHANNELS;
6655 hdspm->qs_in_channels = AIO_IN_QS_CHANNELS;
6656 hdspm->ss_out_channels = AIO_OUT_SS_CHANNELS;
6657 hdspm->ds_out_channels = AIO_OUT_DS_CHANNELS;
6658 hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS;
6659
6660 hdspm->channel_map_out_ss = channel_map_aio_out_ss;
6661 hdspm->channel_map_out_ds = channel_map_aio_out_ds;
6662 hdspm->channel_map_out_qs = channel_map_aio_out_qs;
6663
6664 hdspm->channel_map_in_ss = channel_map_aio_in_ss;
6665 hdspm->channel_map_in_ds = channel_map_aio_in_ds;
6666 hdspm->channel_map_in_qs = channel_map_aio_in_qs;
6667
6668 hdspm->port_names_in_ss = texts_ports_aio_in_ss;
6669 hdspm->port_names_out_ss = texts_ports_aio_out_ss;
6670 hdspm->port_names_in_ds = texts_ports_aio_in_ds;
6671 hdspm->port_names_out_ds = texts_ports_aio_out_ds;
6672 hdspm->port_names_in_qs = texts_ports_aio_in_qs;
6673 hdspm->port_names_out_qs = texts_ports_aio_out_qs;
6674
6675 break;
6676
6677 case RayDAT:
6678 hdspm->ss_in_channels = hdspm->ss_out_channels =
6679 RAYDAT_SS_CHANNELS;
6680 hdspm->ds_in_channels = hdspm->ds_out_channels =
6681 RAYDAT_DS_CHANNELS;
6682 hdspm->qs_in_channels = hdspm->qs_out_channels =
6683 RAYDAT_QS_CHANNELS;
6684
6685 hdspm->max_channels_in = RAYDAT_SS_CHANNELS;
6686 hdspm->max_channels_out = RAYDAT_SS_CHANNELS;
6687
6688 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6689 channel_map_raydat_ss;
6690 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6691 channel_map_raydat_ds;
6692 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6693 channel_map_raydat_qs;
6694 hdspm->channel_map_in = hdspm->channel_map_out =
6695 channel_map_raydat_ss;
6696
6697 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6698 texts_ports_raydat_ss;
6699 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6700 texts_ports_raydat_ds;
6701 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6702 texts_ports_raydat_qs;
6703
6704
6705 break;
6706
6707 }
6708
6709 /* TCO detection */
6710 switch (hdspm->io_type) {
6711 case AIO:
6712 case RayDAT:
6713 if (hdspm_read(hdspm, HDSPM_statusRegister2) &
6714 HDSPM_s2_tco_detect) {
6715 hdspm->midiPorts++;
6716 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6717 GFP_KERNEL);
6718 if (NULL != hdspm->tco) {
6719 hdspm_tco_write(hdspm);
6720 }
6721 snd_printk(KERN_INFO "HDSPM: AIO/RayDAT TCO module found\n");
6722 } else {
6723 hdspm->tco = NULL;
6724 }
6725 break;
6726
6727 case MADI:
6728 if (hdspm_read(hdspm, HDSPM_statusRegister) & HDSPM_tco_detect) {
6729 hdspm->midiPorts++;
6730 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6731 GFP_KERNEL);
6732 if (NULL != hdspm->tco) {
6733 hdspm_tco_write(hdspm);
6734 }
6735 snd_printk(KERN_INFO "HDSPM: MADI TCO module found\n");
6736 } else {
6737 hdspm->tco = NULL;
6738 }
6739 break;
6740
6741 default:
6742 hdspm->tco = NULL;
6743 }
6744
6745 /* texts */
6746 switch (hdspm->io_type) {
6747 case AES32:
6748 if (hdspm->tco) {
6749 hdspm->texts_autosync = texts_autosync_aes_tco;
6750 hdspm->texts_autosync_items = 10;
6751 } else {
6752 hdspm->texts_autosync = texts_autosync_aes;
6753 hdspm->texts_autosync_items = 9;
6754 }
6755 break;
6756
6757 case MADI:
6758 if (hdspm->tco) {
6759 hdspm->texts_autosync = texts_autosync_madi_tco;
6760 hdspm->texts_autosync_items = 4;
6761 } else {
6762 hdspm->texts_autosync = texts_autosync_madi;
6763 hdspm->texts_autosync_items = 3;
6764 }
6765 break;
6766
6767 case MADIface:
6768
6769 break;
6770
6771 case RayDAT:
6772 if (hdspm->tco) {
6773 hdspm->texts_autosync = texts_autosync_raydat_tco;
6774 hdspm->texts_autosync_items = 9;
6775 } else {
6776 hdspm->texts_autosync = texts_autosync_raydat;
6777 hdspm->texts_autosync_items = 8;
6778 }
6779 break;
6780
6781 case AIO:
6782 if (hdspm->tco) {
6783 hdspm->texts_autosync = texts_autosync_aio_tco;
6784 hdspm->texts_autosync_items = 6;
6785 } else {
6786 hdspm->texts_autosync = texts_autosync_aio;
6787 hdspm->texts_autosync_items = 5;
6788 }
6789 break;
6790
6791 }
6792
6793 tasklet_init(&hdspm->midi_tasklet,
6794 hdspm_midi_tasklet, (unsigned long) hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006795
6796 snd_printdd("create alsa devices.\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006797 err = snd_hdspm_create_alsa_devices(card, hdspm);
6798 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006799 return err;
6800
6801 snd_hdspm_initialize_midi_flush(hdspm);
6802
6803 return 0;
6804}
6805
Adrian Knoth0dca1792011-01-26 19:32:14 +01006806
Takashi Iwai98274f02005-11-17 14:52:34 +01006807static int snd_hdspm_free(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006808{
6809
6810 if (hdspm->port) {
6811
6812 /* stop th audio, and cancel all interrupts */
6813 hdspm->control_register &=
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006814 ~(HDSPM_Start | HDSPM_AudioInterruptEnable |
Adrian Knoth0dca1792011-01-26 19:32:14 +01006815 HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable |
6816 HDSPM_Midi2InterruptEnable | HDSPM_Midi3InterruptEnable);
Takashi Iwai763f3562005-06-03 11:25:34 +02006817 hdspm_write(hdspm, HDSPM_controlRegister,
6818 hdspm->control_register);
6819 }
6820
6821 if (hdspm->irq >= 0)
6822 free_irq(hdspm->irq, (void *) hdspm);
6823
Jesper Juhlfc584222005-10-24 15:11:28 +02006824 kfree(hdspm->mixer);
Takashi Iwai763f3562005-06-03 11:25:34 +02006825
6826 if (hdspm->iobase)
6827 iounmap(hdspm->iobase);
6828
Takashi Iwai763f3562005-06-03 11:25:34 +02006829 if (hdspm->port)
6830 pci_release_regions(hdspm->pci);
6831
6832 pci_disable_device(hdspm->pci);
6833 return 0;
6834}
6835
Adrian Knoth0dca1792011-01-26 19:32:14 +01006836
Takashi Iwai98274f02005-11-17 14:52:34 +01006837static void snd_hdspm_card_free(struct snd_card *card)
Takashi Iwai763f3562005-06-03 11:25:34 +02006838{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006839 struct hdspm *hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006840
6841 if (hdspm)
6842 snd_hdspm_free(hdspm);
6843}
6844
Adrian Knoth0dca1792011-01-26 19:32:14 +01006845
Takashi Iwai763f3562005-06-03 11:25:34 +02006846static int __devinit snd_hdspm_probe(struct pci_dev *pci,
6847 const struct pci_device_id *pci_id)
6848{
6849 static int dev;
Takashi Iwai98274f02005-11-17 14:52:34 +01006850 struct hdspm *hdspm;
6851 struct snd_card *card;
Takashi Iwai763f3562005-06-03 11:25:34 +02006852 int err;
6853
6854 if (dev >= SNDRV_CARDS)
6855 return -ENODEV;
6856 if (!enable[dev]) {
6857 dev++;
6858 return -ENOENT;
6859 }
6860
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006861 err = snd_card_create(index[dev], id[dev],
Adrian Knoth0dca1792011-01-26 19:32:14 +01006862 THIS_MODULE, sizeof(struct hdspm), &card);
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006863 if (err < 0)
6864 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006865
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006866 hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006867 card->private_free = snd_hdspm_card_free;
6868 hdspm->dev = dev;
6869 hdspm->pci = pci;
6870
Takashi Iwaic187c042007-02-19 15:27:33 +01006871 snd_card_set_dev(card, &pci->dev);
6872
Adrian Knoth0dca1792011-01-26 19:32:14 +01006873 err = snd_hdspm_create(card, hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006874 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006875 snd_card_free(card);
6876 return err;
6877 }
6878
Adrian Knoth0dca1792011-01-26 19:32:14 +01006879 if (hdspm->io_type != MADIface) {
6880 sprintf(card->shortname, "%s_%x",
6881 hdspm->card_name,
6882 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF);
6883 sprintf(card->longname, "%s S/N 0x%x at 0x%lx, irq %d",
6884 hdspm->card_name,
6885 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF,
6886 hdspm->port, hdspm->irq);
6887 } else {
6888 sprintf(card->shortname, "%s", hdspm->card_name);
6889 sprintf(card->longname, "%s at 0x%lx, irq %d",
6890 hdspm->card_name, hdspm->port, hdspm->irq);
6891 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006892
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006893 err = snd_card_register(card);
6894 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006895 snd_card_free(card);
6896 return err;
6897 }
6898
6899 pci_set_drvdata(pci, card);
6900
6901 dev++;
6902 return 0;
6903}
6904
6905static void __devexit snd_hdspm_remove(struct pci_dev *pci)
6906{
6907 snd_card_free(pci_get_drvdata(pci));
6908 pci_set_drvdata(pci, NULL);
6909}
6910
6911static struct pci_driver driver = {
Takashi Iwai3733e422011-06-10 16:20:20 +02006912 .name = KBUILD_MODNAME,
Takashi Iwai763f3562005-06-03 11:25:34 +02006913 .id_table = snd_hdspm_ids,
6914 .probe = snd_hdspm_probe,
6915 .remove = __devexit_p(snd_hdspm_remove),
6916};
6917
6918
6919static int __init alsa_card_hdspm_init(void)
6920{
6921 return pci_register_driver(&driver);
6922}
6923
6924static void __exit alsa_card_hdspm_exit(void)
6925{
6926 pci_unregister_driver(&driver);
6927}
6928
6929module_init(alsa_card_hdspm_init)
6930module_exit(alsa_card_hdspm_exit)