blob: 60a0b7de8e572dcf59500c7bd1e03276d903ed9c [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
Adrian Knoth2e610272011-08-15 00:22:54 +02001326 if (32 == frames) {
1327 /* Special case for new RME cards like RayDAT/AIO which
1328 * support period sizes of 32 samples. Since latency is
1329 * encoded in the three bits of HDSP_LatencyMask, we can only
1330 * have values from 0 .. 7. While 0 still means 64 samples and
1331 * 6 represents 4096 samples on all cards, 7 represents 8192
1332 * on older cards and 32 samples on new cards.
1333 *
1334 * In other words, period size in samples is calculated by
1335 * 2^(n+6) with n ranging from 0 .. 7.
1336 */
1337 n = 7;
1338 } else {
1339 frames >>= 7;
1340 n = 0;
1341 while (frames) {
1342 n++;
1343 frames >>= 1;
1344 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001345 }
Adrian Knoth2e610272011-08-15 00:22:54 +02001346
Takashi Iwai763f3562005-06-03 11:25:34 +02001347 s->control_register &= ~HDSPM_LatencyMask;
1348 s->control_register |= hdspm_encode_latency(n);
1349
1350 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1351
1352 hdspm_compute_period_size(s);
1353
1354 spin_unlock_irq(&s->lock);
1355
1356 return 0;
1357}
1358
Adrian Knoth0dca1792011-01-26 19:32:14 +01001359static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period)
1360{
1361 u64 freq_const;
1362
1363 if (period == 0)
1364 return 0;
1365
1366 switch (hdspm->io_type) {
1367 case MADI:
1368 case AES32:
1369 freq_const = 110069313433624ULL;
1370 break;
1371 case RayDAT:
1372 case AIO:
1373 freq_const = 104857600000000ULL;
1374 break;
1375 case MADIface:
1376 freq_const = 131072000000000ULL;
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001377 break;
1378 default:
1379 snd_BUG();
1380 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001381 }
1382
1383 return div_u64(freq_const, period);
1384}
1385
1386
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001387static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
1388{
1389 u64 n;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001390
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001391 if (rate >= 112000)
1392 rate /= 4;
1393 else if (rate >= 56000)
1394 rate /= 2;
1395
Adrian Knoth0dca1792011-01-26 19:32:14 +01001396 switch (hdspm->io_type) {
1397 case MADIface:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001398 n = 131072000000000ULL; /* 125 MHz */
1399 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001400 case MADI:
1401 case AES32:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001402 n = 110069313433624ULL; /* 105 MHz */
1403 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001404 case RayDAT:
1405 case AIO:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001406 n = 104857600000000ULL; /* 100 MHz */
1407 break;
1408 default:
1409 snd_BUG();
1410 return;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001411 }
1412
Takashi Iwai3f7440a2009-06-05 17:40:04 +02001413 n = div_u64(n, rate);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001414 /* n should be less than 2^32 for being written to FREQ register */
Takashi Iwaida3cec32008-08-08 17:12:14 +02001415 snd_BUG_ON(n >> 32);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001416 hdspm_write(hdspm, HDSPM_freqReg, (u32)n);
1417}
Takashi Iwai763f3562005-06-03 11:25:34 +02001418
1419/* dummy set rate lets see what happens */
Takashi Iwai98274f02005-11-17 14:52:34 +01001420static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
Takashi Iwai763f3562005-06-03 11:25:34 +02001421{
Takashi Iwai763f3562005-06-03 11:25:34 +02001422 int current_rate;
1423 int rate_bits;
1424 int not_set = 0;
Remy Bruno65345992007-08-31 12:21:08 +02001425 int current_speed, target_speed;
Takashi Iwai763f3562005-06-03 11:25:34 +02001426
1427 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
1428 it (e.g. during module initialization).
1429 */
1430
1431 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
1432
Adrian Knoth0dca1792011-01-26 19:32:14 +01001433 /* SLAVE --- */
Takashi Iwai763f3562005-06-03 11:25:34 +02001434 if (called_internally) {
1435
Adrian Knoth0dca1792011-01-26 19:32:14 +01001436 /* request from ctl or card initialization
1437 just make a warning an remember setting
1438 for future master mode switching */
1439
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001440 snd_printk(KERN_WARNING "HDSPM: "
1441 "Warning: device is not running "
1442 "as a clock master.\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001443 not_set = 1;
1444 } else {
1445
1446 /* hw_param request while in AutoSync mode */
1447 int external_freq =
1448 hdspm_external_sample_rate(hdspm);
1449
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001450 if (hdspm_autosync_ref(hdspm) ==
1451 HDSPM_AUTOSYNC_FROM_NONE) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001452
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001453 snd_printk(KERN_WARNING "HDSPM: "
1454 "Detected no Externel Sync \n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001455 not_set = 1;
1456
1457 } else if (rate != external_freq) {
1458
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001459 snd_printk(KERN_WARNING "HDSPM: "
1460 "Warning: No AutoSync source for "
1461 "requested rate\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001462 not_set = 1;
1463 }
1464 }
1465 }
1466
1467 current_rate = hdspm->system_sample_rate;
1468
1469 /* Changing between Singe, Double and Quad speed is not
1470 allowed if any substreams are open. This is because such a change
1471 causes a shift in the location of the DMA buffers and a reduction
1472 in the number of available buffers.
1473
1474 Note that a similar but essentially insoluble problem exists for
1475 externally-driven rate changes. All we can do is to flag rate
Adrian Knoth0dca1792011-01-26 19:32:14 +01001476 changes in the read/write routines.
Takashi Iwai763f3562005-06-03 11:25:34 +02001477 */
1478
Remy Bruno65345992007-08-31 12:21:08 +02001479 if (current_rate <= 48000)
1480 current_speed = HDSPM_SPEED_SINGLE;
1481 else if (current_rate <= 96000)
1482 current_speed = HDSPM_SPEED_DOUBLE;
1483 else
1484 current_speed = HDSPM_SPEED_QUAD;
1485
1486 if (rate <= 48000)
1487 target_speed = HDSPM_SPEED_SINGLE;
1488 else if (rate <= 96000)
1489 target_speed = HDSPM_SPEED_DOUBLE;
1490 else
1491 target_speed = HDSPM_SPEED_QUAD;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001492
Takashi Iwai763f3562005-06-03 11:25:34 +02001493 switch (rate) {
1494 case 32000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001495 rate_bits = HDSPM_Frequency32KHz;
1496 break;
1497 case 44100:
Takashi Iwai763f3562005-06-03 11:25:34 +02001498 rate_bits = HDSPM_Frequency44_1KHz;
1499 break;
1500 case 48000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001501 rate_bits = HDSPM_Frequency48KHz;
1502 break;
1503 case 64000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001504 rate_bits = HDSPM_Frequency64KHz;
1505 break;
1506 case 88200:
Takashi Iwai763f3562005-06-03 11:25:34 +02001507 rate_bits = HDSPM_Frequency88_2KHz;
1508 break;
1509 case 96000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001510 rate_bits = HDSPM_Frequency96KHz;
1511 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001512 case 128000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001513 rate_bits = HDSPM_Frequency128KHz;
1514 break;
1515 case 176400:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001516 rate_bits = HDSPM_Frequency176_4KHz;
1517 break;
1518 case 192000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001519 rate_bits = HDSPM_Frequency192KHz;
1520 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001521 default:
1522 return -EINVAL;
1523 }
1524
Remy Bruno65345992007-08-31 12:21:08 +02001525 if (current_speed != target_speed
Takashi Iwai763f3562005-06-03 11:25:34 +02001526 && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
1527 snd_printk
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001528 (KERN_ERR "HDSPM: "
Remy Bruno65345992007-08-31 12:21:08 +02001529 "cannot change from %s speed to %s speed mode "
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001530 "(capture PID = %d, playback PID = %d)\n",
Remy Bruno65345992007-08-31 12:21:08 +02001531 hdspm_speed_names[current_speed],
1532 hdspm_speed_names[target_speed],
Takashi Iwai763f3562005-06-03 11:25:34 +02001533 hdspm->capture_pid, hdspm->playback_pid);
1534 return -EBUSY;
1535 }
1536
1537 hdspm->control_register &= ~HDSPM_FrequencyMask;
1538 hdspm->control_register |= rate_bits;
1539 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1540
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001541 /* For AES32, need to set DDS value in FREQ register
1542 For MADI, also apparently */
1543 hdspm_set_dds_value(hdspm, rate);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001544
1545 if (AES32 == hdspm->io_type && rate != current_rate)
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001546 hdspm_write(hdspm, HDSPM_eeprom_wr, 0);
Takashi Iwai763f3562005-06-03 11:25:34 +02001547
1548 hdspm->system_sample_rate = rate;
1549
Adrian Knoth0dca1792011-01-26 19:32:14 +01001550 if (rate <= 48000) {
1551 hdspm->channel_map_in = hdspm->channel_map_in_ss;
1552 hdspm->channel_map_out = hdspm->channel_map_out_ss;
1553 hdspm->max_channels_in = hdspm->ss_in_channels;
1554 hdspm->max_channels_out = hdspm->ss_out_channels;
1555 hdspm->port_names_in = hdspm->port_names_in_ss;
1556 hdspm->port_names_out = hdspm->port_names_out_ss;
1557 } else if (rate <= 96000) {
1558 hdspm->channel_map_in = hdspm->channel_map_in_ds;
1559 hdspm->channel_map_out = hdspm->channel_map_out_ds;
1560 hdspm->max_channels_in = hdspm->ds_in_channels;
1561 hdspm->max_channels_out = hdspm->ds_out_channels;
1562 hdspm->port_names_in = hdspm->port_names_in_ds;
1563 hdspm->port_names_out = hdspm->port_names_out_ds;
1564 } else {
1565 hdspm->channel_map_in = hdspm->channel_map_in_qs;
1566 hdspm->channel_map_out = hdspm->channel_map_out_qs;
1567 hdspm->max_channels_in = hdspm->qs_in_channels;
1568 hdspm->max_channels_out = hdspm->qs_out_channels;
1569 hdspm->port_names_in = hdspm->port_names_in_qs;
1570 hdspm->port_names_out = hdspm->port_names_out_qs;
1571 }
1572
Takashi Iwai763f3562005-06-03 11:25:34 +02001573 if (not_set != 0)
1574 return -1;
1575
1576 return 0;
1577}
1578
1579/* mainly for init to 0 on load */
Takashi Iwai98274f02005-11-17 14:52:34 +01001580static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
Takashi Iwai763f3562005-06-03 11:25:34 +02001581{
1582 int i, j;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001583 unsigned int gain;
1584
1585 if (sgain > UNITY_GAIN)
1586 gain = UNITY_GAIN;
1587 else if (sgain < 0)
1588 gain = 0;
1589 else
1590 gain = sgain;
Takashi Iwai763f3562005-06-03 11:25:34 +02001591
1592 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
1593 for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
1594 hdspm_write_in_gain(hdspm, i, j, gain);
1595 hdspm_write_pb_gain(hdspm, i, j, gain);
1596 }
1597}
1598
1599/*----------------------------------------------------------------------------
1600 MIDI
1601 ----------------------------------------------------------------------------*/
1602
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001603static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm,
1604 int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001605{
1606 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001607 return hdspm_read(hdspm, hdspm->midi[id].dataIn);
Takashi Iwai763f3562005-06-03 11:25:34 +02001608}
1609
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001610static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
1611 int val)
Takashi Iwai763f3562005-06-03 11:25:34 +02001612{
1613 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001614 return hdspm_write(hdspm, hdspm->midi[id].dataOut, val);
Takashi Iwai763f3562005-06-03 11:25:34 +02001615}
1616
Takashi Iwai98274f02005-11-17 14:52:34 +01001617static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001618{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001619 return hdspm_read(hdspm, hdspm->midi[id].statusIn) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001620}
1621
Takashi Iwai98274f02005-11-17 14:52:34 +01001622static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001623{
1624 int fifo_bytes_used;
1625
Adrian Knoth0dca1792011-01-26 19:32:14 +01001626 fifo_bytes_used = hdspm_read(hdspm, hdspm->midi[id].statusOut) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001627
1628 if (fifo_bytes_used < 128)
1629 return 128 - fifo_bytes_used;
1630 else
1631 return 0;
1632}
1633
Denys Vlasenko62cef822008-04-14 13:04:18 +02001634static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001635{
1636 while (snd_hdspm_midi_input_available (hdspm, id))
1637 snd_hdspm_midi_read_byte (hdspm, id);
1638}
1639
Takashi Iwai98274f02005-11-17 14:52:34 +01001640static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001641{
1642 unsigned long flags;
1643 int n_pending;
1644 int to_write;
1645 int i;
1646 unsigned char buf[128];
1647
1648 /* Output is not interrupt driven */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001649
Takashi Iwai763f3562005-06-03 11:25:34 +02001650 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001651 if (hmidi->output &&
1652 !snd_rawmidi_transmit_empty (hmidi->output)) {
1653 n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm,
1654 hmidi->id);
1655 if (n_pending > 0) {
1656 if (n_pending > (int)sizeof (buf))
1657 n_pending = sizeof (buf);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001658
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001659 to_write = snd_rawmidi_transmit (hmidi->output, buf,
1660 n_pending);
1661 if (to_write > 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001662 for (i = 0; i < to_write; ++i)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001663 snd_hdspm_midi_write_byte (hmidi->hdspm,
1664 hmidi->id,
1665 buf[i]);
Takashi Iwai763f3562005-06-03 11:25:34 +02001666 }
1667 }
1668 }
1669 spin_unlock_irqrestore (&hmidi->lock, flags);
1670 return 0;
1671}
1672
Takashi Iwai98274f02005-11-17 14:52:34 +01001673static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001674{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001675 unsigned char buf[128]; /* this buffer is designed to match the MIDI
1676 * input FIFO size
1677 */
Takashi Iwai763f3562005-06-03 11:25:34 +02001678 unsigned long flags;
1679 int n_pending;
1680 int i;
1681
1682 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001683 n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id);
1684 if (n_pending > 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001685 if (hmidi->input) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001686 if (n_pending > (int)sizeof (buf))
Takashi Iwai763f3562005-06-03 11:25:34 +02001687 n_pending = sizeof (buf);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001688 for (i = 0; i < n_pending; ++i)
1689 buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm,
1690 hmidi->id);
1691 if (n_pending)
1692 snd_rawmidi_receive (hmidi->input, buf,
1693 n_pending);
Takashi Iwai763f3562005-06-03 11:25:34 +02001694 } else {
1695 /* flush the MIDI input FIFO */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001696 while (n_pending--)
1697 snd_hdspm_midi_read_byte (hmidi->hdspm,
1698 hmidi->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02001699 }
1700 }
1701 hmidi->pending = 0;
Adrian Knothc0da0012011-06-12 17:26:17 +02001702 spin_unlock_irqrestore(&hmidi->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001703
Adrian Knothc0da0012011-06-12 17:26:17 +02001704 spin_lock_irqsave(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001705 hmidi->hdspm->control_register |= hmidi->ie;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001706 hdspm_write(hmidi->hdspm, HDSPM_controlRegister,
1707 hmidi->hdspm->control_register);
Adrian Knothc0da0012011-06-12 17:26:17 +02001708 spin_unlock_irqrestore(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001709
Takashi Iwai763f3562005-06-03 11:25:34 +02001710 return snd_hdspm_midi_output_write (hmidi);
1711}
1712
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001713static void
1714snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001715{
Takashi Iwai98274f02005-11-17 14:52:34 +01001716 struct hdspm *hdspm;
1717 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001718 unsigned long flags;
Takashi Iwai763f3562005-06-03 11:25:34 +02001719
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001720 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001721 hdspm = hmidi->hdspm;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001722
Takashi Iwai763f3562005-06-03 11:25:34 +02001723 spin_lock_irqsave (&hdspm->lock, flags);
1724 if (up) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001725 if (!(hdspm->control_register & hmidi->ie)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001726 snd_hdspm_flush_midi_input (hdspm, hmidi->id);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001727 hdspm->control_register |= hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001728 }
1729 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001730 hdspm->control_register &= ~hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001731 }
1732
1733 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1734 spin_unlock_irqrestore (&hdspm->lock, flags);
1735}
1736
1737static void snd_hdspm_midi_output_timer(unsigned long data)
1738{
Takashi Iwai98274f02005-11-17 14:52:34 +01001739 struct hdspm_midi *hmidi = (struct hdspm_midi *) data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001740 unsigned long flags;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001741
Takashi Iwai763f3562005-06-03 11:25:34 +02001742 snd_hdspm_midi_output_write(hmidi);
1743 spin_lock_irqsave (&hmidi->lock, flags);
1744
1745 /* this does not bump hmidi->istimer, because the
1746 kernel automatically removed the timer when it
1747 expired, and we are now adding it back, thus
Adrian Knoth0dca1792011-01-26 19:32:14 +01001748 leaving istimer wherever it was set before.
Takashi Iwai763f3562005-06-03 11:25:34 +02001749 */
1750
1751 if (hmidi->istimer) {
1752 hmidi->timer.expires = 1 + jiffies;
1753 add_timer(&hmidi->timer);
1754 }
1755
1756 spin_unlock_irqrestore (&hmidi->lock, flags);
1757}
1758
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001759static void
1760snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001761{
Takashi Iwai98274f02005-11-17 14:52:34 +01001762 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001763 unsigned long flags;
1764
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001765 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001766 spin_lock_irqsave (&hmidi->lock, flags);
1767 if (up) {
1768 if (!hmidi->istimer) {
1769 init_timer(&hmidi->timer);
1770 hmidi->timer.function = snd_hdspm_midi_output_timer;
1771 hmidi->timer.data = (unsigned long) hmidi;
1772 hmidi->timer.expires = 1 + jiffies;
1773 add_timer(&hmidi->timer);
1774 hmidi->istimer++;
1775 }
1776 } else {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001777 if (hmidi->istimer && --hmidi->istimer <= 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02001778 del_timer (&hmidi->timer);
Takashi Iwai763f3562005-06-03 11:25:34 +02001779 }
1780 spin_unlock_irqrestore (&hmidi->lock, flags);
1781 if (up)
1782 snd_hdspm_midi_output_write(hmidi);
1783}
1784
Takashi Iwai98274f02005-11-17 14:52:34 +01001785static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001786{
Takashi Iwai98274f02005-11-17 14:52:34 +01001787 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001788
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001789 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001790 spin_lock_irq (&hmidi->lock);
1791 snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
1792 hmidi->input = substream;
1793 spin_unlock_irq (&hmidi->lock);
1794
1795 return 0;
1796}
1797
Takashi Iwai98274f02005-11-17 14:52:34 +01001798static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001799{
Takashi Iwai98274f02005-11-17 14:52:34 +01001800 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001801
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001802 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001803 spin_lock_irq (&hmidi->lock);
1804 hmidi->output = substream;
1805 spin_unlock_irq (&hmidi->lock);
1806
1807 return 0;
1808}
1809
Takashi Iwai98274f02005-11-17 14:52:34 +01001810static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001811{
Takashi Iwai98274f02005-11-17 14:52:34 +01001812 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001813
1814 snd_hdspm_midi_input_trigger (substream, 0);
1815
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001816 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001817 spin_lock_irq (&hmidi->lock);
1818 hmidi->input = NULL;
1819 spin_unlock_irq (&hmidi->lock);
1820
1821 return 0;
1822}
1823
Takashi Iwai98274f02005-11-17 14:52:34 +01001824static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001825{
Takashi Iwai98274f02005-11-17 14:52:34 +01001826 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001827
1828 snd_hdspm_midi_output_trigger (substream, 0);
1829
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001830 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001831 spin_lock_irq (&hmidi->lock);
1832 hmidi->output = NULL;
1833 spin_unlock_irq (&hmidi->lock);
1834
1835 return 0;
1836}
1837
Takashi Iwai98274f02005-11-17 14:52:34 +01001838static struct snd_rawmidi_ops snd_hdspm_midi_output =
Takashi Iwai763f3562005-06-03 11:25:34 +02001839{
1840 .open = snd_hdspm_midi_output_open,
1841 .close = snd_hdspm_midi_output_close,
1842 .trigger = snd_hdspm_midi_output_trigger,
1843};
1844
Takashi Iwai98274f02005-11-17 14:52:34 +01001845static struct snd_rawmidi_ops snd_hdspm_midi_input =
Takashi Iwai763f3562005-06-03 11:25:34 +02001846{
1847 .open = snd_hdspm_midi_input_open,
1848 .close = snd_hdspm_midi_input_close,
1849 .trigger = snd_hdspm_midi_input_trigger,
1850};
1851
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001852static int __devinit snd_hdspm_create_midi (struct snd_card *card,
1853 struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001854{
1855 int err;
1856 char buf[32];
1857
1858 hdspm->midi[id].id = id;
Takashi Iwai763f3562005-06-03 11:25:34 +02001859 hdspm->midi[id].hdspm = hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +02001860 spin_lock_init (&hdspm->midi[id].lock);
1861
Adrian Knoth0dca1792011-01-26 19:32:14 +01001862 if (0 == id) {
1863 if (MADIface == hdspm->io_type) {
1864 /* MIDI-over-MADI on HDSPe MADIface */
1865 hdspm->midi[0].dataIn = HDSPM_midiDataIn2;
1866 hdspm->midi[0].statusIn = HDSPM_midiStatusIn2;
1867 hdspm->midi[0].dataOut = HDSPM_midiDataOut2;
1868 hdspm->midi[0].statusOut = HDSPM_midiStatusOut2;
1869 hdspm->midi[0].ie = HDSPM_Midi2InterruptEnable;
1870 hdspm->midi[0].irq = HDSPM_midi2IRQPending;
1871 } else {
1872 hdspm->midi[0].dataIn = HDSPM_midiDataIn0;
1873 hdspm->midi[0].statusIn = HDSPM_midiStatusIn0;
1874 hdspm->midi[0].dataOut = HDSPM_midiDataOut0;
1875 hdspm->midi[0].statusOut = HDSPM_midiStatusOut0;
1876 hdspm->midi[0].ie = HDSPM_Midi0InterruptEnable;
1877 hdspm->midi[0].irq = HDSPM_midi0IRQPending;
1878 }
1879 } else if (1 == id) {
1880 hdspm->midi[1].dataIn = HDSPM_midiDataIn1;
1881 hdspm->midi[1].statusIn = HDSPM_midiStatusIn1;
1882 hdspm->midi[1].dataOut = HDSPM_midiDataOut1;
1883 hdspm->midi[1].statusOut = HDSPM_midiStatusOut1;
1884 hdspm->midi[1].ie = HDSPM_Midi1InterruptEnable;
1885 hdspm->midi[1].irq = HDSPM_midi1IRQPending;
1886 } else if ((2 == id) && (MADI == hdspm->io_type)) {
1887 /* MIDI-over-MADI on HDSPe MADI */
1888 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1889 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1890 hdspm->midi[2].dataOut = HDSPM_midiDataOut2;
1891 hdspm->midi[2].statusOut = HDSPM_midiStatusOut2;
1892 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1893 hdspm->midi[2].irq = HDSPM_midi2IRQPending;
1894 } else if (2 == id) {
1895 /* TCO MTC, read only */
1896 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1897 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1898 hdspm->midi[2].dataOut = -1;
1899 hdspm->midi[2].statusOut = -1;
1900 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1901 hdspm->midi[2].irq = HDSPM_midi2IRQPendingAES;
1902 } else if (3 == id) {
1903 /* TCO MTC on HDSPe MADI */
1904 hdspm->midi[3].dataIn = HDSPM_midiDataIn3;
1905 hdspm->midi[3].statusIn = HDSPM_midiStatusIn3;
1906 hdspm->midi[3].dataOut = -1;
1907 hdspm->midi[3].statusOut = -1;
1908 hdspm->midi[3].ie = HDSPM_Midi3InterruptEnable;
1909 hdspm->midi[3].irq = HDSPM_midi3IRQPending;
1910 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001911
Adrian Knoth0dca1792011-01-26 19:32:14 +01001912 if ((id < 2) || ((2 == id) && ((MADI == hdspm->io_type) ||
1913 (MADIface == hdspm->io_type)))) {
1914 if ((id == 0) && (MADIface == hdspm->io_type)) {
1915 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1916 } else if ((id == 2) && (MADI == hdspm->io_type)) {
1917 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1918 } else {
1919 sprintf(buf, "%s MIDI %d", card->shortname, id+1);
1920 }
1921 err = snd_rawmidi_new(card, buf, id, 1, 1,
1922 &hdspm->midi[id].rmidi);
1923 if (err < 0)
1924 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02001925
Adrian Knoth0dca1792011-01-26 19:32:14 +01001926 sprintf(hdspm->midi[id].rmidi->name, "%s MIDI %d",
1927 card->id, id+1);
1928 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
Takashi Iwai763f3562005-06-03 11:25:34 +02001929
Adrian Knoth0dca1792011-01-26 19:32:14 +01001930 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1931 SNDRV_RAWMIDI_STREAM_OUTPUT,
1932 &snd_hdspm_midi_output);
1933 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1934 SNDRV_RAWMIDI_STREAM_INPUT,
1935 &snd_hdspm_midi_input);
1936
1937 hdspm->midi[id].rmidi->info_flags |=
1938 SNDRV_RAWMIDI_INFO_OUTPUT |
1939 SNDRV_RAWMIDI_INFO_INPUT |
1940 SNDRV_RAWMIDI_INFO_DUPLEX;
1941 } else {
1942 /* TCO MTC, read only */
1943 sprintf(buf, "%s MTC %d", card->shortname, id+1);
1944 err = snd_rawmidi_new(card, buf, id, 1, 1,
1945 &hdspm->midi[id].rmidi);
1946 if (err < 0)
1947 return err;
1948
1949 sprintf(hdspm->midi[id].rmidi->name,
1950 "%s MTC %d", card->id, id+1);
1951 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
1952
1953 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1954 SNDRV_RAWMIDI_STREAM_INPUT,
1955 &snd_hdspm_midi_input);
1956
1957 hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
1958 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001959
1960 return 0;
1961}
1962
1963
1964static void hdspm_midi_tasklet(unsigned long arg)
1965{
Takashi Iwai98274f02005-11-17 14:52:34 +01001966 struct hdspm *hdspm = (struct hdspm *)arg;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001967 int i = 0;
1968
1969 while (i < hdspm->midiPorts) {
1970 if (hdspm->midi[i].pending)
1971 snd_hdspm_midi_input_read(&hdspm->midi[i]);
1972
1973 i++;
1974 }
1975}
Takashi Iwai763f3562005-06-03 11:25:34 +02001976
1977
1978/*-----------------------------------------------------------------------------
1979 Status Interface
1980 ----------------------------------------------------------------------------*/
1981
1982/* get the system sample rate which is set */
1983
Adrian Knoth0dca1792011-01-26 19:32:14 +01001984
1985/**
1986 * Calculate the real sample rate from the
1987 * current DDS value.
1988 **/
1989static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
1990{
1991 unsigned int period, rate;
1992
1993 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
1994 rate = hdspm_calc_dds_value(hdspm, period);
1995
1996 return rate;
1997}
1998
1999
Takashi Iwai763f3562005-06-03 11:25:34 +02002000#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002001{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002002 .name = xname, \
2003 .index = xindex, \
2004 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2005 .info = snd_hdspm_info_system_sample_rate, \
2006 .get = snd_hdspm_get_system_sample_rate \
2007}
2008
Takashi Iwai98274f02005-11-17 14:52:34 +01002009static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
2010 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002011{
2012 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2013 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002014 uinfo->value.integer.min = 27000;
2015 uinfo->value.integer.max = 207000;
2016 uinfo->value.integer.step = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002017 return 0;
2018}
2019
Adrian Knoth0dca1792011-01-26 19:32:14 +01002020
Takashi Iwai98274f02005-11-17 14:52:34 +01002021static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
2022 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002023 ucontrol)
2024{
Takashi Iwai98274f02005-11-17 14:52:34 +01002025 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002026
Adrian Knoth0dca1792011-01-26 19:32:14 +01002027 ucontrol->value.integer.value[0] = hdspm_get_system_sample_rate(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002028 return 0;
2029}
2030
Adrian Knoth0dca1792011-01-26 19:32:14 +01002031
2032/**
2033 * Returns the WordClock sample rate class for the given card.
2034 **/
2035static int hdspm_get_wc_sample_rate(struct hdspm *hdspm)
2036{
2037 int status;
2038
2039 switch (hdspm->io_type) {
2040 case RayDAT:
2041 case AIO:
2042 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2043 return (status >> 16) & 0xF;
2044 break;
2045 default:
2046 break;
2047 }
2048
2049
2050 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002051}
2052
Adrian Knoth0dca1792011-01-26 19:32:14 +01002053
2054/**
2055 * Returns the TCO sample rate class for the given card.
2056 **/
2057static int hdspm_get_tco_sample_rate(struct hdspm *hdspm)
2058{
2059 int status;
2060
2061 if (hdspm->tco) {
2062 switch (hdspm->io_type) {
2063 case RayDAT:
2064 case AIO:
2065 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2066 return (status >> 20) & 0xF;
2067 break;
2068 default:
2069 break;
2070 }
2071 }
2072
2073 return 0;
2074}
2075
2076
2077/**
2078 * Returns the SYNC_IN sample rate class for the given card.
2079 **/
2080static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm)
2081{
2082 int status;
2083
2084 if (hdspm->tco) {
2085 switch (hdspm->io_type) {
2086 case RayDAT:
2087 case AIO:
2088 status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2089 return (status >> 12) & 0xF;
2090 break;
2091 default:
2092 break;
2093 }
2094 }
2095
2096 return 0;
2097}
2098
2099
2100/**
2101 * Returns the sample rate class for input source <idx> for
2102 * 'new style' cards like the AIO and RayDAT.
2103 **/
2104static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
2105{
2106 int status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2107
2108 return (status >> (idx*4)) & 0xF;
2109}
2110
2111
2112
2113#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
2114{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2115 .name = xname, \
2116 .private_value = xindex, \
2117 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2118 .info = snd_hdspm_info_autosync_sample_rate, \
2119 .get = snd_hdspm_get_autosync_sample_rate \
2120}
2121
2122
Takashi Iwai98274f02005-11-17 14:52:34 +01002123static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2124 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002125{
Takashi Iwai763f3562005-06-03 11:25:34 +02002126 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2127 uinfo->count = 1;
2128 uinfo->value.enumerated.items = 10;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002129
Takashi Iwai763f3562005-06-03 11:25:34 +02002130 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
Adrian Knoth0dca1792011-01-26 19:32:14 +01002131 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002132 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002133 texts_freq[uinfo->value.enumerated.item]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002134 return 0;
2135}
2136
Adrian Knoth0dca1792011-01-26 19:32:14 +01002137
Takashi Iwai98274f02005-11-17 14:52:34 +01002138static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2139 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002140 ucontrol)
2141{
Takashi Iwai98274f02005-11-17 14:52:34 +01002142 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002143
Adrian Knoth0dca1792011-01-26 19:32:14 +01002144 switch (hdspm->io_type) {
2145 case RayDAT:
2146 switch (kcontrol->private_value) {
2147 case 0:
2148 ucontrol->value.enumerated.item[0] =
2149 hdspm_get_wc_sample_rate(hdspm);
2150 break;
2151 case 7:
2152 ucontrol->value.enumerated.item[0] =
2153 hdspm_get_tco_sample_rate(hdspm);
2154 break;
2155 case 8:
2156 ucontrol->value.enumerated.item[0] =
2157 hdspm_get_sync_in_sample_rate(hdspm);
2158 break;
2159 default:
2160 ucontrol->value.enumerated.item[0] =
2161 hdspm_get_s1_sample_rate(hdspm,
2162 kcontrol->private_value-1);
2163 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002164
Adrian Knoth0dca1792011-01-26 19:32:14 +01002165 case AIO:
2166 switch (kcontrol->private_value) {
2167 case 0: /* WC */
2168 ucontrol->value.enumerated.item[0] =
2169 hdspm_get_wc_sample_rate(hdspm);
2170 break;
2171 case 4: /* TCO */
2172 ucontrol->value.enumerated.item[0] =
2173 hdspm_get_tco_sample_rate(hdspm);
2174 break;
2175 case 5: /* SYNC_IN */
2176 ucontrol->value.enumerated.item[0] =
2177 hdspm_get_sync_in_sample_rate(hdspm);
2178 break;
2179 default:
2180 ucontrol->value.enumerated.item[0] =
2181 hdspm_get_s1_sample_rate(hdspm,
2182 ucontrol->id.index-1);
2183 }
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002184
2185 case AES32:
2186
2187 switch (kcontrol->private_value) {
2188 case 0: /* WC */
2189 ucontrol->value.enumerated.item[0] =
2190 hdspm_get_wc_sample_rate(hdspm);
2191 break;
2192 case 9: /* TCO */
2193 ucontrol->value.enumerated.item[0] =
2194 hdspm_get_tco_sample_rate(hdspm);
2195 break;
2196 case 10: /* SYNC_IN */
2197 ucontrol->value.enumerated.item[0] =
2198 hdspm_get_sync_in_sample_rate(hdspm);
2199 break;
2200 default: /* AES1 to AES8 */
2201 ucontrol->value.enumerated.item[0] =
2202 hdspm_get_s1_sample_rate(hdspm,
2203 kcontrol->private_value-1);
2204 break;
2205
2206 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002207 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002208 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002209 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002210
Takashi Iwai763f3562005-06-03 11:25:34 +02002211 return 0;
2212}
2213
Adrian Knoth0dca1792011-01-26 19:32:14 +01002214
Takashi Iwai763f3562005-06-03 11:25:34 +02002215#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002216{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2217 .name = xname, \
2218 .index = xindex, \
2219 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2220 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2221 .info = snd_hdspm_info_system_clock_mode, \
2222 .get = snd_hdspm_get_system_clock_mode, \
2223 .put = snd_hdspm_put_system_clock_mode, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002224}
2225
2226
Adrian Knoth0dca1792011-01-26 19:32:14 +01002227/**
2228 * Returns the system clock mode for the given card.
2229 * @returns 0 - master, 1 - slave
2230 **/
2231static int hdspm_system_clock_mode(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002232{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002233 switch (hdspm->io_type) {
2234 case AIO:
2235 case RayDAT:
2236 if (hdspm->settings_register & HDSPM_c0Master)
2237 return 0;
2238 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002239
Adrian Knoth0dca1792011-01-26 19:32:14 +01002240 default:
2241 if (hdspm->control_register & HDSPM_ClockModeMaster)
2242 return 0;
2243 }
2244
Takashi Iwai763f3562005-06-03 11:25:34 +02002245 return 1;
2246}
2247
Adrian Knoth0dca1792011-01-26 19:32:14 +01002248
2249/**
2250 * Sets the system clock mode.
2251 * @param mode 0 - master, 1 - slave
2252 **/
2253static void hdspm_set_system_clock_mode(struct hdspm *hdspm, int mode)
2254{
2255 switch (hdspm->io_type) {
2256 case AIO:
2257 case RayDAT:
2258 if (0 == mode)
2259 hdspm->settings_register |= HDSPM_c0Master;
2260 else
2261 hdspm->settings_register &= ~HDSPM_c0Master;
2262
2263 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2264 break;
2265
2266 default:
2267 if (0 == mode)
2268 hdspm->control_register |= HDSPM_ClockModeMaster;
2269 else
2270 hdspm->control_register &= ~HDSPM_ClockModeMaster;
2271
2272 hdspm_write(hdspm, HDSPM_controlRegister,
2273 hdspm->control_register);
2274 }
2275}
2276
2277
Takashi Iwai98274f02005-11-17 14:52:34 +01002278static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
2279 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002280{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002281 static char *texts[] = { "Master", "AutoSync" };
Takashi Iwai763f3562005-06-03 11:25:34 +02002282
2283 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2284 uinfo->count = 1;
2285 uinfo->value.enumerated.items = 2;
2286 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2287 uinfo->value.enumerated.item =
2288 uinfo->value.enumerated.items - 1;
2289 strcpy(uinfo->value.enumerated.name,
2290 texts[uinfo->value.enumerated.item]);
2291 return 0;
2292}
2293
Takashi Iwai98274f02005-11-17 14:52:34 +01002294static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
2295 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002296{
Takashi Iwai98274f02005-11-17 14:52:34 +01002297 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002298
Adrian Knoth0dca1792011-01-26 19:32:14 +01002299 ucontrol->value.enumerated.item[0] = hdspm_system_clock_mode(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002300 return 0;
2301}
2302
Adrian Knoth0dca1792011-01-26 19:32:14 +01002303static int snd_hdspm_put_system_clock_mode(struct snd_kcontrol *kcontrol,
2304 struct snd_ctl_elem_value *ucontrol)
2305{
2306 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2307 int val;
2308
2309 if (!snd_hdspm_use_is_exclusive(hdspm))
2310 return -EBUSY;
2311
2312 val = ucontrol->value.enumerated.item[0];
2313 if (val < 0)
2314 val = 0;
2315 else if (val > 1)
2316 val = 1;
2317
2318 hdspm_set_system_clock_mode(hdspm, val);
2319
2320 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002321}
2322
Adrian Knoth0dca1792011-01-26 19:32:14 +01002323
2324#define HDSPM_INTERNAL_CLOCK(xname, xindex) \
2325{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2326 .name = xname, \
2327 .index = xindex, \
2328 .info = snd_hdspm_info_clock_source, \
2329 .get = snd_hdspm_get_clock_source, \
2330 .put = snd_hdspm_put_clock_source \
2331}
2332
2333
Takashi Iwai98274f02005-11-17 14:52:34 +01002334static int hdspm_clock_source(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002335{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002336 switch (hdspm->system_sample_rate) {
2337 case 32000: return 0;
2338 case 44100: return 1;
2339 case 48000: return 2;
2340 case 64000: return 3;
2341 case 88200: return 4;
2342 case 96000: return 5;
2343 case 128000: return 6;
2344 case 176400: return 7;
2345 case 192000: return 8;
Takashi Iwai763f3562005-06-03 11:25:34 +02002346 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002347
2348 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002349}
2350
Takashi Iwai98274f02005-11-17 14:52:34 +01002351static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
Takashi Iwai763f3562005-06-03 11:25:34 +02002352{
2353 int rate;
2354 switch (mode) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002355 case 0:
2356 rate = 32000; break;
2357 case 1:
2358 rate = 44100; break;
2359 case 2:
2360 rate = 48000; break;
2361 case 3:
2362 rate = 64000; break;
2363 case 4:
2364 rate = 88200; break;
2365 case 5:
2366 rate = 96000; break;
2367 case 6:
2368 rate = 128000; break;
2369 case 7:
2370 rate = 176400; break;
2371 case 8:
2372 rate = 192000; break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002373 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002374 rate = 48000;
Takashi Iwai763f3562005-06-03 11:25:34 +02002375 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002376 hdspm_set_rate(hdspm, rate, 1);
2377 return 0;
2378}
2379
Takashi Iwai98274f02005-11-17 14:52:34 +01002380static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
2381 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002382{
Takashi Iwai763f3562005-06-03 11:25:34 +02002383 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2384 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002385 uinfo->value.enumerated.items = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002386
2387 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2388 uinfo->value.enumerated.item =
2389 uinfo->value.enumerated.items - 1;
2390
2391 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002392 texts_freq[uinfo->value.enumerated.item+1]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002393
2394 return 0;
2395}
2396
Takashi Iwai98274f02005-11-17 14:52:34 +01002397static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
2398 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002399{
Takashi Iwai98274f02005-11-17 14:52:34 +01002400 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002401
2402 ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
2403 return 0;
2404}
2405
Takashi Iwai98274f02005-11-17 14:52:34 +01002406static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
2407 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002408{
Takashi Iwai98274f02005-11-17 14:52:34 +01002409 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002410 int change;
2411 int val;
2412
2413 if (!snd_hdspm_use_is_exclusive(hdspm))
2414 return -EBUSY;
2415 val = ucontrol->value.enumerated.item[0];
2416 if (val < 0)
2417 val = 0;
Remy Bruno65345992007-08-31 12:21:08 +02002418 if (val > 9)
2419 val = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002420 spin_lock_irq(&hdspm->lock);
2421 if (val != hdspm_clock_source(hdspm))
2422 change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
2423 else
2424 change = 0;
2425 spin_unlock_irq(&hdspm->lock);
2426 return change;
2427}
2428
Adrian Knoth0dca1792011-01-26 19:32:14 +01002429
Takashi Iwai763f3562005-06-03 11:25:34 +02002430#define HDSPM_PREF_SYNC_REF(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002431{.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2432 .name = xname, \
2433 .index = xindex, \
2434 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2435 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2436 .info = snd_hdspm_info_pref_sync_ref, \
2437 .get = snd_hdspm_get_pref_sync_ref, \
2438 .put = snd_hdspm_put_pref_sync_ref \
Takashi Iwai763f3562005-06-03 11:25:34 +02002439}
2440
Adrian Knoth0dca1792011-01-26 19:32:14 +01002441
2442/**
2443 * Returns the current preferred sync reference setting.
2444 * The semantics of the return value are depending on the
2445 * card, please see the comments for clarification.
2446 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002447static int hdspm_pref_sync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002448{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002449 switch (hdspm->io_type) {
2450 case AES32:
Remy Bruno3cee5a62006-10-16 12:46:32 +02002451 switch (hdspm->control_register & HDSPM_SyncRefMask) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002452 case 0: return 0; /* WC */
2453 case HDSPM_SyncRef0: return 1; /* AES 1 */
2454 case HDSPM_SyncRef1: return 2; /* AES 2 */
2455 case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; /* AES 3 */
2456 case HDSPM_SyncRef2: return 4; /* AES 4 */
2457 case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; /* AES 5 */
2458 case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; /* AES 6 */
2459 case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0:
2460 return 7; /* AES 7 */
2461 case HDSPM_SyncRef3: return 8; /* AES 8 */
2462 case HDSPM_SyncRef3+HDSPM_SyncRef0: return 9; /* TCO */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002463 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002464 break;
2465
2466 case MADI:
2467 case MADIface:
2468 if (hdspm->tco) {
2469 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2470 case 0: return 0; /* WC */
2471 case HDSPM_SyncRef0: return 1; /* MADI */
2472 case HDSPM_SyncRef1: return 2; /* TCO */
2473 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2474 return 3; /* SYNC_IN */
2475 }
2476 } else {
2477 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2478 case 0: return 0; /* WC */
2479 case HDSPM_SyncRef0: return 1; /* MADI */
2480 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2481 return 2; /* SYNC_IN */
2482 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02002483 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002484 break;
2485
2486 case RayDAT:
2487 if (hdspm->tco) {
2488 switch ((hdspm->settings_register &
2489 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2490 case 0: return 0; /* WC */
2491 case 3: return 1; /* ADAT 1 */
2492 case 4: return 2; /* ADAT 2 */
2493 case 5: return 3; /* ADAT 3 */
2494 case 6: return 4; /* ADAT 4 */
2495 case 1: return 5; /* AES */
2496 case 2: return 6; /* SPDIF */
2497 case 9: return 7; /* TCO */
2498 case 10: return 8; /* SYNC_IN */
2499 }
2500 } else {
2501 switch ((hdspm->settings_register &
2502 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2503 case 0: return 0; /* WC */
2504 case 3: return 1; /* ADAT 1 */
2505 case 4: return 2; /* ADAT 2 */
2506 case 5: return 3; /* ADAT 3 */
2507 case 6: return 4; /* ADAT 4 */
2508 case 1: return 5; /* AES */
2509 case 2: return 6; /* SPDIF */
2510 case 10: return 7; /* SYNC_IN */
2511 }
2512 }
2513
2514 break;
2515
2516 case AIO:
2517 if (hdspm->tco) {
2518 switch ((hdspm->settings_register &
2519 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2520 case 0: return 0; /* WC */
2521 case 3: return 1; /* ADAT */
2522 case 1: return 2; /* AES */
2523 case 2: return 3; /* SPDIF */
2524 case 9: return 4; /* TCO */
2525 case 10: return 5; /* SYNC_IN */
2526 }
2527 } else {
2528 switch ((hdspm->settings_register &
2529 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2530 case 0: return 0; /* WC */
2531 case 3: return 1; /* ADAT */
2532 case 1: return 2; /* AES */
2533 case 2: return 3; /* SPDIF */
2534 case 10: return 4; /* SYNC_IN */
2535 }
2536 }
2537
2538 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002539 }
2540
Adrian Knoth0dca1792011-01-26 19:32:14 +01002541 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002542}
2543
Adrian Knoth0dca1792011-01-26 19:32:14 +01002544
2545/**
2546 * Set the preferred sync reference to <pref>. The semantics
2547 * of <pref> are depending on the card type, see the comments
2548 * for clarification.
2549 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002550static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
Takashi Iwai763f3562005-06-03 11:25:34 +02002551{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002552 int p = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002553
Adrian Knoth0dca1792011-01-26 19:32:14 +01002554 switch (hdspm->io_type) {
2555 case AES32:
2556 hdspm->control_register &= ~HDSPM_SyncRefMask;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002557 switch (pref) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002558 case 0: /* WC */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002559 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002560 case 1: /* AES 1 */
2561 hdspm->control_register |= HDSPM_SyncRef0;
2562 break;
2563 case 2: /* AES 2 */
2564 hdspm->control_register |= HDSPM_SyncRef1;
2565 break;
2566 case 3: /* AES 3 */
2567 hdspm->control_register |=
2568 HDSPM_SyncRef1+HDSPM_SyncRef0;
2569 break;
2570 case 4: /* AES 4 */
2571 hdspm->control_register |= HDSPM_SyncRef2;
2572 break;
2573 case 5: /* AES 5 */
2574 hdspm->control_register |=
2575 HDSPM_SyncRef2+HDSPM_SyncRef0;
2576 break;
2577 case 6: /* AES 6 */
2578 hdspm->control_register |=
2579 HDSPM_SyncRef2+HDSPM_SyncRef1;
2580 break;
2581 case 7: /* AES 7 */
2582 hdspm->control_register |=
2583 HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
2584 break;
2585 case 8: /* AES 8 */
2586 hdspm->control_register |= HDSPM_SyncRef3;
2587 break;
2588 case 9: /* TCO */
2589 hdspm->control_register |=
2590 HDSPM_SyncRef3+HDSPM_SyncRef0;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002591 break;
2592 default:
2593 return -1;
2594 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002595
2596 break;
2597
2598 case MADI:
2599 case MADIface:
2600 hdspm->control_register &= ~HDSPM_SyncRefMask;
2601 if (hdspm->tco) {
2602 switch (pref) {
2603 case 0: /* WC */
2604 break;
2605 case 1: /* MADI */
2606 hdspm->control_register |= HDSPM_SyncRef0;
2607 break;
2608 case 2: /* TCO */
2609 hdspm->control_register |= HDSPM_SyncRef1;
2610 break;
2611 case 3: /* SYNC_IN */
2612 hdspm->control_register |=
2613 HDSPM_SyncRef0+HDSPM_SyncRef1;
2614 break;
2615 default:
2616 return -1;
2617 }
2618 } else {
2619 switch (pref) {
2620 case 0: /* WC */
2621 break;
2622 case 1: /* MADI */
2623 hdspm->control_register |= HDSPM_SyncRef0;
2624 break;
2625 case 2: /* SYNC_IN */
2626 hdspm->control_register |=
2627 HDSPM_SyncRef0+HDSPM_SyncRef1;
2628 break;
2629 default:
2630 return -1;
2631 }
2632 }
2633
2634 break;
2635
2636 case RayDAT:
2637 if (hdspm->tco) {
2638 switch (pref) {
2639 case 0: p = 0; break; /* WC */
2640 case 1: p = 3; break; /* ADAT 1 */
2641 case 2: p = 4; break; /* ADAT 2 */
2642 case 3: p = 5; break; /* ADAT 3 */
2643 case 4: p = 6; break; /* ADAT 4 */
2644 case 5: p = 1; break; /* AES */
2645 case 6: p = 2; break; /* SPDIF */
2646 case 7: p = 9; break; /* TCO */
2647 case 8: p = 10; break; /* SYNC_IN */
2648 default: return -1;
2649 }
2650 } else {
2651 switch (pref) {
2652 case 0: p = 0; break; /* WC */
2653 case 1: p = 3; break; /* ADAT 1 */
2654 case 2: p = 4; break; /* ADAT 2 */
2655 case 3: p = 5; break; /* ADAT 3 */
2656 case 4: p = 6; break; /* ADAT 4 */
2657 case 5: p = 1; break; /* AES */
2658 case 6: p = 2; break; /* SPDIF */
2659 case 7: p = 10; break; /* SYNC_IN */
2660 default: return -1;
2661 }
2662 }
2663 break;
2664
2665 case AIO:
2666 if (hdspm->tco) {
2667 switch (pref) {
2668 case 0: p = 0; break; /* WC */
2669 case 1: p = 3; break; /* ADAT */
2670 case 2: p = 1; break; /* AES */
2671 case 3: p = 2; break; /* SPDIF */
2672 case 4: p = 9; break; /* TCO */
2673 case 5: p = 10; break; /* SYNC_IN */
2674 default: return -1;
2675 }
2676 } else {
2677 switch (pref) {
2678 case 0: p = 0; break; /* WC */
2679 case 1: p = 3; break; /* ADAT */
2680 case 2: p = 1; break; /* AES */
2681 case 3: p = 2; break; /* SPDIF */
2682 case 4: p = 10; break; /* SYNC_IN */
2683 default: return -1;
2684 }
2685 }
2686 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002687 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002688
2689 switch (hdspm->io_type) {
2690 case RayDAT:
2691 case AIO:
2692 hdspm->settings_register &= ~HDSPM_c0_SyncRefMask;
2693 hdspm->settings_register |= HDSPM_c0_SyncRef0 * p;
2694 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2695 break;
2696
2697 case MADI:
2698 case MADIface:
2699 case AES32:
2700 hdspm_write(hdspm, HDSPM_controlRegister,
2701 hdspm->control_register);
2702 }
2703
Takashi Iwai763f3562005-06-03 11:25:34 +02002704 return 0;
2705}
2706
Adrian Knoth0dca1792011-01-26 19:32:14 +01002707
Takashi Iwai98274f02005-11-17 14:52:34 +01002708static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
2709 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002710{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002711 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002712
Adrian Knoth0dca1792011-01-26 19:32:14 +01002713 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2714 uinfo->count = 1;
2715 uinfo->value.enumerated.items = hdspm->texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +02002716
Adrian Knoth0dca1792011-01-26 19:32:14 +01002717 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2718 uinfo->value.enumerated.item =
2719 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002720
Adrian Knoth0dca1792011-01-26 19:32:14 +01002721 strcpy(uinfo->value.enumerated.name,
2722 hdspm->texts_autosync[uinfo->value.enumerated.item]);
Remy Bruno3cee5a62006-10-16 12:46:32 +02002723
Takashi Iwai763f3562005-06-03 11:25:34 +02002724 return 0;
2725}
2726
Takashi Iwai98274f02005-11-17 14:52:34 +01002727static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
2728 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002729{
Takashi Iwai98274f02005-11-17 14:52:34 +01002730 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002731 int psf = hdspm_pref_sync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002732
Adrian Knoth0dca1792011-01-26 19:32:14 +01002733 if (psf >= 0) {
2734 ucontrol->value.enumerated.item[0] = psf;
2735 return 0;
2736 }
2737
2738 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002739}
2740
Takashi Iwai98274f02005-11-17 14:52:34 +01002741static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
2742 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002743{
Takashi Iwai98274f02005-11-17 14:52:34 +01002744 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002745 int val, change = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002746
2747 if (!snd_hdspm_use_is_exclusive(hdspm))
2748 return -EBUSY;
2749
Adrian Knoth0dca1792011-01-26 19:32:14 +01002750 val = ucontrol->value.enumerated.item[0];
2751
2752 if (val < 0)
2753 val = 0;
2754 else if (val >= hdspm->texts_autosync_items)
2755 val = hdspm->texts_autosync_items-1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002756
2757 spin_lock_irq(&hdspm->lock);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002758 if (val != hdspm_pref_sync_ref(hdspm))
2759 change = (0 == hdspm_set_pref_sync_ref(hdspm, val)) ? 1 : 0;
2760
Takashi Iwai763f3562005-06-03 11:25:34 +02002761 spin_unlock_irq(&hdspm->lock);
2762 return change;
2763}
2764
Adrian Knoth0dca1792011-01-26 19:32:14 +01002765
Takashi Iwai763f3562005-06-03 11:25:34 +02002766#define HDSPM_AUTOSYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002767{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002768 .name = xname, \
2769 .index = xindex, \
2770 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2771 .info = snd_hdspm_info_autosync_ref, \
2772 .get = snd_hdspm_get_autosync_ref, \
2773}
2774
Adrian Knoth0dca1792011-01-26 19:32:14 +01002775static int hdspm_autosync_ref(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002776{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002777 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002778 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002779 unsigned int syncref =
2780 (status >> HDSPM_AES32_syncref_bit) & 0xF;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002781 if (syncref == 0)
2782 return HDSPM_AES32_AUTOSYNC_FROM_WORD;
2783 if (syncref <= 8)
2784 return syncref;
2785 return HDSPM_AES32_AUTOSYNC_FROM_NONE;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002786 } else if (MADI == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002787 /* This looks at the autosync selected sync reference */
2788 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Takashi Iwai763f3562005-06-03 11:25:34 +02002789
Remy Bruno3cee5a62006-10-16 12:46:32 +02002790 switch (status2 & HDSPM_SelSyncRefMask) {
2791 case HDSPM_SelSyncRef_WORD:
2792 return HDSPM_AUTOSYNC_FROM_WORD;
2793 case HDSPM_SelSyncRef_MADI:
2794 return HDSPM_AUTOSYNC_FROM_MADI;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002795 case HDSPM_SelSyncRef_TCO:
2796 return HDSPM_AUTOSYNC_FROM_TCO;
2797 case HDSPM_SelSyncRef_SyncIn:
2798 return HDSPM_AUTOSYNC_FROM_SYNC_IN;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002799 case HDSPM_SelSyncRef_NVALID:
2800 return HDSPM_AUTOSYNC_FROM_NONE;
2801 default:
2802 return 0;
2803 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002804
Takashi Iwai763f3562005-06-03 11:25:34 +02002805 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002806 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002807}
2808
Adrian Knoth0dca1792011-01-26 19:32:14 +01002809
Takashi Iwai98274f02005-11-17 14:52:34 +01002810static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
2811 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002812{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002813 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002814
Adrian Knoth0dca1792011-01-26 19:32:14 +01002815 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002816 static char *texts[] = { "WordClock", "AES1", "AES2", "AES3",
2817 "AES4", "AES5", "AES6", "AES7", "AES8", "None"};
2818
2819 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2820 uinfo->count = 1;
2821 uinfo->value.enumerated.items = 10;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002822 if (uinfo->value.enumerated.item >=
2823 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002824 uinfo->value.enumerated.item =
2825 uinfo->value.enumerated.items - 1;
2826 strcpy(uinfo->value.enumerated.name,
2827 texts[uinfo->value.enumerated.item]);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002828 } else if (MADI == hdspm->io_type) {
2829 static char *texts[] = {"Word Clock", "MADI", "TCO",
2830 "Sync In", "None" };
Remy Bruno3cee5a62006-10-16 12:46:32 +02002831
2832 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2833 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002834 uinfo->value.enumerated.items = 5;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002835 if (uinfo->value.enumerated.item >=
Adrian Knoth0dca1792011-01-26 19:32:14 +01002836 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002837 uinfo->value.enumerated.item =
2838 uinfo->value.enumerated.items - 1;
2839 strcpy(uinfo->value.enumerated.name,
2840 texts[uinfo->value.enumerated.item]);
2841 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002842 return 0;
2843}
2844
Takashi Iwai98274f02005-11-17 14:52:34 +01002845static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
2846 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002847{
Takashi Iwai98274f02005-11-17 14:52:34 +01002848 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002849
Remy Bruno65345992007-08-31 12:21:08 +02002850 ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002851 return 0;
2852}
2853
Adrian Knoth0dca1792011-01-26 19:32:14 +01002854
Takashi Iwai763f3562005-06-03 11:25:34 +02002855#define HDSPM_LINE_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002856{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002857 .name = xname, \
2858 .index = xindex, \
2859 .info = snd_hdspm_info_line_out, \
2860 .get = snd_hdspm_get_line_out, \
2861 .put = snd_hdspm_put_line_out \
2862}
2863
Takashi Iwai98274f02005-11-17 14:52:34 +01002864static int hdspm_line_out(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002865{
2866 return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0;
2867}
2868
2869
Takashi Iwai98274f02005-11-17 14:52:34 +01002870static int hdspm_set_line_output(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002871{
2872 if (out)
2873 hdspm->control_register |= HDSPM_LineOut;
2874 else
2875 hdspm->control_register &= ~HDSPM_LineOut;
2876 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2877
2878 return 0;
2879}
2880
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002881#define snd_hdspm_info_line_out snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002882
Takashi Iwai98274f02005-11-17 14:52:34 +01002883static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol,
2884 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002885{
Takashi Iwai98274f02005-11-17 14:52:34 +01002886 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002887
2888 spin_lock_irq(&hdspm->lock);
2889 ucontrol->value.integer.value[0] = hdspm_line_out(hdspm);
2890 spin_unlock_irq(&hdspm->lock);
2891 return 0;
2892}
2893
Takashi Iwai98274f02005-11-17 14:52:34 +01002894static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
2895 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002896{
Takashi Iwai98274f02005-11-17 14:52:34 +01002897 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002898 int change;
2899 unsigned int val;
2900
2901 if (!snd_hdspm_use_is_exclusive(hdspm))
2902 return -EBUSY;
2903 val = ucontrol->value.integer.value[0] & 1;
2904 spin_lock_irq(&hdspm->lock);
2905 change = (int) val != hdspm_line_out(hdspm);
2906 hdspm_set_line_output(hdspm, val);
2907 spin_unlock_irq(&hdspm->lock);
2908 return change;
2909}
2910
Adrian Knoth0dca1792011-01-26 19:32:14 +01002911
Takashi Iwai763f3562005-06-03 11:25:34 +02002912#define HDSPM_TX_64(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002913{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002914 .name = xname, \
2915 .index = xindex, \
2916 .info = snd_hdspm_info_tx_64, \
2917 .get = snd_hdspm_get_tx_64, \
2918 .put = snd_hdspm_put_tx_64 \
2919}
2920
Takashi Iwai98274f02005-11-17 14:52:34 +01002921static int hdspm_tx_64(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002922{
2923 return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0;
2924}
2925
Takashi Iwai98274f02005-11-17 14:52:34 +01002926static int hdspm_set_tx_64(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002927{
2928 if (out)
2929 hdspm->control_register |= HDSPM_TX_64ch;
2930 else
2931 hdspm->control_register &= ~HDSPM_TX_64ch;
2932 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2933
2934 return 0;
2935}
2936
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002937#define snd_hdspm_info_tx_64 snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002938
Takashi Iwai98274f02005-11-17 14:52:34 +01002939static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol,
2940 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002941{
Takashi Iwai98274f02005-11-17 14:52:34 +01002942 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002943
2944 spin_lock_irq(&hdspm->lock);
2945 ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm);
2946 spin_unlock_irq(&hdspm->lock);
2947 return 0;
2948}
2949
Takashi Iwai98274f02005-11-17 14:52:34 +01002950static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
2951 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002952{
Takashi Iwai98274f02005-11-17 14:52:34 +01002953 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002954 int change;
2955 unsigned int val;
2956
2957 if (!snd_hdspm_use_is_exclusive(hdspm))
2958 return -EBUSY;
2959 val = ucontrol->value.integer.value[0] & 1;
2960 spin_lock_irq(&hdspm->lock);
2961 change = (int) val != hdspm_tx_64(hdspm);
2962 hdspm_set_tx_64(hdspm, val);
2963 spin_unlock_irq(&hdspm->lock);
2964 return change;
2965}
2966
Adrian Knoth0dca1792011-01-26 19:32:14 +01002967
Takashi Iwai763f3562005-06-03 11:25:34 +02002968#define HDSPM_C_TMS(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002969{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002970 .name = xname, \
2971 .index = xindex, \
2972 .info = snd_hdspm_info_c_tms, \
2973 .get = snd_hdspm_get_c_tms, \
2974 .put = snd_hdspm_put_c_tms \
2975}
2976
Takashi Iwai98274f02005-11-17 14:52:34 +01002977static int hdspm_c_tms(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002978{
2979 return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0;
2980}
2981
Takashi Iwai98274f02005-11-17 14:52:34 +01002982static int hdspm_set_c_tms(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002983{
2984 if (out)
2985 hdspm->control_register |= HDSPM_clr_tms;
2986 else
2987 hdspm->control_register &= ~HDSPM_clr_tms;
2988 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2989
2990 return 0;
2991}
2992
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002993#define snd_hdspm_info_c_tms snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002994
Takashi Iwai98274f02005-11-17 14:52:34 +01002995static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol,
2996 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002997{
Takashi Iwai98274f02005-11-17 14:52:34 +01002998 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002999
3000 spin_lock_irq(&hdspm->lock);
3001 ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm);
3002 spin_unlock_irq(&hdspm->lock);
3003 return 0;
3004}
3005
Takashi Iwai98274f02005-11-17 14:52:34 +01003006static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,
3007 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003008{
Takashi Iwai98274f02005-11-17 14:52:34 +01003009 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003010 int change;
3011 unsigned int val;
3012
3013 if (!snd_hdspm_use_is_exclusive(hdspm))
3014 return -EBUSY;
3015 val = ucontrol->value.integer.value[0] & 1;
3016 spin_lock_irq(&hdspm->lock);
3017 change = (int) val != hdspm_c_tms(hdspm);
3018 hdspm_set_c_tms(hdspm, val);
3019 spin_unlock_irq(&hdspm->lock);
3020 return change;
3021}
3022
Adrian Knoth0dca1792011-01-26 19:32:14 +01003023
Takashi Iwai763f3562005-06-03 11:25:34 +02003024#define HDSPM_SAFE_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003025{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003026 .name = xname, \
3027 .index = xindex, \
3028 .info = snd_hdspm_info_safe_mode, \
3029 .get = snd_hdspm_get_safe_mode, \
3030 .put = snd_hdspm_put_safe_mode \
3031}
3032
Takashi Iwai98274f02005-11-17 14:52:34 +01003033static int hdspm_safe_mode(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003034{
3035 return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0;
3036}
3037
Takashi Iwai98274f02005-11-17 14:52:34 +01003038static int hdspm_set_safe_mode(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02003039{
3040 if (out)
3041 hdspm->control_register |= HDSPM_AutoInp;
3042 else
3043 hdspm->control_register &= ~HDSPM_AutoInp;
3044 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3045
3046 return 0;
3047}
3048
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003049#define snd_hdspm_info_safe_mode snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02003050
Takashi Iwai98274f02005-11-17 14:52:34 +01003051static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol,
3052 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003053{
Takashi Iwai98274f02005-11-17 14:52:34 +01003054 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003055
3056 spin_lock_irq(&hdspm->lock);
3057 ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm);
3058 spin_unlock_irq(&hdspm->lock);
3059 return 0;
3060}
3061
Takashi Iwai98274f02005-11-17 14:52:34 +01003062static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
3063 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003064{
Takashi Iwai98274f02005-11-17 14:52:34 +01003065 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003066 int change;
3067 unsigned int val;
3068
3069 if (!snd_hdspm_use_is_exclusive(hdspm))
3070 return -EBUSY;
3071 val = ucontrol->value.integer.value[0] & 1;
3072 spin_lock_irq(&hdspm->lock);
3073 change = (int) val != hdspm_safe_mode(hdspm);
3074 hdspm_set_safe_mode(hdspm, val);
3075 spin_unlock_irq(&hdspm->lock);
3076 return change;
3077}
3078
Adrian Knoth0dca1792011-01-26 19:32:14 +01003079
Remy Bruno3cee5a62006-10-16 12:46:32 +02003080#define HDSPM_EMPHASIS(xname, xindex) \
3081{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3082 .name = xname, \
3083 .index = xindex, \
3084 .info = snd_hdspm_info_emphasis, \
3085 .get = snd_hdspm_get_emphasis, \
3086 .put = snd_hdspm_put_emphasis \
3087}
3088
3089static int hdspm_emphasis(struct hdspm * hdspm)
3090{
3091 return (hdspm->control_register & HDSPM_Emphasis) ? 1 : 0;
3092}
3093
3094static int hdspm_set_emphasis(struct hdspm * hdspm, int emp)
3095{
3096 if (emp)
3097 hdspm->control_register |= HDSPM_Emphasis;
3098 else
3099 hdspm->control_register &= ~HDSPM_Emphasis;
3100 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3101
3102 return 0;
3103}
3104
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003105#define snd_hdspm_info_emphasis snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02003106
3107static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol,
3108 struct snd_ctl_elem_value *ucontrol)
3109{
3110 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3111
3112 spin_lock_irq(&hdspm->lock);
3113 ucontrol->value.enumerated.item[0] = hdspm_emphasis(hdspm);
3114 spin_unlock_irq(&hdspm->lock);
3115 return 0;
3116}
3117
3118static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
3119 struct snd_ctl_elem_value *ucontrol)
3120{
3121 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3122 int change;
3123 unsigned int val;
3124
3125 if (!snd_hdspm_use_is_exclusive(hdspm))
3126 return -EBUSY;
3127 val = ucontrol->value.integer.value[0] & 1;
3128 spin_lock_irq(&hdspm->lock);
3129 change = (int) val != hdspm_emphasis(hdspm);
3130 hdspm_set_emphasis(hdspm, val);
3131 spin_unlock_irq(&hdspm->lock);
3132 return change;
3133}
3134
Adrian Knoth0dca1792011-01-26 19:32:14 +01003135
Remy Bruno3cee5a62006-10-16 12:46:32 +02003136#define HDSPM_DOLBY(xname, xindex) \
3137{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3138 .name = xname, \
3139 .index = xindex, \
3140 .info = snd_hdspm_info_dolby, \
3141 .get = snd_hdspm_get_dolby, \
3142 .put = snd_hdspm_put_dolby \
3143}
3144
3145static int hdspm_dolby(struct hdspm * hdspm)
3146{
3147 return (hdspm->control_register & HDSPM_Dolby) ? 1 : 0;
3148}
3149
3150static int hdspm_set_dolby(struct hdspm * hdspm, int dol)
3151{
3152 if (dol)
3153 hdspm->control_register |= HDSPM_Dolby;
3154 else
3155 hdspm->control_register &= ~HDSPM_Dolby;
3156 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3157
3158 return 0;
3159}
3160
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003161#define snd_hdspm_info_dolby snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02003162
3163static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol,
3164 struct snd_ctl_elem_value *ucontrol)
3165{
3166 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3167
3168 spin_lock_irq(&hdspm->lock);
3169 ucontrol->value.enumerated.item[0] = hdspm_dolby(hdspm);
3170 spin_unlock_irq(&hdspm->lock);
3171 return 0;
3172}
3173
3174static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
3175 struct snd_ctl_elem_value *ucontrol)
3176{
3177 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3178 int change;
3179 unsigned int val;
3180
3181 if (!snd_hdspm_use_is_exclusive(hdspm))
3182 return -EBUSY;
3183 val = ucontrol->value.integer.value[0] & 1;
3184 spin_lock_irq(&hdspm->lock);
3185 change = (int) val != hdspm_dolby(hdspm);
3186 hdspm_set_dolby(hdspm, val);
3187 spin_unlock_irq(&hdspm->lock);
3188 return change;
3189}
3190
Adrian Knoth0dca1792011-01-26 19:32:14 +01003191
Remy Bruno3cee5a62006-10-16 12:46:32 +02003192#define HDSPM_PROFESSIONAL(xname, xindex) \
3193{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3194 .name = xname, \
3195 .index = xindex, \
3196 .info = snd_hdspm_info_professional, \
3197 .get = snd_hdspm_get_professional, \
3198 .put = snd_hdspm_put_professional \
3199}
3200
3201static int hdspm_professional(struct hdspm * hdspm)
3202{
3203 return (hdspm->control_register & HDSPM_Professional) ? 1 : 0;
3204}
3205
3206static int hdspm_set_professional(struct hdspm * hdspm, int dol)
3207{
3208 if (dol)
3209 hdspm->control_register |= HDSPM_Professional;
3210 else
3211 hdspm->control_register &= ~HDSPM_Professional;
3212 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3213
3214 return 0;
3215}
3216
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003217#define snd_hdspm_info_professional snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02003218
3219static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol,
3220 struct snd_ctl_elem_value *ucontrol)
3221{
3222 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3223
3224 spin_lock_irq(&hdspm->lock);
3225 ucontrol->value.enumerated.item[0] = hdspm_professional(hdspm);
3226 spin_unlock_irq(&hdspm->lock);
3227 return 0;
3228}
3229
3230static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,
3231 struct snd_ctl_elem_value *ucontrol)
3232{
3233 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3234 int change;
3235 unsigned int val;
3236
3237 if (!snd_hdspm_use_is_exclusive(hdspm))
3238 return -EBUSY;
3239 val = ucontrol->value.integer.value[0] & 1;
3240 spin_lock_irq(&hdspm->lock);
3241 change = (int) val != hdspm_professional(hdspm);
3242 hdspm_set_professional(hdspm, val);
3243 spin_unlock_irq(&hdspm->lock);
3244 return change;
3245}
3246
Takashi Iwai763f3562005-06-03 11:25:34 +02003247#define HDSPM_INPUT_SELECT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003248{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003249 .name = xname, \
3250 .index = xindex, \
3251 .info = snd_hdspm_info_input_select, \
3252 .get = snd_hdspm_get_input_select, \
3253 .put = snd_hdspm_put_input_select \
3254}
3255
Takashi Iwai98274f02005-11-17 14:52:34 +01003256static int hdspm_input_select(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003257{
3258 return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
3259}
3260
Takashi Iwai98274f02005-11-17 14:52:34 +01003261static int hdspm_set_input_select(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02003262{
3263 if (out)
3264 hdspm->control_register |= HDSPM_InputSelect0;
3265 else
3266 hdspm->control_register &= ~HDSPM_InputSelect0;
3267 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3268
3269 return 0;
3270}
3271
Takashi Iwai98274f02005-11-17 14:52:34 +01003272static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
3273 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003274{
3275 static char *texts[] = { "optical", "coaxial" };
3276
3277 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3278 uinfo->count = 1;
3279 uinfo->value.enumerated.items = 2;
3280
3281 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3282 uinfo->value.enumerated.item =
3283 uinfo->value.enumerated.items - 1;
3284 strcpy(uinfo->value.enumerated.name,
3285 texts[uinfo->value.enumerated.item]);
3286
3287 return 0;
3288}
3289
Takashi Iwai98274f02005-11-17 14:52:34 +01003290static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
3291 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003292{
Takashi Iwai98274f02005-11-17 14:52:34 +01003293 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003294
3295 spin_lock_irq(&hdspm->lock);
3296 ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
3297 spin_unlock_irq(&hdspm->lock);
3298 return 0;
3299}
3300
Takashi Iwai98274f02005-11-17 14:52:34 +01003301static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
3302 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003303{
Takashi Iwai98274f02005-11-17 14:52:34 +01003304 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003305 int change;
3306 unsigned int val;
3307
3308 if (!snd_hdspm_use_is_exclusive(hdspm))
3309 return -EBUSY;
3310 val = ucontrol->value.integer.value[0] & 1;
3311 spin_lock_irq(&hdspm->lock);
3312 change = (int) val != hdspm_input_select(hdspm);
3313 hdspm_set_input_select(hdspm, val);
3314 spin_unlock_irq(&hdspm->lock);
3315 return change;
3316}
3317
Adrian Knoth0dca1792011-01-26 19:32:14 +01003318
Remy Bruno3cee5a62006-10-16 12:46:32 +02003319#define HDSPM_DS_WIRE(xname, xindex) \
3320{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3321 .name = xname, \
3322 .index = xindex, \
3323 .info = snd_hdspm_info_ds_wire, \
3324 .get = snd_hdspm_get_ds_wire, \
3325 .put = snd_hdspm_put_ds_wire \
3326}
3327
3328static int hdspm_ds_wire(struct hdspm * hdspm)
3329{
3330 return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
3331}
3332
3333static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
3334{
3335 if (ds)
3336 hdspm->control_register |= HDSPM_DS_DoubleWire;
3337 else
3338 hdspm->control_register &= ~HDSPM_DS_DoubleWire;
3339 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3340
3341 return 0;
3342}
3343
3344static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
3345 struct snd_ctl_elem_info *uinfo)
3346{
3347 static char *texts[] = { "Single", "Double" };
3348
3349 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3350 uinfo->count = 1;
3351 uinfo->value.enumerated.items = 2;
3352
3353 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3354 uinfo->value.enumerated.item =
3355 uinfo->value.enumerated.items - 1;
3356 strcpy(uinfo->value.enumerated.name,
3357 texts[uinfo->value.enumerated.item]);
3358
3359 return 0;
3360}
3361
3362static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
3363 struct snd_ctl_elem_value *ucontrol)
3364{
3365 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3366
3367 spin_lock_irq(&hdspm->lock);
3368 ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
3369 spin_unlock_irq(&hdspm->lock);
3370 return 0;
3371}
3372
3373static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
3374 struct snd_ctl_elem_value *ucontrol)
3375{
3376 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3377 int change;
3378 unsigned int val;
3379
3380 if (!snd_hdspm_use_is_exclusive(hdspm))
3381 return -EBUSY;
3382 val = ucontrol->value.integer.value[0] & 1;
3383 spin_lock_irq(&hdspm->lock);
3384 change = (int) val != hdspm_ds_wire(hdspm);
3385 hdspm_set_ds_wire(hdspm, val);
3386 spin_unlock_irq(&hdspm->lock);
3387 return change;
3388}
3389
Adrian Knoth0dca1792011-01-26 19:32:14 +01003390
Remy Bruno3cee5a62006-10-16 12:46:32 +02003391#define HDSPM_QS_WIRE(xname, xindex) \
3392{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3393 .name = xname, \
3394 .index = xindex, \
3395 .info = snd_hdspm_info_qs_wire, \
3396 .get = snd_hdspm_get_qs_wire, \
3397 .put = snd_hdspm_put_qs_wire \
3398}
3399
3400static int hdspm_qs_wire(struct hdspm * hdspm)
3401{
3402 if (hdspm->control_register & HDSPM_QS_DoubleWire)
3403 return 1;
3404 if (hdspm->control_register & HDSPM_QS_QuadWire)
3405 return 2;
3406 return 0;
3407}
3408
3409static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
3410{
3411 hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
3412 switch (mode) {
3413 case 0:
3414 break;
3415 case 1:
3416 hdspm->control_register |= HDSPM_QS_DoubleWire;
3417 break;
3418 case 2:
3419 hdspm->control_register |= HDSPM_QS_QuadWire;
3420 break;
3421 }
3422 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3423
3424 return 0;
3425}
3426
3427static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
3428 struct snd_ctl_elem_info *uinfo)
3429{
3430 static char *texts[] = { "Single", "Double", "Quad" };
3431
3432 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3433 uinfo->count = 1;
3434 uinfo->value.enumerated.items = 3;
3435
3436 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3437 uinfo->value.enumerated.item =
3438 uinfo->value.enumerated.items - 1;
3439 strcpy(uinfo->value.enumerated.name,
3440 texts[uinfo->value.enumerated.item]);
3441
3442 return 0;
3443}
3444
3445static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
3446 struct snd_ctl_elem_value *ucontrol)
3447{
3448 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3449
3450 spin_lock_irq(&hdspm->lock);
3451 ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
3452 spin_unlock_irq(&hdspm->lock);
3453 return 0;
3454}
3455
3456static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
3457 struct snd_ctl_elem_value *ucontrol)
3458{
3459 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3460 int change;
3461 int val;
3462
3463 if (!snd_hdspm_use_is_exclusive(hdspm))
3464 return -EBUSY;
3465 val = ucontrol->value.integer.value[0];
3466 if (val < 0)
3467 val = 0;
3468 if (val > 2)
3469 val = 2;
3470 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003471 change = val != hdspm_qs_wire(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003472 hdspm_set_qs_wire(hdspm, val);
3473 spin_unlock_irq(&hdspm->lock);
3474 return change;
3475}
3476
Adrian Knoth700d1ef2011-07-29 03:11:02 +02003477#define HDSPM_MADI_SPEEDMODE(xname, xindex) \
3478{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3479 .name = xname, \
3480 .index = xindex, \
3481 .info = snd_hdspm_info_madi_speedmode, \
3482 .get = snd_hdspm_get_madi_speedmode, \
3483 .put = snd_hdspm_put_madi_speedmode \
3484}
3485
3486static int hdspm_madi_speedmode(struct hdspm *hdspm)
3487{
3488 if (hdspm->control_register & HDSPM_QuadSpeed)
3489 return 2;
3490 if (hdspm->control_register & HDSPM_DoubleSpeed)
3491 return 1;
3492 return 0;
3493}
3494
3495static int hdspm_set_madi_speedmode(struct hdspm *hdspm, int mode)
3496{
3497 hdspm->control_register &= ~(HDSPM_DoubleSpeed | HDSPM_QuadSpeed);
3498 switch (mode) {
3499 case 0:
3500 break;
3501 case 1:
3502 hdspm->control_register |= HDSPM_DoubleSpeed;
3503 break;
3504 case 2:
3505 hdspm->control_register |= HDSPM_QuadSpeed;
3506 break;
3507 }
3508 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3509
3510 return 0;
3511}
3512
3513static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol,
3514 struct snd_ctl_elem_info *uinfo)
3515{
3516 static char *texts[] = { "Single", "Double", "Quad" };
3517
3518 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3519 uinfo->count = 1;
3520 uinfo->value.enumerated.items = 3;
3521
3522 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3523 uinfo->value.enumerated.item =
3524 uinfo->value.enumerated.items - 1;
3525 strcpy(uinfo->value.enumerated.name,
3526 texts[uinfo->value.enumerated.item]);
3527
3528 return 0;
3529}
3530
3531static int snd_hdspm_get_madi_speedmode(struct snd_kcontrol *kcontrol,
3532 struct snd_ctl_elem_value *ucontrol)
3533{
3534 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3535
3536 spin_lock_irq(&hdspm->lock);
3537 ucontrol->value.enumerated.item[0] = hdspm_madi_speedmode(hdspm);
3538 spin_unlock_irq(&hdspm->lock);
3539 return 0;
3540}
3541
3542static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol,
3543 struct snd_ctl_elem_value *ucontrol)
3544{
3545 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3546 int change;
3547 int val;
3548
3549 if (!snd_hdspm_use_is_exclusive(hdspm))
3550 return -EBUSY;
3551 val = ucontrol->value.integer.value[0];
3552 if (val < 0)
3553 val = 0;
3554 if (val > 2)
3555 val = 2;
3556 spin_lock_irq(&hdspm->lock);
3557 change = val != hdspm_madi_speedmode(hdspm);
3558 hdspm_set_madi_speedmode(hdspm, val);
3559 spin_unlock_irq(&hdspm->lock);
3560 return change;
3561}
Takashi Iwai763f3562005-06-03 11:25:34 +02003562
3563#define HDSPM_MIXER(xname, xindex) \
3564{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
3565 .name = xname, \
3566 .index = xindex, \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003567 .device = 0, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003568 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
3569 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3570 .info = snd_hdspm_info_mixer, \
3571 .get = snd_hdspm_get_mixer, \
3572 .put = snd_hdspm_put_mixer \
3573}
3574
Takashi Iwai98274f02005-11-17 14:52:34 +01003575static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
3576 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003577{
3578 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3579 uinfo->count = 3;
3580 uinfo->value.integer.min = 0;
3581 uinfo->value.integer.max = 65535;
3582 uinfo->value.integer.step = 1;
3583 return 0;
3584}
3585
Takashi Iwai98274f02005-11-17 14:52:34 +01003586static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
3587 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003588{
Takashi Iwai98274f02005-11-17 14:52:34 +01003589 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003590 int source;
3591 int destination;
3592
3593 source = ucontrol->value.integer.value[0];
3594 if (source < 0)
3595 source = 0;
3596 else if (source >= 2 * HDSPM_MAX_CHANNELS)
3597 source = 2 * HDSPM_MAX_CHANNELS - 1;
3598
3599 destination = ucontrol->value.integer.value[1];
3600 if (destination < 0)
3601 destination = 0;
3602 else if (destination >= HDSPM_MAX_CHANNELS)
3603 destination = HDSPM_MAX_CHANNELS - 1;
3604
3605 spin_lock_irq(&hdspm->lock);
3606 if (source >= HDSPM_MAX_CHANNELS)
3607 ucontrol->value.integer.value[2] =
3608 hdspm_read_pb_gain(hdspm, destination,
3609 source - HDSPM_MAX_CHANNELS);
3610 else
3611 ucontrol->value.integer.value[2] =
3612 hdspm_read_in_gain(hdspm, destination, source);
3613
3614 spin_unlock_irq(&hdspm->lock);
3615
3616 return 0;
3617}
3618
Takashi Iwai98274f02005-11-17 14:52:34 +01003619static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
3620 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003621{
Takashi Iwai98274f02005-11-17 14:52:34 +01003622 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003623 int change;
3624 int source;
3625 int destination;
3626 int gain;
3627
3628 if (!snd_hdspm_use_is_exclusive(hdspm))
3629 return -EBUSY;
3630
3631 source = ucontrol->value.integer.value[0];
3632 destination = ucontrol->value.integer.value[1];
3633
3634 if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
3635 return -1;
3636 if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
3637 return -1;
3638
3639 gain = ucontrol->value.integer.value[2];
3640
3641 spin_lock_irq(&hdspm->lock);
3642
3643 if (source >= HDSPM_MAX_CHANNELS)
3644 change = gain != hdspm_read_pb_gain(hdspm, destination,
3645 source -
3646 HDSPM_MAX_CHANNELS);
3647 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003648 change = gain != hdspm_read_in_gain(hdspm, destination,
3649 source);
Takashi Iwai763f3562005-06-03 11:25:34 +02003650
3651 if (change) {
3652 if (source >= HDSPM_MAX_CHANNELS)
3653 hdspm_write_pb_gain(hdspm, destination,
3654 source - HDSPM_MAX_CHANNELS,
3655 gain);
3656 else
3657 hdspm_write_in_gain(hdspm, destination, source,
3658 gain);
3659 }
3660 spin_unlock_irq(&hdspm->lock);
3661
3662 return change;
3663}
3664
3665/* The simple mixer control(s) provide gain control for the
3666 basic 1:1 mappings of playback streams to output
Adrian Knoth0dca1792011-01-26 19:32:14 +01003667 streams.
Takashi Iwai763f3562005-06-03 11:25:34 +02003668*/
3669
3670#define HDSPM_PLAYBACK_MIXER \
3671{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3672 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
3673 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3674 .info = snd_hdspm_info_playback_mixer, \
3675 .get = snd_hdspm_get_playback_mixer, \
3676 .put = snd_hdspm_put_playback_mixer \
3677}
3678
Takashi Iwai98274f02005-11-17 14:52:34 +01003679static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
3680 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003681{
3682 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3683 uinfo->count = 1;
3684 uinfo->value.integer.min = 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003685 uinfo->value.integer.max = 64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003686 uinfo->value.integer.step = 1;
3687 return 0;
3688}
3689
Takashi Iwai98274f02005-11-17 14:52:34 +01003690static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
3691 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003692{
Takashi Iwai98274f02005-11-17 14:52:34 +01003693 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003694 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003695
3696 channel = ucontrol->id.index - 1;
3697
Takashi Iwaida3cec32008-08-08 17:12:14 +02003698 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3699 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003700
Takashi Iwai763f3562005-06-03 11:25:34 +02003701 spin_lock_irq(&hdspm->lock);
3702 ucontrol->value.integer.value[0] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003703 (hdspm_read_pb_gain(hdspm, channel, channel)*64)/UNITY_GAIN;
Takashi Iwai763f3562005-06-03 11:25:34 +02003704 spin_unlock_irq(&hdspm->lock);
3705
Takashi Iwai763f3562005-06-03 11:25:34 +02003706 return 0;
3707}
3708
Takashi Iwai98274f02005-11-17 14:52:34 +01003709static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
3710 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003711{
Takashi Iwai98274f02005-11-17 14:52:34 +01003712 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003713 int change;
3714 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003715 int gain;
3716
3717 if (!snd_hdspm_use_is_exclusive(hdspm))
3718 return -EBUSY;
3719
3720 channel = ucontrol->id.index - 1;
3721
Takashi Iwaida3cec32008-08-08 17:12:14 +02003722 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3723 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003724
Adrian Knoth0dca1792011-01-26 19:32:14 +01003725 gain = ucontrol->value.integer.value[0]*UNITY_GAIN/64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003726
3727 spin_lock_irq(&hdspm->lock);
3728 change =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003729 gain != hdspm_read_pb_gain(hdspm, channel,
3730 channel);
Takashi Iwai763f3562005-06-03 11:25:34 +02003731 if (change)
Adrian Knoth0dca1792011-01-26 19:32:14 +01003732 hdspm_write_pb_gain(hdspm, channel, channel,
Takashi Iwai763f3562005-06-03 11:25:34 +02003733 gain);
3734 spin_unlock_irq(&hdspm->lock);
3735 return change;
3736}
3737
Adrian Knoth0dca1792011-01-26 19:32:14 +01003738#define HDSPM_SYNC_CHECK(xname, xindex) \
3739{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3740 .name = xname, \
3741 .private_value = xindex, \
3742 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3743 .info = snd_hdspm_info_sync_check, \
3744 .get = snd_hdspm_get_sync_check \
Takashi Iwai763f3562005-06-03 11:25:34 +02003745}
3746
Adrian Knoth0dca1792011-01-26 19:32:14 +01003747
Takashi Iwai98274f02005-11-17 14:52:34 +01003748static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
3749 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003750{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003751 static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" };
Takashi Iwai763f3562005-06-03 11:25:34 +02003752 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3753 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003754 uinfo->value.enumerated.items = 4;
Takashi Iwai763f3562005-06-03 11:25:34 +02003755 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3756 uinfo->value.enumerated.item =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003757 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02003758 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01003759 texts[uinfo->value.enumerated.item]);
Takashi Iwai763f3562005-06-03 11:25:34 +02003760 return 0;
3761}
3762
Adrian Knoth0dca1792011-01-26 19:32:14 +01003763static int hdspm_wc_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003764{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003765 int status, status2;
3766
3767 switch (hdspm->io_type) {
3768 case AES32:
3769 status = hdspm_read(hdspm, HDSPM_statusRegister);
3770 if (status & HDSPM_wcSync)
Takashi Iwai763f3562005-06-03 11:25:34 +02003771 return 2;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003772 else if (status & HDSPM_wcLock)
3773 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003774 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003775 break;
3776
3777 case MADI:
3778 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003779 if (status2 & HDSPM_wcLock) {
3780 if (status2 & HDSPM_wcSync)
3781 return 2;
3782 else
3783 return 1;
3784 }
3785 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003786 break;
3787
3788 case RayDAT:
3789 case AIO:
3790 status = hdspm_read(hdspm, HDSPM_statusRegister);
3791
3792 if (status & 0x2000000)
3793 return 2;
3794 else if (status & 0x1000000)
3795 return 1;
3796 return 0;
3797
3798 break;
3799
3800 case MADIface:
3801 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02003802 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003803
Takashi Iwai763f3562005-06-03 11:25:34 +02003804
Adrian Knoth0dca1792011-01-26 19:32:14 +01003805 return 3;
Takashi Iwai763f3562005-06-03 11:25:34 +02003806}
3807
3808
Adrian Knoth0dca1792011-01-26 19:32:14 +01003809static int hdspm_madi_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003810{
3811 int status = hdspm_read(hdspm, HDSPM_statusRegister);
3812 if (status & HDSPM_madiLock) {
3813 if (status & HDSPM_madiSync)
3814 return 2;
3815 else
3816 return 1;
3817 }
3818 return 0;
3819}
3820
Adrian Knoth0dca1792011-01-26 19:32:14 +01003821
3822static int hdspm_s1_sync_check(struct hdspm *hdspm, int idx)
3823{
3824 int status, lock, sync;
3825
3826 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3827
3828 lock = (status & (0x1<<idx)) ? 1 : 0;
3829 sync = (status & (0x100<<idx)) ? 1 : 0;
3830
3831 if (lock && sync)
3832 return 2;
3833 else if (lock)
3834 return 1;
3835 return 0;
3836}
3837
3838
3839static int hdspm_sync_in_sync_check(struct hdspm *hdspm)
3840{
3841 int status, lock = 0, sync = 0;
3842
3843 switch (hdspm->io_type) {
3844 case RayDAT:
3845 case AIO:
3846 status = hdspm_read(hdspm, HDSPM_RD_STATUS_3);
3847 lock = (status & 0x400) ? 1 : 0;
3848 sync = (status & 0x800) ? 1 : 0;
3849 break;
3850
3851 case MADI:
3852 case AES32:
3853 status = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knotha7edbd52011-02-23 11:43:15 +01003854 lock = (status & HDSPM_syncInLock) ? 1 : 0;
3855 sync = (status & HDSPM_syncInSync) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003856 break;
3857
3858 case MADIface:
3859 break;
3860 }
3861
3862 if (lock && sync)
3863 return 2;
3864 else if (lock)
3865 return 1;
3866
3867 return 0;
3868}
3869
3870static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx)
3871{
3872 int status2, lock, sync;
3873 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
3874
3875 lock = (status2 & (0x0080 >> idx)) ? 1 : 0;
3876 sync = (status2 & (0x8000 >> idx)) ? 1 : 0;
3877
3878 if (sync)
3879 return 2;
3880 else if (lock)
3881 return 1;
3882 return 0;
3883}
3884
3885
3886static int hdspm_tco_sync_check(struct hdspm *hdspm)
3887{
3888 int status;
3889
3890 if (hdspm->tco) {
3891 switch (hdspm->io_type) {
3892 case MADI:
3893 case AES32:
3894 status = hdspm_read(hdspm, HDSPM_statusRegister);
3895 if (status & HDSPM_tcoLock) {
3896 if (status & HDSPM_tcoSync)
3897 return 2;
3898 else
3899 return 1;
3900 }
3901 return 0;
3902
3903 break;
3904
3905 case RayDAT:
3906 case AIO:
3907 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3908
3909 if (status & 0x8000000)
3910 return 2; /* Sync */
3911 if (status & 0x4000000)
3912 return 1; /* Lock */
3913 return 0; /* No signal */
3914 break;
3915
3916 default:
3917 break;
3918 }
3919 }
3920
3921 return 3; /* N/A */
3922}
3923
3924
3925static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
3926 struct snd_ctl_elem_value *ucontrol)
3927{
3928 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3929 int val = -1;
3930
3931 switch (hdspm->io_type) {
3932 case RayDAT:
3933 switch (kcontrol->private_value) {
3934 case 0: /* WC */
3935 val = hdspm_wc_sync_check(hdspm); break;
3936 case 7: /* TCO */
3937 val = hdspm_tco_sync_check(hdspm); break;
3938 case 8: /* SYNC IN */
3939 val = hdspm_sync_in_sync_check(hdspm); break;
3940 default:
3941 val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
3942 }
3943
3944 case AIO:
3945 switch (kcontrol->private_value) {
3946 case 0: /* WC */
3947 val = hdspm_wc_sync_check(hdspm); break;
3948 case 4: /* TCO */
3949 val = hdspm_tco_sync_check(hdspm); break;
3950 case 5: /* SYNC IN */
3951 val = hdspm_sync_in_sync_check(hdspm); break;
3952 default:
3953 val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
3954 }
3955
3956 case MADI:
3957 switch (kcontrol->private_value) {
3958 case 0: /* WC */
3959 val = hdspm_wc_sync_check(hdspm); break;
3960 case 1: /* MADI */
3961 val = hdspm_madi_sync_check(hdspm); break;
3962 case 2: /* TCO */
3963 val = hdspm_tco_sync_check(hdspm); break;
3964 case 3: /* SYNC_IN */
3965 val = hdspm_sync_in_sync_check(hdspm); break;
3966 }
3967
3968 case MADIface:
3969 val = hdspm_madi_sync_check(hdspm); /* MADI */
3970 break;
3971
3972 case AES32:
3973 switch (kcontrol->private_value) {
3974 case 0: /* WC */
3975 val = hdspm_wc_sync_check(hdspm); break;
3976 case 9: /* TCO */
3977 val = hdspm_tco_sync_check(hdspm); break;
3978 case 10 /* SYNC IN */:
3979 val = hdspm_sync_in_sync_check(hdspm); break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01003980 default: /* AES1 to AES8 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01003981 val = hdspm_aes_sync_check(hdspm,
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01003982 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003983 }
3984
3985 }
3986
3987 if (-1 == val)
3988 val = 3;
3989
3990 ucontrol->value.enumerated.item[0] = val;
3991 return 0;
3992}
3993
3994
3995
3996/**
3997 * TCO controls
3998 **/
3999static void hdspm_tco_write(struct hdspm *hdspm)
4000{
4001 unsigned int tc[4] = { 0, 0, 0, 0};
4002
4003 switch (hdspm->tco->input) {
4004 case 0:
4005 tc[2] |= HDSPM_TCO2_set_input_MSB;
4006 break;
4007 case 1:
4008 tc[2] |= HDSPM_TCO2_set_input_LSB;
4009 break;
4010 default:
4011 break;
4012 }
4013
4014 switch (hdspm->tco->framerate) {
4015 case 1:
4016 tc[1] |= HDSPM_TCO1_LTC_Format_LSB;
4017 break;
4018 case 2:
4019 tc[1] |= HDSPM_TCO1_LTC_Format_MSB;
4020 break;
4021 case 3:
4022 tc[1] |= HDSPM_TCO1_LTC_Format_MSB +
4023 HDSPM_TCO1_set_drop_frame_flag;
4024 break;
4025 case 4:
4026 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
4027 HDSPM_TCO1_LTC_Format_MSB;
4028 break;
4029 case 5:
4030 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
4031 HDSPM_TCO1_LTC_Format_MSB +
4032 HDSPM_TCO1_set_drop_frame_flag;
4033 break;
4034 default:
4035 break;
4036 }
4037
4038 switch (hdspm->tco->wordclock) {
4039 case 1:
4040 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_LSB;
4041 break;
4042 case 2:
4043 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_MSB;
4044 break;
4045 default:
4046 break;
4047 }
4048
4049 switch (hdspm->tco->samplerate) {
4050 case 1:
4051 tc[2] |= HDSPM_TCO2_set_freq;
4052 break;
4053 case 2:
4054 tc[2] |= HDSPM_TCO2_set_freq_from_app;
4055 break;
4056 default:
4057 break;
4058 }
4059
4060 switch (hdspm->tco->pull) {
4061 case 1:
4062 tc[2] |= HDSPM_TCO2_set_pull_up;
4063 break;
4064 case 2:
4065 tc[2] |= HDSPM_TCO2_set_pull_down;
4066 break;
4067 case 3:
4068 tc[2] |= HDSPM_TCO2_set_pull_up + HDSPM_TCO2_set_01_4;
4069 break;
4070 case 4:
4071 tc[2] |= HDSPM_TCO2_set_pull_down + HDSPM_TCO2_set_01_4;
4072 break;
4073 default:
4074 break;
4075 }
4076
4077 if (1 == hdspm->tco->term) {
4078 tc[2] |= HDSPM_TCO2_set_term_75R;
4079 }
4080
4081 hdspm_write(hdspm, HDSPM_WR_TCO, tc[0]);
4082 hdspm_write(hdspm, HDSPM_WR_TCO+4, tc[1]);
4083 hdspm_write(hdspm, HDSPM_WR_TCO+8, tc[2]);
4084 hdspm_write(hdspm, HDSPM_WR_TCO+12, tc[3]);
4085}
4086
4087
4088#define HDSPM_TCO_SAMPLE_RATE(xname, xindex) \
4089{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4090 .name = xname, \
4091 .index = xindex, \
4092 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4093 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4094 .info = snd_hdspm_info_tco_sample_rate, \
4095 .get = snd_hdspm_get_tco_sample_rate, \
4096 .put = snd_hdspm_put_tco_sample_rate \
4097}
4098
4099static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol,
4100 struct snd_ctl_elem_info *uinfo)
4101{
4102 static char *texts[] = { "44.1 kHz", "48 kHz" };
4103 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4104 uinfo->count = 1;
4105 uinfo->value.enumerated.items = 2;
4106
4107 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4108 uinfo->value.enumerated.item =
4109 uinfo->value.enumerated.items - 1;
4110
4111 strcpy(uinfo->value.enumerated.name,
4112 texts[uinfo->value.enumerated.item]);
4113
4114 return 0;
4115}
4116
4117static int snd_hdspm_get_tco_sample_rate(struct snd_kcontrol *kcontrol,
4118 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02004119{
Takashi Iwai98274f02005-11-17 14:52:34 +01004120 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02004121
Adrian Knoth0dca1792011-01-26 19:32:14 +01004122 ucontrol->value.enumerated.item[0] = hdspm->tco->samplerate;
4123
Takashi Iwai763f3562005-06-03 11:25:34 +02004124 return 0;
4125}
4126
Adrian Knoth0dca1792011-01-26 19:32:14 +01004127static int snd_hdspm_put_tco_sample_rate(struct snd_kcontrol *kcontrol,
4128 struct snd_ctl_elem_value *ucontrol)
Remy Bruno3cee5a62006-10-16 12:46:32 +02004129{
Adrian Knoth0dca1792011-01-26 19:32:14 +01004130 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4131
4132 if (hdspm->tco->samplerate != ucontrol->value.enumerated.item[0]) {
4133 hdspm->tco->samplerate = ucontrol->value.enumerated.item[0];
4134
4135 hdspm_tco_write(hdspm);
4136
4137 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004138 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01004139
Remy Bruno3cee5a62006-10-16 12:46:32 +02004140 return 0;
4141}
4142
Adrian Knoth0dca1792011-01-26 19:32:14 +01004143
4144#define HDSPM_TCO_PULL(xname, xindex) \
4145{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4146 .name = xname, \
4147 .index = xindex, \
4148 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4149 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4150 .info = snd_hdspm_info_tco_pull, \
4151 .get = snd_hdspm_get_tco_pull, \
4152 .put = snd_hdspm_put_tco_pull \
4153}
4154
4155static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol,
4156 struct snd_ctl_elem_info *uinfo)
4157{
4158 static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" };
4159 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4160 uinfo->count = 1;
4161 uinfo->value.enumerated.items = 5;
4162
4163 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4164 uinfo->value.enumerated.item =
4165 uinfo->value.enumerated.items - 1;
4166
4167 strcpy(uinfo->value.enumerated.name,
4168 texts[uinfo->value.enumerated.item]);
4169
4170 return 0;
4171}
4172
4173static int snd_hdspm_get_tco_pull(struct snd_kcontrol *kcontrol,
4174 struct snd_ctl_elem_value *ucontrol)
4175{
4176 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4177
4178 ucontrol->value.enumerated.item[0] = hdspm->tco->pull;
4179
4180 return 0;
4181}
4182
4183static int snd_hdspm_put_tco_pull(struct snd_kcontrol *kcontrol,
4184 struct snd_ctl_elem_value *ucontrol)
4185{
4186 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4187
4188 if (hdspm->tco->pull != ucontrol->value.enumerated.item[0]) {
4189 hdspm->tco->pull = ucontrol->value.enumerated.item[0];
4190
4191 hdspm_tco_write(hdspm);
4192
4193 return 1;
4194 }
4195
4196 return 0;
4197}
4198
4199#define HDSPM_TCO_WCK_CONVERSION(xname, xindex) \
4200{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4201 .name = xname, \
4202 .index = xindex, \
4203 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4204 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4205 .info = snd_hdspm_info_tco_wck_conversion, \
4206 .get = snd_hdspm_get_tco_wck_conversion, \
4207 .put = snd_hdspm_put_tco_wck_conversion \
4208}
4209
4210static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4211 struct snd_ctl_elem_info *uinfo)
4212{
4213 static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
4214 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4215 uinfo->count = 1;
4216 uinfo->value.enumerated.items = 3;
4217
4218 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4219 uinfo->value.enumerated.item =
4220 uinfo->value.enumerated.items - 1;
4221
4222 strcpy(uinfo->value.enumerated.name,
4223 texts[uinfo->value.enumerated.item]);
4224
4225 return 0;
4226}
4227
4228static int snd_hdspm_get_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4229 struct snd_ctl_elem_value *ucontrol)
4230{
4231 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4232
4233 ucontrol->value.enumerated.item[0] = hdspm->tco->wordclock;
4234
4235 return 0;
4236}
4237
4238static int snd_hdspm_put_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4239 struct snd_ctl_elem_value *ucontrol)
4240{
4241 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4242
4243 if (hdspm->tco->wordclock != ucontrol->value.enumerated.item[0]) {
4244 hdspm->tco->wordclock = ucontrol->value.enumerated.item[0];
4245
4246 hdspm_tco_write(hdspm);
4247
4248 return 1;
4249 }
4250
4251 return 0;
4252}
4253
4254
4255#define HDSPM_TCO_FRAME_RATE(xname, xindex) \
4256{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4257 .name = xname, \
4258 .index = xindex, \
4259 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4260 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4261 .info = snd_hdspm_info_tco_frame_rate, \
4262 .get = snd_hdspm_get_tco_frame_rate, \
4263 .put = snd_hdspm_put_tco_frame_rate \
4264}
4265
4266static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol,
4267 struct snd_ctl_elem_info *uinfo)
4268{
4269 static char *texts[] = { "24 fps", "25 fps", "29.97fps",
4270 "29.97 dfps", "30 fps", "30 dfps" };
4271 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4272 uinfo->count = 1;
4273 uinfo->value.enumerated.items = 6;
4274
4275 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4276 uinfo->value.enumerated.item =
4277 uinfo->value.enumerated.items - 1;
4278
4279 strcpy(uinfo->value.enumerated.name,
4280 texts[uinfo->value.enumerated.item]);
4281
4282 return 0;
4283}
4284
4285static int snd_hdspm_get_tco_frame_rate(struct snd_kcontrol *kcontrol,
Remy Bruno3cee5a62006-10-16 12:46:32 +02004286 struct snd_ctl_elem_value *ucontrol)
4287{
Remy Bruno3cee5a62006-10-16 12:46:32 +02004288 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4289
Adrian Knoth0dca1792011-01-26 19:32:14 +01004290 ucontrol->value.enumerated.item[0] = hdspm->tco->framerate;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004291
Remy Bruno3cee5a62006-10-16 12:46:32 +02004292 return 0;
4293}
Takashi Iwai763f3562005-06-03 11:25:34 +02004294
Adrian Knoth0dca1792011-01-26 19:32:14 +01004295static int snd_hdspm_put_tco_frame_rate(struct snd_kcontrol *kcontrol,
4296 struct snd_ctl_elem_value *ucontrol)
4297{
4298 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4299
4300 if (hdspm->tco->framerate != ucontrol->value.enumerated.item[0]) {
4301 hdspm->tco->framerate = ucontrol->value.enumerated.item[0];
4302
4303 hdspm_tco_write(hdspm);
4304
4305 return 1;
4306 }
4307
4308 return 0;
4309}
4310
4311
4312#define HDSPM_TCO_SYNC_SOURCE(xname, xindex) \
4313{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4314 .name = xname, \
4315 .index = xindex, \
4316 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4317 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4318 .info = snd_hdspm_info_tco_sync_source, \
4319 .get = snd_hdspm_get_tco_sync_source, \
4320 .put = snd_hdspm_put_tco_sync_source \
4321}
4322
4323static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol,
4324 struct snd_ctl_elem_info *uinfo)
4325{
4326 static char *texts[] = { "LTC", "Video", "WCK" };
4327 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4328 uinfo->count = 1;
4329 uinfo->value.enumerated.items = 3;
4330
4331 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4332 uinfo->value.enumerated.item =
4333 uinfo->value.enumerated.items - 1;
4334
4335 strcpy(uinfo->value.enumerated.name,
4336 texts[uinfo->value.enumerated.item]);
4337
4338 return 0;
4339}
4340
4341static int snd_hdspm_get_tco_sync_source(struct snd_kcontrol *kcontrol,
4342 struct snd_ctl_elem_value *ucontrol)
4343{
4344 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4345
4346 ucontrol->value.enumerated.item[0] = hdspm->tco->input;
4347
4348 return 0;
4349}
4350
4351static int snd_hdspm_put_tco_sync_source(struct snd_kcontrol *kcontrol,
4352 struct snd_ctl_elem_value *ucontrol)
4353{
4354 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4355
4356 if (hdspm->tco->input != ucontrol->value.enumerated.item[0]) {
4357 hdspm->tco->input = ucontrol->value.enumerated.item[0];
4358
4359 hdspm_tco_write(hdspm);
4360
4361 return 1;
4362 }
4363
4364 return 0;
4365}
4366
4367
4368#define HDSPM_TCO_WORD_TERM(xname, xindex) \
4369{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4370 .name = xname, \
4371 .index = xindex, \
4372 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4373 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4374 .info = snd_hdspm_info_tco_word_term, \
4375 .get = snd_hdspm_get_tco_word_term, \
4376 .put = snd_hdspm_put_tco_word_term \
4377}
4378
4379static int snd_hdspm_info_tco_word_term(struct snd_kcontrol *kcontrol,
4380 struct snd_ctl_elem_info *uinfo)
4381{
4382 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
4383 uinfo->count = 1;
4384 uinfo->value.integer.min = 0;
4385 uinfo->value.integer.max = 1;
4386
4387 return 0;
4388}
4389
4390
4391static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol,
4392 struct snd_ctl_elem_value *ucontrol)
4393{
4394 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4395
4396 ucontrol->value.enumerated.item[0] = hdspm->tco->term;
4397
4398 return 0;
4399}
4400
4401
4402static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol,
4403 struct snd_ctl_elem_value *ucontrol)
4404{
4405 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4406
4407 if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) {
4408 hdspm->tco->term = ucontrol->value.enumerated.item[0];
4409
4410 hdspm_tco_write(hdspm);
4411
4412 return 1;
4413 }
4414
4415 return 0;
4416}
4417
4418
4419
Takashi Iwai763f3562005-06-03 11:25:34 +02004420
Remy Bruno3cee5a62006-10-16 12:46:32 +02004421static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004422 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004423 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Takashi Iwai763f3562005-06-03 11:25:34 +02004424 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4425 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4426 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4427 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004428 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4429 HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
4430 HDSPM_SYNC_CHECK("TCO SyncCHeck", 2),
4431 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
Takashi Iwai763f3562005-06-03 11:25:34 +02004432 HDSPM_LINE_OUT("Line Out", 0),
4433 HDSPM_TX_64("TX 64 channels mode", 0),
4434 HDSPM_C_TMS("Clear Track Marker", 0),
4435 HDSPM_SAFE_MODE("Safe Mode", 0),
Adrian Knoth700d1ef2011-07-29 03:11:02 +02004436 HDSPM_INPUT_SELECT("Input Select", 0),
4437 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004438};
4439
4440
4441static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
4442 HDSPM_MIXER("Mixer", 0),
4443 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4444 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4445 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4446 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4447 HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
4448 HDSPM_TX_64("TX 64 channels mode", 0),
4449 HDSPM_C_TMS("Clear Track Marker", 0),
Adrian Knoth700d1ef2011-07-29 03:11:02 +02004450 HDSPM_SAFE_MODE("Safe Mode", 0),
4451 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004452};
4453
Adrian Knoth0dca1792011-01-26 19:32:14 +01004454static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004455 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004456 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004457 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4458 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4459 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4460 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004461 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004462 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4463 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4464 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4465 HDSPM_SYNC_CHECK("ADAT SyncCheck", 3),
4466 HDSPM_SYNC_CHECK("TCO SyncCheck", 4),
4467 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 5),
4468 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4469 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4470 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4471 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT Frequency", 3),
4472 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 4),
4473 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5)
4474
4475 /*
4476 HDSPM_INPUT_SELECT("Input Select", 0),
4477 HDSPM_SPDIF_OPTICAL("SPDIF Out Optical", 0),
4478 HDSPM_PROFESSIONAL("SPDIF Out Professional", 0);
4479 HDSPM_SPDIF_IN("SPDIF In", 0);
4480 HDSPM_BREAKOUT_CABLE("Breakout Cable", 0);
4481 HDSPM_INPUT_LEVEL("Input Level", 0);
4482 HDSPM_OUTPUT_LEVEL("Output Level", 0);
4483 HDSPM_PHONES("Phones", 0);
4484 */
4485};
4486
4487static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = {
4488 HDSPM_MIXER("Mixer", 0),
4489 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4490 HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0),
4491 HDSPM_PREF_SYNC_REF("Pref Sync Ref", 0),
4492 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4493 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4494 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4495 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4496 HDSPM_SYNC_CHECK("ADAT1 SyncCheck", 3),
4497 HDSPM_SYNC_CHECK("ADAT2 SyncCheck", 4),
4498 HDSPM_SYNC_CHECK("ADAT3 SyncCheck", 5),
4499 HDSPM_SYNC_CHECK("ADAT4 SyncCheck", 6),
4500 HDSPM_SYNC_CHECK("TCO SyncCheck", 7),
4501 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 8),
4502 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4503 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4504 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4505 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT1 Frequency", 3),
4506 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT2 Frequency", 4),
4507 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT3 Frequency", 5),
4508 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT4 Frequency", 6),
4509 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 7),
4510 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8)
4511};
4512
4513static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
4514 HDSPM_MIXER("Mixer", 0),
4515 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4516 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4517 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4518 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4519 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4520 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4521 HDSPM_SYNC_CHECK("WC Sync Check", 0),
4522 HDSPM_SYNC_CHECK("AES1 Sync Check", 1),
4523 HDSPM_SYNC_CHECK("AES2 Sync Check", 2),
4524 HDSPM_SYNC_CHECK("AES3 Sync Check", 3),
4525 HDSPM_SYNC_CHECK("AES4 Sync Check", 4),
4526 HDSPM_SYNC_CHECK("AES5 Sync Check", 5),
4527 HDSPM_SYNC_CHECK("AES6 Sync Check", 6),
4528 HDSPM_SYNC_CHECK("AES7 Sync Check", 7),
4529 HDSPM_SYNC_CHECK("AES8 Sync Check", 8),
4530 HDSPM_SYNC_CHECK("TCO Sync Check", 9),
4531 HDSPM_SYNC_CHECK("SYNC IN Sync Check", 10),
4532 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4533 HDSPM_AUTOSYNC_SAMPLE_RATE("AES1 Frequency", 1),
4534 HDSPM_AUTOSYNC_SAMPLE_RATE("AES2 Frequency", 2),
4535 HDSPM_AUTOSYNC_SAMPLE_RATE("AES3 Frequency", 3),
4536 HDSPM_AUTOSYNC_SAMPLE_RATE("AES4 Frequency", 4),
4537 HDSPM_AUTOSYNC_SAMPLE_RATE("AES5 Frequency", 5),
4538 HDSPM_AUTOSYNC_SAMPLE_RATE("AES6 Frequency", 6),
4539 HDSPM_AUTOSYNC_SAMPLE_RATE("AES7 Frequency", 7),
4540 HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8),
4541 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9),
4542 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004543 HDSPM_LINE_OUT("Line Out", 0),
4544 HDSPM_EMPHASIS("Emphasis", 0),
4545 HDSPM_DOLBY("Non Audio", 0),
4546 HDSPM_PROFESSIONAL("Professional", 0),
4547 HDSPM_C_TMS("Clear Track Marker", 0),
4548 HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
4549 HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
4550};
4551
Adrian Knoth0dca1792011-01-26 19:32:14 +01004552
4553
4554/* Control elements for the optional TCO module */
4555static struct snd_kcontrol_new snd_hdspm_controls_tco[] = {
4556 HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0),
4557 HDSPM_TCO_PULL("TCO Pull", 0),
4558 HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0),
4559 HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0),
4560 HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0),
4561 HDSPM_TCO_WORD_TERM("TCO Word Term", 0)
4562};
4563
4564
Takashi Iwai98274f02005-11-17 14:52:34 +01004565static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
Takashi Iwai763f3562005-06-03 11:25:34 +02004566
4567
Takashi Iwai98274f02005-11-17 14:52:34 +01004568static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004569{
4570 int i;
4571
Adrian Knoth0dca1792011-01-26 19:32:14 +01004572 for (i = hdspm->ds_out_channels; i < hdspm->ss_out_channels; ++i) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004573 if (hdspm->system_sample_rate > 48000) {
4574 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004575 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
4576 SNDRV_CTL_ELEM_ACCESS_READ |
4577 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004578 } else {
4579 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004580 SNDRV_CTL_ELEM_ACCESS_READWRITE |
4581 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004582 }
4583 snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
Adrian Knoth0dca1792011-01-26 19:32:14 +01004584 SNDRV_CTL_EVENT_MASK_INFO,
4585 &hdspm->playback_mixer_ctls[i]->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02004586 }
4587
4588 return 0;
4589}
4590
4591
Adrian Knoth0dca1792011-01-26 19:32:14 +01004592static int snd_hdspm_create_controls(struct snd_card *card,
4593 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004594{
4595 unsigned int idx, limit;
4596 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01004597 struct snd_kcontrol *kctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004598 struct snd_kcontrol_new *list = NULL;
Takashi Iwai763f3562005-06-03 11:25:34 +02004599
Adrian Knoth0dca1792011-01-26 19:32:14 +01004600 switch (hdspm->io_type) {
4601 case MADI:
4602 list = snd_hdspm_controls_madi;
4603 limit = ARRAY_SIZE(snd_hdspm_controls_madi);
4604 break;
4605 case MADIface:
4606 list = snd_hdspm_controls_madiface;
4607 limit = ARRAY_SIZE(snd_hdspm_controls_madiface);
4608 break;
4609 case AIO:
4610 list = snd_hdspm_controls_aio;
4611 limit = ARRAY_SIZE(snd_hdspm_controls_aio);
4612 break;
4613 case RayDAT:
4614 list = snd_hdspm_controls_raydat;
4615 limit = ARRAY_SIZE(snd_hdspm_controls_raydat);
4616 break;
4617 case AES32:
4618 list = snd_hdspm_controls_aes32;
4619 limit = ARRAY_SIZE(snd_hdspm_controls_aes32);
4620 break;
4621 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004622
Adrian Knoth0dca1792011-01-26 19:32:14 +01004623 if (NULL != list) {
4624 for (idx = 0; idx < limit; idx++) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004625 err = snd_ctl_add(card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004626 snd_ctl_new1(&list[idx], hdspm));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004627 if (err < 0)
4628 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004629 }
4630 }
4631
Takashi Iwai763f3562005-06-03 11:25:34 +02004632
Adrian Knoth0dca1792011-01-26 19:32:14 +01004633 /* create simple 1:1 playback mixer controls */
Takashi Iwai763f3562005-06-03 11:25:34 +02004634 snd_hdspm_playback_mixer.name = "Chn";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004635 if (hdspm->system_sample_rate >= 128000) {
4636 limit = hdspm->qs_out_channels;
4637 } else if (hdspm->system_sample_rate >= 64000) {
4638 limit = hdspm->ds_out_channels;
4639 } else {
4640 limit = hdspm->ss_out_channels;
4641 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004642 for (idx = 0; idx < limit; ++idx) {
4643 snd_hdspm_playback_mixer.index = idx + 1;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004644 kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm);
4645 err = snd_ctl_add(card, kctl);
4646 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004647 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004648 hdspm->playback_mixer_ctls[idx] = kctl;
4649 }
4650
Adrian Knoth0dca1792011-01-26 19:32:14 +01004651
4652 if (hdspm->tco) {
4653 /* add tco control elements */
4654 list = snd_hdspm_controls_tco;
4655 limit = ARRAY_SIZE(snd_hdspm_controls_tco);
4656 for (idx = 0; idx < limit; idx++) {
4657 err = snd_ctl_add(card,
4658 snd_ctl_new1(&list[idx], hdspm));
4659 if (err < 0)
4660 return err;
4661 }
4662 }
4663
Takashi Iwai763f3562005-06-03 11:25:34 +02004664 return 0;
4665}
4666
4667/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01004668 /proc interface
Takashi Iwai763f3562005-06-03 11:25:34 +02004669 ------------------------------------------------------------*/
4670
4671static void
Remy Bruno3cee5a62006-10-16 12:46:32 +02004672snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
4673 struct snd_info_buffer *buffer)
Takashi Iwai763f3562005-06-03 11:25:34 +02004674{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004675 struct hdspm *hdspm = entry->private_data;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004676 unsigned int status, status2, control, freq;
4677
Takashi Iwai763f3562005-06-03 11:25:34 +02004678 char *pref_sync_ref;
4679 char *autosync_ref;
4680 char *system_clock_mode;
Takashi Iwai763f3562005-06-03 11:25:34 +02004681 char *insel;
Takashi Iwai763f3562005-06-03 11:25:34 +02004682 int x, x2;
4683
Adrian Knoth0dca1792011-01-26 19:32:14 +01004684 /* TCO stuff */
4685 int a, ltc, frames, seconds, minutes, hours;
4686 unsigned int period;
4687 u64 freq_const = 0;
4688 u32 rate;
4689
Takashi Iwai763f3562005-06-03 11:25:34 +02004690 status = hdspm_read(hdspm, HDSPM_statusRegister);
4691 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004692 control = hdspm->control_register;
4693 freq = hdspm_read(hdspm, HDSPM_timecodeRegister);
Takashi Iwai763f3562005-06-03 11:25:34 +02004694
4695 snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004696 hdspm->card_name, hdspm->card->number + 1,
4697 hdspm->firmware_rev,
4698 (status2 & HDSPM_version0) |
4699 (status2 & HDSPM_version1) | (status2 &
4700 HDSPM_version2));
4701
4702 snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n",
4703 (hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF,
4704 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF);
Takashi Iwai763f3562005-06-03 11:25:34 +02004705
4706 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004707 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
Takashi Iwai763f3562005-06-03 11:25:34 +02004708
4709 snd_iprintf(buffer, "--- System ---\n");
4710
4711 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004712 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4713 status & HDSPM_audioIRQPending,
4714 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4715 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4716 hdspm->irq_count);
Takashi Iwai763f3562005-06-03 11:25:34 +02004717 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004718 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4719 "estimated= %ld (bytes)\n",
4720 ((status & HDSPM_BufferID) ? 1 : 0),
4721 (status & HDSPM_BufferPositionMask),
4722 (status & HDSPM_BufferPositionMask) %
4723 (2 * (int)hdspm->period_bytes),
4724 ((status & HDSPM_BufferPositionMask) - 64) %
4725 (2 * (int)hdspm->period_bytes),
4726 (long) hdspm_hw_pointer(hdspm) * 4);
Takashi Iwai763f3562005-06-03 11:25:34 +02004727
4728 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004729 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4730 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4731 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4732 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4733 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
Takashi Iwai763f3562005-06-03 11:25:34 +02004734 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004735 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4736 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4737 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4738 snd_iprintf(buffer,
4739 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4740 "status2=0x%x\n",
4741 hdspm->control_register, hdspm->control2_register,
4742 status, status2);
4743 if (status & HDSPM_tco_detect) {
4744 snd_iprintf(buffer, "TCO module detected.\n");
4745 a = hdspm_read(hdspm, HDSPM_RD_TCO+4);
4746 if (a & HDSPM_TCO1_LTC_Input_valid) {
4747 snd_iprintf(buffer, " LTC valid, ");
4748 switch (a & (HDSPM_TCO1_LTC_Format_LSB |
4749 HDSPM_TCO1_LTC_Format_MSB)) {
4750 case 0:
4751 snd_iprintf(buffer, "24 fps, ");
4752 break;
4753 case HDSPM_TCO1_LTC_Format_LSB:
4754 snd_iprintf(buffer, "25 fps, ");
4755 break;
4756 case HDSPM_TCO1_LTC_Format_MSB:
4757 snd_iprintf(buffer, "29.97 fps, ");
4758 break;
4759 default:
4760 snd_iprintf(buffer, "30 fps, ");
4761 break;
4762 }
4763 if (a & HDSPM_TCO1_set_drop_frame_flag) {
4764 snd_iprintf(buffer, "drop frame\n");
4765 } else {
4766 snd_iprintf(buffer, "full frame\n");
4767 }
4768 } else {
4769 snd_iprintf(buffer, " no LTC\n");
4770 }
4771 if (a & HDSPM_TCO1_Video_Input_Format_NTSC) {
4772 snd_iprintf(buffer, " Video: NTSC\n");
4773 } else if (a & HDSPM_TCO1_Video_Input_Format_PAL) {
4774 snd_iprintf(buffer, " Video: PAL\n");
4775 } else {
4776 snd_iprintf(buffer, " No video\n");
4777 }
4778 if (a & HDSPM_TCO1_TCO_lock) {
4779 snd_iprintf(buffer, " Sync: lock\n");
4780 } else {
4781 snd_iprintf(buffer, " Sync: no lock\n");
4782 }
4783
4784 switch (hdspm->io_type) {
4785 case MADI:
4786 case AES32:
4787 freq_const = 110069313433624ULL;
4788 break;
4789 case RayDAT:
4790 case AIO:
4791 freq_const = 104857600000000ULL;
4792 break;
4793 case MADIface:
4794 break; /* no TCO possible */
4795 }
4796
4797 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
4798 snd_iprintf(buffer, " period: %u\n", period);
4799
4800
4801 /* rate = freq_const/period; */
4802 rate = div_u64(freq_const, period);
4803
4804 if (control & HDSPM_QuadSpeed) {
4805 rate *= 4;
4806 } else if (control & HDSPM_DoubleSpeed) {
4807 rate *= 2;
4808 }
4809
4810 snd_iprintf(buffer, " Frequency: %u Hz\n",
4811 (unsigned int) rate);
4812
4813 ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
4814 frames = ltc & 0xF;
4815 ltc >>= 4;
4816 frames += (ltc & 0x3) * 10;
4817 ltc >>= 4;
4818 seconds = ltc & 0xF;
4819 ltc >>= 4;
4820 seconds += (ltc & 0x7) * 10;
4821 ltc >>= 4;
4822 minutes = ltc & 0xF;
4823 ltc >>= 4;
4824 minutes += (ltc & 0x7) * 10;
4825 ltc >>= 4;
4826 hours = ltc & 0xF;
4827 ltc >>= 4;
4828 hours += (ltc & 0x3) * 10;
4829 snd_iprintf(buffer,
4830 " LTC In: %02d:%02d:%02d:%02d\n",
4831 hours, minutes, seconds, frames);
4832
4833 } else {
4834 snd_iprintf(buffer, "No TCO module detected.\n");
4835 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004836
4837 snd_iprintf(buffer, "--- Settings ---\n");
4838
Adrian Knoth7cb155f2011-08-15 00:22:53 +02004839 x = hdspm_get_latency(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02004840
4841 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004842 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4843 x, (unsigned long) hdspm->period_bytes);
Takashi Iwai763f3562005-06-03 11:25:34 +02004844
Adrian Knoth0dca1792011-01-26 19:32:14 +01004845 snd_iprintf(buffer, "Line out: %s\n",
4846 (hdspm->control_register & HDSPM_LineOut) ? "on " : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004847
4848 switch (hdspm->control_register & HDSPM_InputMask) {
4849 case HDSPM_InputOptical:
4850 insel = "Optical";
4851 break;
4852 case HDSPM_InputCoaxial:
4853 insel = "Coaxial";
4854 break;
4855 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01004856 insel = "Unkown";
Takashi Iwai763f3562005-06-03 11:25:34 +02004857 }
4858
Takashi Iwai763f3562005-06-03 11:25:34 +02004859 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004860 "ClearTrackMarker = %s, Transmit in %s Channel Mode, "
4861 "Auto Input %s\n",
4862 (hdspm->control_register & HDSPM_clr_tms) ? "on" : "off",
4863 (hdspm->control_register & HDSPM_TX_64ch) ? "64" : "56",
4864 (hdspm->control_register & HDSPM_AutoInp) ? "on" : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004865
Adrian Knoth0dca1792011-01-26 19:32:14 +01004866
Remy Bruno3cee5a62006-10-16 12:46:32 +02004867 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
Adrian Knoth0dca1792011-01-26 19:32:14 +01004868 system_clock_mode = "AutoSync";
Remy Bruno3cee5a62006-10-16 12:46:32 +02004869 else
Takashi Iwai763f3562005-06-03 11:25:34 +02004870 system_clock_mode = "Master";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004871 snd_iprintf(buffer, "AutoSync Reference: %s\n", system_clock_mode);
Takashi Iwai763f3562005-06-03 11:25:34 +02004872
4873 switch (hdspm_pref_sync_ref(hdspm)) {
4874 case HDSPM_SYNC_FROM_WORD:
4875 pref_sync_ref = "Word Clock";
4876 break;
4877 case HDSPM_SYNC_FROM_MADI:
4878 pref_sync_ref = "MADI Sync";
4879 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004880 case HDSPM_SYNC_FROM_TCO:
4881 pref_sync_ref = "TCO";
4882 break;
4883 case HDSPM_SYNC_FROM_SYNC_IN:
4884 pref_sync_ref = "Sync In";
4885 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004886 default:
4887 pref_sync_ref = "XXXX Clock";
4888 break;
4889 }
4890 snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004891 pref_sync_ref);
Takashi Iwai763f3562005-06-03 11:25:34 +02004892
4893 snd_iprintf(buffer, "System Clock Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004894 hdspm->system_sample_rate);
Takashi Iwai763f3562005-06-03 11:25:34 +02004895
4896
4897 snd_iprintf(buffer, "--- Status:\n");
4898
4899 x = status & HDSPM_madiSync;
4900 x2 = status2 & HDSPM_wcSync;
4901
4902 snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004903 (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
4904 "NoLock",
4905 (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
4906 "NoLock");
Takashi Iwai763f3562005-06-03 11:25:34 +02004907
4908 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004909 case HDSPM_AUTOSYNC_FROM_SYNC_IN:
4910 autosync_ref = "Sync In";
4911 break;
4912 case HDSPM_AUTOSYNC_FROM_TCO:
4913 autosync_ref = "TCO";
4914 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004915 case HDSPM_AUTOSYNC_FROM_WORD:
4916 autosync_ref = "Word Clock";
4917 break;
4918 case HDSPM_AUTOSYNC_FROM_MADI:
4919 autosync_ref = "MADI Sync";
4920 break;
4921 case HDSPM_AUTOSYNC_FROM_NONE:
4922 autosync_ref = "Input not valid";
4923 break;
4924 default:
4925 autosync_ref = "---";
4926 break;
4927 }
4928 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004929 "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
4930 autosync_ref, hdspm_external_sample_rate(hdspm),
4931 (status & HDSPM_madiFreqMask) >> 22,
4932 (status2 & HDSPM_wcFreqMask) >> 5);
Takashi Iwai763f3562005-06-03 11:25:34 +02004933
4934 snd_iprintf(buffer, "Input: %s, Mode=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004935 (status & HDSPM_AB_int) ? "Coax" : "Optical",
4936 (status & HDSPM_RX_64ch) ? "64 channels" :
4937 "56 channels");
Takashi Iwai763f3562005-06-03 11:25:34 +02004938
4939 snd_iprintf(buffer, "\n");
4940}
4941
Remy Bruno3cee5a62006-10-16 12:46:32 +02004942static void
4943snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
4944 struct snd_info_buffer *buffer)
4945{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004946 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004947 unsigned int status;
4948 unsigned int status2;
4949 unsigned int timecode;
4950 int pref_syncref;
4951 char *autosync_ref;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004952 int x;
4953
4954 status = hdspm_read(hdspm, HDSPM_statusRegister);
4955 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
4956 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
4957
4958 snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
4959 hdspm->card_name, hdspm->card->number + 1,
4960 hdspm->firmware_rev);
4961
4962 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
4963 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
4964
4965 snd_iprintf(buffer, "--- System ---\n");
4966
4967 snd_iprintf(buffer,
4968 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4969 status & HDSPM_audioIRQPending,
4970 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4971 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4972 hdspm->irq_count);
4973 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004974 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4975 "estimated= %ld (bytes)\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004976 ((status & HDSPM_BufferID) ? 1 : 0),
4977 (status & HDSPM_BufferPositionMask),
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004978 (status & HDSPM_BufferPositionMask) %
4979 (2 * (int)hdspm->period_bytes),
4980 ((status & HDSPM_BufferPositionMask) - 64) %
4981 (2 * (int)hdspm->period_bytes),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004982 (long) hdspm_hw_pointer(hdspm) * 4);
4983
4984 snd_iprintf(buffer,
4985 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4986 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4987 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4988 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4989 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
4990 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004991 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4992 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4993 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4994 snd_iprintf(buffer,
4995 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4996 "status2=0x%x\n",
4997 hdspm->control_register, hdspm->control2_register,
4998 status, status2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02004999
5000 snd_iprintf(buffer, "--- Settings ---\n");
5001
Adrian Knoth7cb155f2011-08-15 00:22:53 +02005002 x = hdspm_get_latency(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02005003
5004 snd_iprintf(buffer,
5005 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
5006 x, (unsigned long) hdspm->period_bytes);
5007
Adrian Knoth0dca1792011-01-26 19:32:14 +01005008 snd_iprintf(buffer, "Line out: %s\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005009 (hdspm->
Adrian Knoth0dca1792011-01-26 19:32:14 +01005010 control_register & HDSPM_LineOut) ? "on " : "off");
Remy Bruno3cee5a62006-10-16 12:46:32 +02005011
5012 snd_iprintf(buffer,
5013 "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
5014 (hdspm->
5015 control_register & HDSPM_clr_tms) ? "on" : "off",
5016 (hdspm->
5017 control_register & HDSPM_Emphasis) ? "on" : "off",
5018 (hdspm->
5019 control_register & HDSPM_Dolby) ? "on" : "off");
5020
Remy Bruno3cee5a62006-10-16 12:46:32 +02005021
5022 pref_syncref = hdspm_pref_sync_ref(hdspm);
5023 if (pref_syncref == 0)
5024 snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
5025 else
5026 snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
5027 pref_syncref);
5028
5029 snd_iprintf(buffer, "System Clock Frequency: %d\n",
5030 hdspm->system_sample_rate);
5031
5032 snd_iprintf(buffer, "Double speed: %s\n",
5033 hdspm->control_register & HDSPM_DS_DoubleWire?
5034 "Double wire" : "Single wire");
5035 snd_iprintf(buffer, "Quad speed: %s\n",
5036 hdspm->control_register & HDSPM_QS_DoubleWire?
5037 "Double wire" :
5038 hdspm->control_register & HDSPM_QS_QuadWire?
5039 "Quad wire" : "Single wire");
5040
5041 snd_iprintf(buffer, "--- Status:\n");
5042
5043 snd_iprintf(buffer, "Word: %s Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01005044 (status & HDSPM_AES32_wcLock) ? "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005045 HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02005046
5047 for (x = 0; x < 8; x++) {
5048 snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005049 x+1,
5050 (status2 & (HDSPM_LockAES >> x)) ?
Adrian Knoth0dca1792011-01-26 19:32:14 +01005051 "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005052 HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02005053 }
5054
5055 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005056 case HDSPM_AES32_AUTOSYNC_FROM_NONE:
5057 autosync_ref = "None"; break;
5058 case HDSPM_AES32_AUTOSYNC_FROM_WORD:
5059 autosync_ref = "Word Clock"; break;
5060 case HDSPM_AES32_AUTOSYNC_FROM_AES1:
5061 autosync_ref = "AES1"; break;
5062 case HDSPM_AES32_AUTOSYNC_FROM_AES2:
5063 autosync_ref = "AES2"; break;
5064 case HDSPM_AES32_AUTOSYNC_FROM_AES3:
5065 autosync_ref = "AES3"; break;
5066 case HDSPM_AES32_AUTOSYNC_FROM_AES4:
5067 autosync_ref = "AES4"; break;
5068 case HDSPM_AES32_AUTOSYNC_FROM_AES5:
5069 autosync_ref = "AES5"; break;
5070 case HDSPM_AES32_AUTOSYNC_FROM_AES6:
5071 autosync_ref = "AES6"; break;
5072 case HDSPM_AES32_AUTOSYNC_FROM_AES7:
5073 autosync_ref = "AES7"; break;
5074 case HDSPM_AES32_AUTOSYNC_FROM_AES8:
5075 autosync_ref = "AES8"; break;
5076 default:
5077 autosync_ref = "---"; break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005078 }
5079 snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
5080
5081 snd_iprintf(buffer, "\n");
5082}
5083
Adrian Knoth0dca1792011-01-26 19:32:14 +01005084static void
5085snd_hdspm_proc_read_raydat(struct snd_info_entry *entry,
5086 struct snd_info_buffer *buffer)
5087{
5088 struct hdspm *hdspm = entry->private_data;
5089 unsigned int status1, status2, status3, control, i;
5090 unsigned int lock, sync;
5091
5092 status1 = hdspm_read(hdspm, HDSPM_RD_STATUS_1); /* s1 */
5093 status2 = hdspm_read(hdspm, HDSPM_RD_STATUS_2); /* freq */
5094 status3 = hdspm_read(hdspm, HDSPM_RD_STATUS_3); /* s2 */
5095
5096 control = hdspm->control_register;
5097
5098 snd_iprintf(buffer, "STATUS1: 0x%08x\n", status1);
5099 snd_iprintf(buffer, "STATUS2: 0x%08x\n", status2);
5100 snd_iprintf(buffer, "STATUS3: 0x%08x\n", status3);
5101
5102
5103 snd_iprintf(buffer, "\n*** CLOCK MODE\n\n");
5104
5105 snd_iprintf(buffer, "Clock mode : %s\n",
5106 (hdspm_system_clock_mode(hdspm) == 0) ? "master" : "slave");
5107 snd_iprintf(buffer, "System frequency: %d Hz\n",
5108 hdspm_get_system_sample_rate(hdspm));
5109
5110 snd_iprintf(buffer, "\n*** INPUT STATUS\n\n");
5111
5112 lock = 0x1;
5113 sync = 0x100;
5114
5115 for (i = 0; i < 8; i++) {
5116 snd_iprintf(buffer, "s1_input %d: Lock %d, Sync %d, Freq %s\n",
5117 i,
5118 (status1 & lock) ? 1 : 0,
5119 (status1 & sync) ? 1 : 0,
5120 texts_freq[(status2 >> (i * 4)) & 0xF]);
5121
5122 lock = lock<<1;
5123 sync = sync<<1;
5124 }
5125
5126 snd_iprintf(buffer, "WC input: Lock %d, Sync %d, Freq %s\n",
5127 (status1 & 0x1000000) ? 1 : 0,
5128 (status1 & 0x2000000) ? 1 : 0,
5129 texts_freq[(status1 >> 16) & 0xF]);
5130
5131 snd_iprintf(buffer, "TCO input: Lock %d, Sync %d, Freq %s\n",
5132 (status1 & 0x4000000) ? 1 : 0,
5133 (status1 & 0x8000000) ? 1 : 0,
5134 texts_freq[(status1 >> 20) & 0xF]);
5135
5136 snd_iprintf(buffer, "SYNC IN: Lock %d, Sync %d, Freq %s\n",
5137 (status3 & 0x400) ? 1 : 0,
5138 (status3 & 0x800) ? 1 : 0,
5139 texts_freq[(status2 >> 12) & 0xF]);
5140
5141}
5142
Remy Bruno3cee5a62006-10-16 12:46:32 +02005143#ifdef CONFIG_SND_DEBUG
5144static void
Adrian Knoth0dca1792011-01-26 19:32:14 +01005145snd_hdspm_proc_read_debug(struct snd_info_entry *entry,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005146 struct snd_info_buffer *buffer)
5147{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005148 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005149
5150 int j,i;
5151
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005152 for (i = 0; i < 256 /* 1024*64 */; i += j) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02005153 snd_iprintf(buffer, "0x%08X: ", i);
5154 for (j = 0; j < 16; j += 4)
5155 snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
5156 snd_iprintf(buffer, "\n");
5157 }
5158}
5159#endif
5160
5161
Adrian Knoth0dca1792011-01-26 19:32:14 +01005162static void snd_hdspm_proc_ports_in(struct snd_info_entry *entry,
5163 struct snd_info_buffer *buffer)
5164{
5165 struct hdspm *hdspm = entry->private_data;
5166 int i;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005167
Adrian Knoth0dca1792011-01-26 19:32:14 +01005168 snd_iprintf(buffer, "# generated by hdspm\n");
5169
5170 for (i = 0; i < hdspm->max_channels_in; i++) {
5171 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_in[i]);
5172 }
5173}
5174
5175static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry,
5176 struct snd_info_buffer *buffer)
5177{
5178 struct hdspm *hdspm = entry->private_data;
5179 int i;
5180
5181 snd_iprintf(buffer, "# generated by hdspm\n");
5182
5183 for (i = 0; i < hdspm->max_channels_out; i++) {
5184 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_out[i]);
5185 }
5186}
5187
5188
5189static void __devinit snd_hdspm_proc_init(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005190{
Takashi Iwai98274f02005-11-17 14:52:34 +01005191 struct snd_info_entry *entry;
Takashi Iwai763f3562005-06-03 11:25:34 +02005192
Adrian Knoth0dca1792011-01-26 19:32:14 +01005193 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) {
5194 switch (hdspm->io_type) {
5195 case AES32:
5196 snd_info_set_text_ops(entry, hdspm,
5197 snd_hdspm_proc_read_aes32);
5198 break;
5199 case MADI:
5200 snd_info_set_text_ops(entry, hdspm,
5201 snd_hdspm_proc_read_madi);
5202 break;
5203 case MADIface:
5204 /* snd_info_set_text_ops(entry, hdspm,
5205 snd_hdspm_proc_read_madiface); */
5206 break;
5207 case RayDAT:
5208 snd_info_set_text_ops(entry, hdspm,
5209 snd_hdspm_proc_read_raydat);
5210 break;
5211 case AIO:
5212 break;
5213 }
5214 }
5215
5216 if (!snd_card_proc_new(hdspm->card, "ports.in", &entry)) {
5217 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_in);
5218 }
5219
5220 if (!snd_card_proc_new(hdspm->card, "ports.out", &entry)) {
5221 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_out);
5222 }
5223
Remy Bruno3cee5a62006-10-16 12:46:32 +02005224#ifdef CONFIG_SND_DEBUG
5225 /* debug file to read all hdspm registers */
5226 if (!snd_card_proc_new(hdspm->card, "debug", &entry))
5227 snd_info_set_text_ops(entry, hdspm,
5228 snd_hdspm_proc_read_debug);
5229#endif
Takashi Iwai763f3562005-06-03 11:25:34 +02005230}
5231
5232/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005233 hdspm intitialize
Takashi Iwai763f3562005-06-03 11:25:34 +02005234 ------------------------------------------------------------*/
5235
Takashi Iwai98274f02005-11-17 14:52:34 +01005236static int snd_hdspm_set_defaults(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005237{
Takashi Iwai763f3562005-06-03 11:25:34 +02005238 /* ASSUMPTION: hdspm->lock is either held, or there is no need to
Joe Perches561de312007-12-18 13:13:47 +01005239 hold it (e.g. during module initialization).
Adrian Knoth0dca1792011-01-26 19:32:14 +01005240 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005241
5242 /* set defaults: */
5243
Adrian Knoth0dca1792011-01-26 19:32:14 +01005244 hdspm->settings_register = 0;
5245
5246 switch (hdspm->io_type) {
5247 case MADI:
5248 case MADIface:
5249 hdspm->control_register =
5250 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5251 break;
5252
5253 case RayDAT:
5254 case AIO:
5255 hdspm->settings_register = 0x1 + 0x1000;
5256 /* Magic values are: LAT_0, LAT_2, Master, freq1, tx64ch, inp_0,
5257 * line_out */
5258 hdspm->control_register =
5259 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5260 break;
5261
5262 case AES32:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005263 hdspm->control_register =
5264 HDSPM_ClockModeMaster | /* Master Cloack Mode on */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005265 hdspm_encode_latency(7) | /* latency max=8192samples */
Remy Bruno3cee5a62006-10-16 12:46:32 +02005266 HDSPM_SyncRef0 | /* AES1 is syncclock */
5267 HDSPM_LineOut | /* Analog output in */
5268 HDSPM_Professional; /* Professional mode */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005269 break;
5270 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005271
5272 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5273
Adrian Knoth0dca1792011-01-26 19:32:14 +01005274 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005275 /* No control2 register for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005276#ifdef SNDRV_BIG_ENDIAN
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005277 hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
Takashi Iwai763f3562005-06-03 11:25:34 +02005278#else
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005279 hdspm->control2_register = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005280#endif
5281
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005282 hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
5283 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005284 hdspm_compute_period_size(hdspm);
5285
5286 /* silence everything */
5287
5288 all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
5289
Adrian Knoth0dca1792011-01-26 19:32:14 +01005290 if (hdspm->io_type == AIO || hdspm->io_type == RayDAT) {
5291 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
Takashi Iwai763f3562005-06-03 11:25:34 +02005292 }
5293
5294 /* set a default rate so that the channel map is set up. */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005295 hdspm_set_rate(hdspm, 48000, 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02005296
5297 return 0;
5298}
5299
5300
5301/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005302 interrupt
Takashi Iwai763f3562005-06-03 11:25:34 +02005303 ------------------------------------------------------------*/
5304
David Howells7d12e782006-10-05 14:55:46 +01005305static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02005306{
Takashi Iwai98274f02005-11-17 14:52:34 +01005307 struct hdspm *hdspm = (struct hdspm *) dev_id;
Takashi Iwai763f3562005-06-03 11:25:34 +02005308 unsigned int status;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005309 int i, audio, midi, schedule = 0;
5310 /* cycles_t now; */
Takashi Iwai763f3562005-06-03 11:25:34 +02005311
5312 status = hdspm_read(hdspm, HDSPM_statusRegister);
5313
5314 audio = status & HDSPM_audioIRQPending;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005315 midi = status & (HDSPM_midi0IRQPending | HDSPM_midi1IRQPending |
5316 HDSPM_midi2IRQPending | HDSPM_midi3IRQPending);
Takashi Iwai763f3562005-06-03 11:25:34 +02005317
Adrian Knoth0dca1792011-01-26 19:32:14 +01005318 /* now = get_cycles(); */
5319 /**
5320 * LAT_2..LAT_0 period counter (win) counter (mac)
5321 * 6 4096 ~256053425 ~514672358
5322 * 5 2048 ~128024983 ~257373821
5323 * 4 1024 ~64023706 ~128718089
5324 * 3 512 ~32005945 ~64385999
5325 * 2 256 ~16003039 ~32260176
5326 * 1 128 ~7998738 ~16194507
5327 * 0 64 ~3998231 ~8191558
5328 **/
5329 /*
5330 snd_printk(KERN_INFO "snd_hdspm_interrupt %llu @ %llx\n",
5331 now-hdspm->last_interrupt, status & 0xFFC0);
5332 hdspm->last_interrupt = now;
5333 */
5334
5335 if (!audio && !midi)
Takashi Iwai763f3562005-06-03 11:25:34 +02005336 return IRQ_NONE;
5337
5338 hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
5339 hdspm->irq_count++;
5340
Takashi Iwai763f3562005-06-03 11:25:34 +02005341
5342 if (audio) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005343 if (hdspm->capture_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005344 snd_pcm_period_elapsed(hdspm->capture_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005345
5346 if (hdspm->playback_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005347 snd_pcm_period_elapsed(hdspm->playback_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005348 }
5349
Adrian Knoth0dca1792011-01-26 19:32:14 +01005350 if (midi) {
5351 i = 0;
5352 while (i < hdspm->midiPorts) {
5353 if ((hdspm_read(hdspm,
5354 hdspm->midi[i].statusIn) & 0xff) &&
5355 (status & hdspm->midi[i].irq)) {
5356 /* we disable interrupts for this input until
5357 * processing is done
5358 */
5359 hdspm->control_register &= ~hdspm->midi[i].ie;
5360 hdspm_write(hdspm, HDSPM_controlRegister,
5361 hdspm->control_register);
5362 hdspm->midi[i].pending = 1;
5363 schedule = 1;
5364 }
5365
5366 i++;
5367 }
5368
5369 if (schedule)
5370 tasklet_hi_schedule(&hdspm->midi_tasklet);
Takashi Iwai763f3562005-06-03 11:25:34 +02005371 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005372
Takashi Iwai763f3562005-06-03 11:25:34 +02005373 return IRQ_HANDLED;
5374}
5375
5376/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005377 pcm interface
Takashi Iwai763f3562005-06-03 11:25:34 +02005378 ------------------------------------------------------------*/
5379
5380
Adrian Knoth0dca1792011-01-26 19:32:14 +01005381static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream
5382 *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005383{
Takashi Iwai98274f02005-11-17 14:52:34 +01005384 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005385 return hdspm_hw_pointer(hdspm);
5386}
5387
Takashi Iwai763f3562005-06-03 11:25:34 +02005388
Takashi Iwai98274f02005-11-17 14:52:34 +01005389static int snd_hdspm_reset(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005390{
Takashi Iwai98274f02005-11-17 14:52:34 +01005391 struct snd_pcm_runtime *runtime = substream->runtime;
5392 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5393 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005394
5395 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5396 other = hdspm->capture_substream;
5397 else
5398 other = hdspm->playback_substream;
5399
5400 if (hdspm->running)
5401 runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
5402 else
5403 runtime->status->hw_ptr = 0;
5404 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005405 struct snd_pcm_substream *s;
5406 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01005407 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005408 if (s == other) {
5409 oruntime->status->hw_ptr =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005410 runtime->status->hw_ptr;
Takashi Iwai763f3562005-06-03 11:25:34 +02005411 break;
5412 }
5413 }
5414 }
5415 return 0;
5416}
5417
Takashi Iwai98274f02005-11-17 14:52:34 +01005418static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
5419 struct snd_pcm_hw_params *params)
Takashi Iwai763f3562005-06-03 11:25:34 +02005420{
Takashi Iwai98274f02005-11-17 14:52:34 +01005421 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005422 int err;
5423 int i;
5424 pid_t this_pid;
5425 pid_t other_pid;
Takashi Iwai763f3562005-06-03 11:25:34 +02005426
5427 spin_lock_irq(&hdspm->lock);
5428
5429 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5430 this_pid = hdspm->playback_pid;
5431 other_pid = hdspm->capture_pid;
5432 } else {
5433 this_pid = hdspm->capture_pid;
5434 other_pid = hdspm->playback_pid;
5435 }
5436
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005437 if (other_pid > 0 && this_pid != other_pid) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005438
5439 /* The other stream is open, and not by the same
5440 task as this one. Make sure that the parameters
5441 that matter are the same.
Adrian Knoth0dca1792011-01-26 19:32:14 +01005442 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005443
5444 if (params_rate(params) != hdspm->system_sample_rate) {
5445 spin_unlock_irq(&hdspm->lock);
5446 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005447 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005448 return -EBUSY;
5449 }
5450
5451 if (params_period_size(params) != hdspm->period_bytes / 4) {
5452 spin_unlock_irq(&hdspm->lock);
5453 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005454 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005455 return -EBUSY;
5456 }
5457
5458 }
5459 /* We're fine. */
5460 spin_unlock_irq(&hdspm->lock);
5461
5462 /* how to make sure that the rate matches an externally-set one ? */
5463
5464 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005465 err = hdspm_set_rate(hdspm, params_rate(params), 0);
5466 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005467 snd_printk(KERN_INFO "err on hdspm_set_rate: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005468 spin_unlock_irq(&hdspm->lock);
5469 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005470 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005471 return err;
5472 }
5473 spin_unlock_irq(&hdspm->lock);
5474
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005475 err = hdspm_set_interrupt_interval(hdspm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005476 params_period_size(params));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005477 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005478 snd_printk(KERN_INFO "err on hdspm_set_interrupt_interval: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005479 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005480 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005481 return err;
5482 }
5483
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005484 /* Memory allocation, takashi's method, dont know if we should
5485 * spinlock
5486 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005487 /* malloc all buffer even if not enabled to get sure */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005488 /* Update for MADI rev 204: we need to allocate for all channels,
5489 * otherwise it doesn't work at 96kHz */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005490
Takashi Iwai763f3562005-06-03 11:25:34 +02005491 err =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005492 snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
5493 if (err < 0) {
5494 snd_printk(KERN_INFO "err on snd_pcm_lib_malloc_pages: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005495 return err;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005496 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005497
Takashi Iwai763f3562005-06-03 11:25:34 +02005498 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5499
Takashi Iwai77a23f22008-08-21 13:00:13 +02005500 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferOut,
Takashi Iwai763f3562005-06-03 11:25:34 +02005501 params_channels(params));
5502
5503 for (i = 0; i < params_channels(params); ++i)
5504 snd_hdspm_enable_out(hdspm, i, 1);
5505
5506 hdspm->playback_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005507 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005508 snd_printdd("Allocated sample buffer for playback at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005509 hdspm->playback_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005510 } else {
Takashi Iwai77a23f22008-08-21 13:00:13 +02005511 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn,
Takashi Iwai763f3562005-06-03 11:25:34 +02005512 params_channels(params));
5513
5514 for (i = 0; i < params_channels(params); ++i)
5515 snd_hdspm_enable_in(hdspm, i, 1);
5516
5517 hdspm->capture_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005518 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005519 snd_printdd("Allocated sample buffer for capture at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005520 hdspm->capture_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005521 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005522
Remy Bruno3cee5a62006-10-16 12:46:32 +02005523 /*
5524 snd_printdd("Allocated sample buffer for %s at 0x%08X\n",
5525 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5526 "playback" : "capture",
Takashi Iwai77a23f22008-08-21 13:00:13 +02005527 snd_pcm_sgbuf_get_addr(substream, 0));
Adrian Knoth0dca1792011-01-26 19:32:14 +01005528 */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005529 /*
Adrian Knoth0dca1792011-01-26 19:32:14 +01005530 snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n",
5531 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5532 "playback" : "capture",
5533 params_rate(params), params_channels(params),
5534 params_buffer_size(params));
5535 */
5536
5537
5538 /* Switch to native float format if requested */
5539 if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) {
5540 if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT))
5541 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE float format.\n");
5542
5543 hdspm->control_register |= HDSPe_FLOAT_FORMAT;
5544 } else if (SNDRV_PCM_FORMAT_S32_LE == params_format(params)) {
5545 if (hdspm->control_register & HDSPe_FLOAT_FORMAT)
5546 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE integer format.\n");
5547
5548 hdspm->control_register &= ~HDSPe_FLOAT_FORMAT;
5549 }
5550 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5551
Takashi Iwai763f3562005-06-03 11:25:34 +02005552 return 0;
5553}
5554
Takashi Iwai98274f02005-11-17 14:52:34 +01005555static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005556{
5557 int i;
Takashi Iwai98274f02005-11-17 14:52:34 +01005558 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005559
5560 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5561
Adrian Knoth0dca1792011-01-26 19:32:14 +01005562 /* params_channels(params) should be enough,
Takashi Iwai763f3562005-06-03 11:25:34 +02005563 but to get sure in case of error */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005564 for (i = 0; i < hdspm->max_channels_out; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005565 snd_hdspm_enable_out(hdspm, i, 0);
5566
5567 hdspm->playback_buffer = NULL;
5568 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005569 for (i = 0; i < hdspm->max_channels_in; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005570 snd_hdspm_enable_in(hdspm, i, 0);
5571
5572 hdspm->capture_buffer = NULL;
5573
5574 }
5575
5576 snd_pcm_lib_free_pages(substream);
5577
5578 return 0;
5579}
5580
Adrian Knoth0dca1792011-01-26 19:32:14 +01005581
Takashi Iwai98274f02005-11-17 14:52:34 +01005582static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005583 struct snd_pcm_channel_info *info)
Takashi Iwai763f3562005-06-03 11:25:34 +02005584{
Takashi Iwai98274f02005-11-17 14:52:34 +01005585 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005586
Adrian Knoth0dca1792011-01-26 19:32:14 +01005587 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5588 if (snd_BUG_ON(info->channel >= hdspm->max_channels_out)) {
5589 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel out of range (%d)\n", info->channel);
5590 return -EINVAL;
5591 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005592
Adrian Knoth0dca1792011-01-26 19:32:14 +01005593 if (hdspm->channel_map_out[info->channel] < 0) {
5594 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel %d mapped out\n", info->channel);
5595 return -EINVAL;
5596 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005597
Adrian Knoth0dca1792011-01-26 19:32:14 +01005598 info->offset = hdspm->channel_map_out[info->channel] *
5599 HDSPM_CHANNEL_BUFFER_BYTES;
5600 } else {
5601 if (snd_BUG_ON(info->channel >= hdspm->max_channels_in)) {
5602 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel out of range (%d)\n", info->channel);
5603 return -EINVAL;
5604 }
5605
5606 if (hdspm->channel_map_in[info->channel] < 0) {
5607 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel %d mapped out\n", info->channel);
5608 return -EINVAL;
5609 }
5610
5611 info->offset = hdspm->channel_map_in[info->channel] *
5612 HDSPM_CHANNEL_BUFFER_BYTES;
5613 }
5614
Takashi Iwai763f3562005-06-03 11:25:34 +02005615 info->first = 0;
5616 info->step = 32;
5617 return 0;
5618}
5619
Adrian Knoth0dca1792011-01-26 19:32:14 +01005620
Takashi Iwai98274f02005-11-17 14:52:34 +01005621static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005622 unsigned int cmd, void *arg)
Takashi Iwai763f3562005-06-03 11:25:34 +02005623{
5624 switch (cmd) {
5625 case SNDRV_PCM_IOCTL1_RESET:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005626 return snd_hdspm_reset(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005627
5628 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Adrian Knoth0dca1792011-01-26 19:32:14 +01005629 {
5630 struct snd_pcm_channel_info *info = arg;
5631 return snd_hdspm_channel_info(substream, info);
5632 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005633 default:
5634 break;
5635 }
5636
5637 return snd_pcm_lib_ioctl(substream, cmd, arg);
5638}
5639
Takashi Iwai98274f02005-11-17 14:52:34 +01005640static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
Takashi Iwai763f3562005-06-03 11:25:34 +02005641{
Takashi Iwai98274f02005-11-17 14:52:34 +01005642 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5643 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005644 int running;
5645
5646 spin_lock(&hdspm->lock);
5647 running = hdspm->running;
5648 switch (cmd) {
5649 case SNDRV_PCM_TRIGGER_START:
5650 running |= 1 << substream->stream;
5651 break;
5652 case SNDRV_PCM_TRIGGER_STOP:
5653 running &= ~(1 << substream->stream);
5654 break;
5655 default:
5656 snd_BUG();
5657 spin_unlock(&hdspm->lock);
5658 return -EINVAL;
5659 }
5660 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5661 other = hdspm->capture_substream;
5662 else
5663 other = hdspm->playback_substream;
5664
5665 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005666 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01005667 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005668 if (s == other) {
5669 snd_pcm_trigger_done(s, substream);
5670 if (cmd == SNDRV_PCM_TRIGGER_START)
5671 running |= 1 << s->stream;
5672 else
5673 running &= ~(1 << s->stream);
5674 goto _ok;
5675 }
5676 }
5677 if (cmd == SNDRV_PCM_TRIGGER_START) {
5678 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005679 && substream->stream ==
5680 SNDRV_PCM_STREAM_CAPTURE)
Takashi Iwai763f3562005-06-03 11:25:34 +02005681 hdspm_silence_playback(hdspm);
5682 } else {
5683 if (running &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01005684 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Takashi Iwai763f3562005-06-03 11:25:34 +02005685 hdspm_silence_playback(hdspm);
5686 }
5687 } else {
5688 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
5689 hdspm_silence_playback(hdspm);
5690 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005691_ok:
Takashi Iwai763f3562005-06-03 11:25:34 +02005692 snd_pcm_trigger_done(substream, substream);
5693 if (!hdspm->running && running)
5694 hdspm_start_audio(hdspm);
5695 else if (hdspm->running && !running)
5696 hdspm_stop_audio(hdspm);
5697 hdspm->running = running;
5698 spin_unlock(&hdspm->lock);
5699
5700 return 0;
5701}
5702
Takashi Iwai98274f02005-11-17 14:52:34 +01005703static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005704{
5705 return 0;
5706}
5707
Takashi Iwai98274f02005-11-17 14:52:34 +01005708static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005709 .info = (SNDRV_PCM_INFO_MMAP |
5710 SNDRV_PCM_INFO_MMAP_VALID |
5711 SNDRV_PCM_INFO_NONINTERLEAVED |
5712 SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
5713 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5714 .rates = (SNDRV_PCM_RATE_32000 |
5715 SNDRV_PCM_RATE_44100 |
5716 SNDRV_PCM_RATE_48000 |
5717 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005718 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5719 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ),
Takashi Iwai763f3562005-06-03 11:25:34 +02005720 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005721 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005722 .channels_min = 1,
5723 .channels_max = HDSPM_MAX_CHANNELS,
5724 .buffer_bytes_max =
5725 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
Adrian Knoth1b6fa102011-08-15 00:22:51 +02005726 .period_bytes_min = (32 * 4),
Takashi Iwai52e6fb42011-08-15 10:40:59 +02005727 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005728 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005729 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005730 .fifo_size = 0
5731};
5732
Takashi Iwai98274f02005-11-17 14:52:34 +01005733static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005734 .info = (SNDRV_PCM_INFO_MMAP |
5735 SNDRV_PCM_INFO_MMAP_VALID |
5736 SNDRV_PCM_INFO_NONINTERLEAVED |
5737 SNDRV_PCM_INFO_SYNC_START),
5738 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5739 .rates = (SNDRV_PCM_RATE_32000 |
5740 SNDRV_PCM_RATE_44100 |
5741 SNDRV_PCM_RATE_48000 |
5742 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005743 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5744 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
Takashi Iwai763f3562005-06-03 11:25:34 +02005745 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005746 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005747 .channels_min = 1,
5748 .channels_max = HDSPM_MAX_CHANNELS,
5749 .buffer_bytes_max =
5750 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
Adrian Knoth1b6fa102011-08-15 00:22:51 +02005751 .period_bytes_min = (32 * 4),
Takashi Iwai52e6fb42011-08-15 10:40:59 +02005752 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005753 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005754 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005755 .fifo_size = 0
5756};
5757
Adrian Knoth0dca1792011-01-26 19:32:14 +01005758static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
5759 struct snd_pcm_hw_rule *rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005760{
Takashi Iwai98274f02005-11-17 14:52:34 +01005761 struct hdspm *hdspm = rule->private;
5762 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005763 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005764 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005765 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5766
Adrian Knoth0dca1792011-01-26 19:32:14 +01005767 if (r->min > 96000 && r->max <= 192000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005768 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005769 .min = hdspm->qs_in_channels,
5770 .max = hdspm->qs_in_channels,
5771 .integer = 1,
5772 };
5773 return snd_interval_refine(c, &t);
5774 } else if (r->min > 48000 && r->max <= 96000) {
5775 struct snd_interval t = {
5776 .min = hdspm->ds_in_channels,
5777 .max = hdspm->ds_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005778 .integer = 1,
5779 };
5780 return snd_interval_refine(c, &t);
5781 } else if (r->max < 64000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005782 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005783 .min = hdspm->ss_in_channels,
5784 .max = hdspm->ss_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005785 .integer = 1,
5786 };
5787 return snd_interval_refine(c, &t);
5788 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005789
Takashi Iwai763f3562005-06-03 11:25:34 +02005790 return 0;
5791}
5792
Adrian Knoth0dca1792011-01-26 19:32:14 +01005793static int snd_hdspm_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
Takashi Iwai98274f02005-11-17 14:52:34 +01005794 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005795{
Takashi Iwai98274f02005-11-17 14:52:34 +01005796 struct hdspm *hdspm = rule->private;
5797 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005798 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005799 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005800 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5801
Adrian Knoth0dca1792011-01-26 19:32:14 +01005802 if (r->min > 96000 && r->max <= 192000) {
5803 struct snd_interval t = {
5804 .min = hdspm->qs_out_channels,
5805 .max = hdspm->qs_out_channels,
5806 .integer = 1,
5807 };
5808 return snd_interval_refine(c, &t);
5809 } else if (r->min > 48000 && r->max <= 96000) {
5810 struct snd_interval t = {
5811 .min = hdspm->ds_out_channels,
5812 .max = hdspm->ds_out_channels,
5813 .integer = 1,
5814 };
5815 return snd_interval_refine(c, &t);
5816 } else if (r->max < 64000) {
5817 struct snd_interval t = {
5818 .min = hdspm->ss_out_channels,
5819 .max = hdspm->ss_out_channels,
5820 .integer = 1,
5821 };
5822 return snd_interval_refine(c, &t);
5823 } else {
5824 }
5825 return 0;
5826}
5827
5828static int snd_hdspm_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
5829 struct snd_pcm_hw_rule * rule)
5830{
5831 struct hdspm *hdspm = rule->private;
5832 struct snd_interval *c =
5833 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5834 struct snd_interval *r =
5835 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5836
5837 if (c->min >= hdspm->ss_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005838 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005839 .min = 32000,
5840 .max = 48000,
5841 .integer = 1,
5842 };
5843 return snd_interval_refine(r, &t);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005844 } else if (c->max <= hdspm->qs_in_channels) {
5845 struct snd_interval t = {
5846 .min = 128000,
5847 .max = 192000,
5848 .integer = 1,
5849 };
5850 return snd_interval_refine(r, &t);
5851 } else if (c->max <= hdspm->ds_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005852 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005853 .min = 64000,
5854 .max = 96000,
5855 .integer = 1,
5856 };
Takashi Iwai763f3562005-06-03 11:25:34 +02005857 return snd_interval_refine(r, &t);
5858 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005859
5860 return 0;
5861}
5862static int snd_hdspm_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
5863 struct snd_pcm_hw_rule *rule)
5864{
5865 struct hdspm *hdspm = rule->private;
5866 struct snd_interval *c =
5867 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5868 struct snd_interval *r =
5869 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5870
5871 if (c->min >= hdspm->ss_out_channels) {
5872 struct snd_interval t = {
5873 .min = 32000,
5874 .max = 48000,
5875 .integer = 1,
5876 };
5877 return snd_interval_refine(r, &t);
5878 } else if (c->max <= hdspm->qs_out_channels) {
5879 struct snd_interval t = {
5880 .min = 128000,
5881 .max = 192000,
5882 .integer = 1,
5883 };
5884 return snd_interval_refine(r, &t);
5885 } else if (c->max <= hdspm->ds_out_channels) {
5886 struct snd_interval t = {
5887 .min = 64000,
5888 .max = 96000,
5889 .integer = 1,
5890 };
5891 return snd_interval_refine(r, &t);
5892 }
5893
Takashi Iwai763f3562005-06-03 11:25:34 +02005894 return 0;
5895}
5896
Adrian Knoth0dca1792011-01-26 19:32:14 +01005897static int snd_hdspm_hw_rule_in_channels(struct snd_pcm_hw_params *params,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005898 struct snd_pcm_hw_rule *rule)
5899{
5900 unsigned int list[3];
5901 struct hdspm *hdspm = rule->private;
5902 struct snd_interval *c = hw_param_interval(params,
5903 SNDRV_PCM_HW_PARAM_CHANNELS);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005904
5905 list[0] = hdspm->qs_in_channels;
5906 list[1] = hdspm->ds_in_channels;
5907 list[2] = hdspm->ss_in_channels;
5908 return snd_interval_list(c, 3, list, 0);
5909}
5910
5911static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params,
5912 struct snd_pcm_hw_rule *rule)
5913{
5914 unsigned int list[3];
5915 struct hdspm *hdspm = rule->private;
5916 struct snd_interval *c = hw_param_interval(params,
5917 SNDRV_PCM_HW_PARAM_CHANNELS);
5918
5919 list[0] = hdspm->qs_out_channels;
5920 list[1] = hdspm->ds_out_channels;
5921 list[2] = hdspm->ss_out_channels;
5922 return snd_interval_list(c, 3, list, 0);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005923}
5924
5925
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005926static unsigned int hdspm_aes32_sample_rates[] = {
5927 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000
5928};
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005929
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005930static struct snd_pcm_hw_constraint_list
5931hdspm_hw_constraints_aes32_sample_rates = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005932 .count = ARRAY_SIZE(hdspm_aes32_sample_rates),
5933 .list = hdspm_aes32_sample_rates,
5934 .mask = 0
5935};
5936
Takashi Iwai98274f02005-11-17 14:52:34 +01005937static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005938{
Takashi Iwai98274f02005-11-17 14:52:34 +01005939 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5940 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02005941
Takashi Iwai763f3562005-06-03 11:25:34 +02005942 spin_lock_irq(&hdspm->lock);
5943
5944 snd_pcm_set_sync(substream);
5945
Adrian Knoth0dca1792011-01-26 19:32:14 +01005946
Takashi Iwai763f3562005-06-03 11:25:34 +02005947 runtime->hw = snd_hdspm_playback_subinfo;
5948
5949 if (hdspm->capture_substream == NULL)
5950 hdspm_stop_audio(hdspm);
5951
5952 hdspm->playback_pid = current->pid;
5953 hdspm->playback_substream = substream;
5954
5955 spin_unlock_irq(&hdspm->lock);
5956
5957 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Takashi Iwaid8776812011-08-15 10:45:42 +02005958 snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005959
Adrian Knoth0dca1792011-01-26 19:32:14 +01005960 switch (hdspm->io_type) {
5961 case AIO:
5962 case RayDAT:
Takashi Iwaid8776812011-08-15 10:45:42 +02005963 snd_pcm_hw_constraint_minmax(runtime,
5964 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5965 32, 4096);
5966 /* RayDAT & AIO have a fixed buffer of 16384 samples per channel */
5967 snd_pcm_hw_constraint_minmax(runtime,
5968 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
5969 16384, 16384);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005970 break;
5971
5972 default:
Takashi Iwaid8776812011-08-15 10:45:42 +02005973 snd_pcm_hw_constraint_minmax(runtime,
5974 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5975 64, 8192);
5976 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005977 }
5978
5979 if (AES32 == hdspm->io_type) {
Takashi Iwai3fa9e3d2011-08-15 10:42:23 +02005980 runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005981 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
5982 &hdspm_hw_constraints_aes32_sample_rates);
5983 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005984 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005985 snd_hdspm_hw_rule_rate_out_channels, hdspm,
5986 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005987 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01005988
5989 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5990 snd_hdspm_hw_rule_out_channels, hdspm,
5991 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
5992
5993 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5994 snd_hdspm_hw_rule_out_channels_rate, hdspm,
5995 SNDRV_PCM_HW_PARAM_RATE, -1);
5996
Takashi Iwai763f3562005-06-03 11:25:34 +02005997 return 0;
5998}
5999
Takashi Iwai98274f02005-11-17 14:52:34 +01006000static int snd_hdspm_playback_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02006001{
Takashi Iwai98274f02005-11-17 14:52:34 +01006002 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02006003
6004 spin_lock_irq(&hdspm->lock);
6005
6006 hdspm->playback_pid = -1;
6007 hdspm->playback_substream = NULL;
6008
6009 spin_unlock_irq(&hdspm->lock);
6010
6011 return 0;
6012}
6013
6014
Takashi Iwai98274f02005-11-17 14:52:34 +01006015static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02006016{
Takashi Iwai98274f02005-11-17 14:52:34 +01006017 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
6018 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02006019
6020 spin_lock_irq(&hdspm->lock);
6021 snd_pcm_set_sync(substream);
6022 runtime->hw = snd_hdspm_capture_subinfo;
6023
6024 if (hdspm->playback_substream == NULL)
6025 hdspm_stop_audio(hdspm);
6026
6027 hdspm->capture_pid = current->pid;
6028 hdspm->capture_substream = substream;
6029
6030 spin_unlock_irq(&hdspm->lock);
6031
6032 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Takashi Iwaid8776812011-08-15 10:45:42 +02006033 snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
6034
Adrian Knoth0dca1792011-01-26 19:32:14 +01006035 switch (hdspm->io_type) {
6036 case AIO:
6037 case RayDAT:
Takashi Iwaid8776812011-08-15 10:45:42 +02006038 snd_pcm_hw_constraint_minmax(runtime,
6039 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
6040 32, 4096);
6041 snd_pcm_hw_constraint_minmax(runtime,
6042 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
6043 16384, 16384);
6044 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006045
6046 default:
Takashi Iwaid8776812011-08-15 10:45:42 +02006047 snd_pcm_hw_constraint_minmax(runtime,
6048 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
6049 64, 8192);
6050 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006051 }
6052
6053 if (AES32 == hdspm->io_type) {
Takashi Iwai3fa9e3d2011-08-15 10:42:23 +02006054 runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006055 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
6056 &hdspm_hw_constraints_aes32_sample_rates);
6057 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006058 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth88fabbf2011-02-23 11:43:10 +01006059 snd_hdspm_hw_rule_rate_in_channels, hdspm,
6060 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006061 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01006062
6063 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
6064 snd_hdspm_hw_rule_in_channels, hdspm,
6065 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
6066
6067 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
6068 snd_hdspm_hw_rule_in_channels_rate, hdspm,
6069 SNDRV_PCM_HW_PARAM_RATE, -1);
6070
Takashi Iwai763f3562005-06-03 11:25:34 +02006071 return 0;
6072}
6073
Takashi Iwai98274f02005-11-17 14:52:34 +01006074static int snd_hdspm_capture_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02006075{
Takashi Iwai98274f02005-11-17 14:52:34 +01006076 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02006077
6078 spin_lock_irq(&hdspm->lock);
6079
6080 hdspm->capture_pid = -1;
6081 hdspm->capture_substream = NULL;
6082
6083 spin_unlock_irq(&hdspm->lock);
6084 return 0;
6085}
6086
Adrian Knoth0dca1792011-01-26 19:32:14 +01006087static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
Takashi Iwai763f3562005-06-03 11:25:34 +02006088{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006089 /* we have nothing to initialize but the call is required */
6090 return 0;
6091}
6092
6093static inline int copy_u32_le(void __user *dest, void __iomem *src)
6094{
6095 u32 val = readl(src);
6096 return copy_to_user(dest, &val, 4);
6097}
6098
6099static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006100 unsigned int cmd, unsigned long arg)
Adrian Knoth0dca1792011-01-26 19:32:14 +01006101{
6102 void __user *argp = (void __user *)arg;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006103 struct hdspm *hdspm = hw->private_data;
Takashi Iwai98274f02005-11-17 14:52:34 +01006104 struct hdspm_mixer_ioctl mixer;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006105 struct hdspm_config info;
6106 struct hdspm_status status;
Takashi Iwai98274f02005-11-17 14:52:34 +01006107 struct hdspm_version hdspm_version;
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006108 struct hdspm_peak_rms *levels;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006109 struct hdspm_ltc ltc;
6110 unsigned int statusregister;
6111 long unsigned int s;
6112 int i = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02006113
6114 switch (cmd) {
6115
Takashi Iwai763f3562005-06-03 11:25:34 +02006116 case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006117 levels = &hdspm->peak_rms;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006118 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006119 levels->input_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006120 readl(hdspm->iobase +
6121 HDSPM_MADI_INPUT_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006122 levels->playback_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006123 readl(hdspm->iobase +
6124 HDSPM_MADI_PLAYBACK_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006125 levels->output_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006126 readl(hdspm->iobase +
6127 HDSPM_MADI_OUTPUT_PEAK + i*4);
6128
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006129 levels->input_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006130 ((uint64_t) readl(hdspm->iobase +
6131 HDSPM_MADI_INPUT_RMS_H + i*4) << 32) |
6132 (uint64_t) readl(hdspm->iobase +
6133 HDSPM_MADI_INPUT_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006134 levels->playback_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006135 ((uint64_t)readl(hdspm->iobase +
6136 HDSPM_MADI_PLAYBACK_RMS_H+i*4) << 32) |
6137 (uint64_t)readl(hdspm->iobase +
6138 HDSPM_MADI_PLAYBACK_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006139 levels->output_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006140 ((uint64_t)readl(hdspm->iobase +
6141 HDSPM_MADI_OUTPUT_RMS_H + i*4) << 32) |
6142 (uint64_t)readl(hdspm->iobase +
6143 HDSPM_MADI_OUTPUT_RMS_L + i*4);
6144 }
6145
6146 if (hdspm->system_sample_rate > 96000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006147 levels->speed = qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006148 } else if (hdspm->system_sample_rate > 48000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006149 levels->speed = ds;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006150 } else {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006151 levels->speed = ss;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006152 }
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006153 levels->status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006154
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006155 s = copy_to_user(argp, levels, sizeof(struct hdspm_peak_rms));
Adrian Knoth0dca1792011-01-26 19:32:14 +01006156 if (0 != s) {
6157 /* snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu
6158 [Levels]\n", sizeof(struct hdspm_peak_rms), s);
6159 */
Takashi Iwai763f3562005-06-03 11:25:34 +02006160 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006161 }
6162 break;
6163
6164 case SNDRV_HDSPM_IOCTL_GET_LTC:
6165 ltc.ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
6166 i = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
6167 if (i & HDSPM_TCO1_LTC_Input_valid) {
6168 switch (i & (HDSPM_TCO1_LTC_Format_LSB |
6169 HDSPM_TCO1_LTC_Format_MSB)) {
6170 case 0:
6171 ltc.format = fps_24;
6172 break;
6173 case HDSPM_TCO1_LTC_Format_LSB:
6174 ltc.format = fps_25;
6175 break;
6176 case HDSPM_TCO1_LTC_Format_MSB:
6177 ltc.format = fps_2997;
6178 break;
6179 default:
6180 ltc.format = 30;
6181 break;
6182 }
6183 if (i & HDSPM_TCO1_set_drop_frame_flag) {
6184 ltc.frame = drop_frame;
6185 } else {
6186 ltc.frame = full_frame;
6187 }
6188 } else {
6189 ltc.format = format_invalid;
6190 ltc.frame = frame_invalid;
6191 }
6192 if (i & HDSPM_TCO1_Video_Input_Format_NTSC) {
6193 ltc.input_format = ntsc;
6194 } else if (i & HDSPM_TCO1_Video_Input_Format_PAL) {
6195 ltc.input_format = pal;
6196 } else {
6197 ltc.input_format = no_video;
6198 }
6199
6200 s = copy_to_user(argp, &ltc, sizeof(struct hdspm_ltc));
6201 if (0 != s) {
6202 /*
6203 snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */
Takashi Iwai763f3562005-06-03 11:25:34 +02006204 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006205 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006206
6207 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02006208
Adrian Knoth0dca1792011-01-26 19:32:14 +01006209 case SNDRV_HDSPM_IOCTL_GET_CONFIG:
Takashi Iwai763f3562005-06-03 11:25:34 +02006210
Adrian Knoth4ab69a22011-02-23 11:43:14 +01006211 memset(&info, 0, sizeof(info));
Takashi Iwai763f3562005-06-03 11:25:34 +02006212 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006213 info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
6214 info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006215
6216 info.system_sample_rate = hdspm->system_sample_rate;
6217 info.autosync_sample_rate =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006218 hdspm_external_sample_rate(hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006219 info.system_clock_mode = hdspm_system_clock_mode(hdspm);
6220 info.clock_source = hdspm_clock_source(hdspm);
6221 info.autosync_ref = hdspm_autosync_ref(hdspm);
6222 info.line_out = hdspm_line_out(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006223 info.passthru = 0;
6224 spin_unlock_irq(&hdspm->lock);
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006225 if (copy_to_user(argp, &info, sizeof(info)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006226 return -EFAULT;
6227 break;
6228
Adrian Knoth0dca1792011-01-26 19:32:14 +01006229 case SNDRV_HDSPM_IOCTL_GET_STATUS:
Dan Carpenter643d6bb2011-09-23 09:24:21 +03006230 memset(&status, 0, sizeof(status));
6231
Adrian Knoth0dca1792011-01-26 19:32:14 +01006232 status.card_type = hdspm->io_type;
6233
6234 status.autosync_source = hdspm_autosync_ref(hdspm);
6235
6236 status.card_clock = 110069313433624ULL;
6237 status.master_period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
6238
6239 switch (hdspm->io_type) {
6240 case MADI:
6241 case MADIface:
6242 status.card_specific.madi.sync_wc =
6243 hdspm_wc_sync_check(hdspm);
6244 status.card_specific.madi.sync_madi =
6245 hdspm_madi_sync_check(hdspm);
6246 status.card_specific.madi.sync_tco =
6247 hdspm_tco_sync_check(hdspm);
6248 status.card_specific.madi.sync_in =
6249 hdspm_sync_in_sync_check(hdspm);
6250
6251 statusregister =
6252 hdspm_read(hdspm, HDSPM_statusRegister);
6253 status.card_specific.madi.madi_input =
6254 (statusregister & HDSPM_AB_int) ? 1 : 0;
6255 status.card_specific.madi.channel_format =
Adrian Knoth9e6ff522011-10-27 21:57:52 +02006256 (statusregister & HDSPM_RX_64ch) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006257 /* TODO: Mac driver sets it when f_s>48kHz */
6258 status.card_specific.madi.frame_format = 0;
6259
6260 default:
6261 break;
6262 }
6263
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006264 if (copy_to_user(argp, &status, sizeof(status)))
Adrian Knoth0dca1792011-01-26 19:32:14 +01006265 return -EFAULT;
6266
6267
6268 break;
6269
Takashi Iwai763f3562005-06-03 11:25:34 +02006270 case SNDRV_HDSPM_IOCTL_GET_VERSION:
Dan Carpenter643d6bb2011-09-23 09:24:21 +03006271 memset(&hdspm_version, 0, sizeof(hdspm_version));
6272
Adrian Knoth0dca1792011-01-26 19:32:14 +01006273 hdspm_version.card_type = hdspm->io_type;
6274 strncpy(hdspm_version.cardname, hdspm->card_name,
6275 sizeof(hdspm_version.cardname));
6276 hdspm_version.serial = (hdspm_read(hdspm,
6277 HDSPM_midiStatusIn0)>>8) & 0xFFFFFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02006278 hdspm_version.firmware_rev = hdspm->firmware_rev;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006279 hdspm_version.addons = 0;
6280 if (hdspm->tco)
6281 hdspm_version.addons |= HDSPM_ADDON_TCO;
6282
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006283 if (copy_to_user(argp, &hdspm_version,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006284 sizeof(hdspm_version)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006285 return -EFAULT;
6286 break;
6287
6288 case SNDRV_HDSPM_IOCTL_GET_MIXER:
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006289 if (copy_from_user(&mixer, argp, sizeof(mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006290 return -EFAULT;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006291 if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006292 sizeof(struct hdspm_mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006293 return -EFAULT;
6294 break;
6295
6296 default:
6297 return -EINVAL;
6298 }
6299 return 0;
6300}
6301
Takashi Iwai98274f02005-11-17 14:52:34 +01006302static struct snd_pcm_ops snd_hdspm_playback_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006303 .open = snd_hdspm_playback_open,
6304 .close = snd_hdspm_playback_release,
6305 .ioctl = snd_hdspm_ioctl,
6306 .hw_params = snd_hdspm_hw_params,
6307 .hw_free = snd_hdspm_hw_free,
6308 .prepare = snd_hdspm_prepare,
6309 .trigger = snd_hdspm_trigger,
6310 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006311 .page = snd_pcm_sgbuf_ops_page,
6312};
6313
Takashi Iwai98274f02005-11-17 14:52:34 +01006314static struct snd_pcm_ops snd_hdspm_capture_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006315 .open = snd_hdspm_capture_open,
6316 .close = snd_hdspm_capture_release,
6317 .ioctl = snd_hdspm_ioctl,
6318 .hw_params = snd_hdspm_hw_params,
6319 .hw_free = snd_hdspm_hw_free,
6320 .prepare = snd_hdspm_prepare,
6321 .trigger = snd_hdspm_trigger,
6322 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006323 .page = snd_pcm_sgbuf_ops_page,
6324};
6325
Takashi Iwai98274f02005-11-17 14:52:34 +01006326static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
6327 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006328{
Takashi Iwai98274f02005-11-17 14:52:34 +01006329 struct snd_hwdep *hw;
Takashi Iwai763f3562005-06-03 11:25:34 +02006330 int err;
6331
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006332 err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw);
6333 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006334 return err;
6335
6336 hdspm->hwdep = hw;
6337 hw->private_data = hdspm;
6338 strcpy(hw->name, "HDSPM hwdep interface");
6339
Adrian Knoth0dca1792011-01-26 19:32:14 +01006340 hw->ops.open = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006341 hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006342 hw->ops.release = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006343
6344 return 0;
6345}
6346
6347
6348/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01006349 memory interface
Takashi Iwai763f3562005-06-03 11:25:34 +02006350 ------------------------------------------------------------*/
Adrian Knoth0dca1792011-01-26 19:32:14 +01006351static int __devinit snd_hdspm_preallocate_memory(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006352{
6353 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01006354 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006355 size_t wanted;
6356
6357 pcm = hdspm->pcm;
6358
Remy Bruno3cee5a62006-10-16 12:46:32 +02006359 wanted = HDSPM_DMA_AREA_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02006360
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006361 err =
Takashi Iwai763f3562005-06-03 11:25:34 +02006362 snd_pcm_lib_preallocate_pages_for_all(pcm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006363 SNDRV_DMA_TYPE_DEV_SG,
Takashi Iwai763f3562005-06-03 11:25:34 +02006364 snd_dma_pci_data(hdspm->pci),
6365 wanted,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006366 wanted);
6367 if (err < 0) {
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006368 snd_printdd("Could not preallocate %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006369
6370 return err;
6371 } else
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006372 snd_printdd(" Preallocated %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006373
6374 return 0;
6375}
6376
Adrian Knoth0dca1792011-01-26 19:32:14 +01006377
6378static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +02006379 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02006380 unsigned int reg, int channels)
6381{
6382 int i;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006383
6384 /* continuous memory segment */
Takashi Iwai763f3562005-06-03 11:25:34 +02006385 for (i = 0; i < (channels * 16); i++)
6386 hdspm_write(hdspm, reg + 4 * i,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006387 snd_pcm_sgbuf_get_addr(substream, 4096 * i));
Takashi Iwai763f3562005-06-03 11:25:34 +02006388}
6389
Adrian Knoth0dca1792011-01-26 19:32:14 +01006390
Takashi Iwai763f3562005-06-03 11:25:34 +02006391/* ------------- ALSA Devices ---------------------------- */
Takashi Iwai98274f02005-11-17 14:52:34 +01006392static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006393 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006394{
Takashi Iwai98274f02005-11-17 14:52:34 +01006395 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006396 int err;
6397
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006398 err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm);
6399 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006400 return err;
6401
6402 hdspm->pcm = pcm;
6403 pcm->private_data = hdspm;
6404 strcpy(pcm->name, hdspm->card_name);
6405
6406 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
6407 &snd_hdspm_playback_ops);
6408 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
6409 &snd_hdspm_capture_ops);
6410
6411 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
6412
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006413 err = snd_hdspm_preallocate_memory(hdspm);
6414 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006415 return err;
6416
6417 return 0;
6418}
6419
Takashi Iwai98274f02005-11-17 14:52:34 +01006420static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006421{
Adrian Knoth7c7102b2011-02-28 15:14:50 +01006422 int i;
6423
6424 for (i = 0; i < hdspm->midiPorts; i++)
6425 snd_hdspm_flush_midi_input(hdspm, i);
Takashi Iwai763f3562005-06-03 11:25:34 +02006426}
6427
Takashi Iwai98274f02005-11-17 14:52:34 +01006428static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
6429 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006430{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006431 int err, i;
Takashi Iwai763f3562005-06-03 11:25:34 +02006432
6433 snd_printdd("Create card...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006434 err = snd_hdspm_create_pcm(card, hdspm);
6435 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006436 return err;
6437
Adrian Knoth0dca1792011-01-26 19:32:14 +01006438 i = 0;
6439 while (i < hdspm->midiPorts) {
6440 err = snd_hdspm_create_midi(card, hdspm, i);
6441 if (err < 0) {
6442 return err;
6443 }
6444 i++;
6445 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006446
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006447 err = snd_hdspm_create_controls(card, hdspm);
6448 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006449 return err;
6450
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006451 err = snd_hdspm_create_hwdep(card, hdspm);
6452 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006453 return err;
6454
6455 snd_printdd("proc init...\n");
6456 snd_hdspm_proc_init(hdspm);
6457
6458 hdspm->system_sample_rate = -1;
6459 hdspm->last_external_sample_rate = -1;
6460 hdspm->last_internal_sample_rate = -1;
6461 hdspm->playback_pid = -1;
6462 hdspm->capture_pid = -1;
6463 hdspm->capture_substream = NULL;
6464 hdspm->playback_substream = NULL;
6465
6466 snd_printdd("Set defaults...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006467 err = snd_hdspm_set_defaults(hdspm);
6468 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006469 return err;
6470
6471 snd_printdd("Update mixer controls...\n");
6472 hdspm_update_simple_mixer_controls(hdspm);
6473
6474 snd_printdd("Initializeing complete ???\n");
6475
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006476 err = snd_card_register(card);
6477 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006478 snd_printk(KERN_ERR "HDSPM: error registering card\n");
6479 return err;
6480 }
6481
6482 snd_printdd("... yes now\n");
6483
6484 return 0;
6485}
6486
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006487static int __devinit snd_hdspm_create(struct snd_card *card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006488 struct hdspm *hdspm) {
6489
Takashi Iwai763f3562005-06-03 11:25:34 +02006490 struct pci_dev *pci = hdspm->pci;
6491 int err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006492 unsigned long io_extent;
6493
6494 hdspm->irq = -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02006495 hdspm->card = card;
6496
6497 spin_lock_init(&hdspm->lock);
6498
Takashi Iwai763f3562005-06-03 11:25:34 +02006499 pci_read_config_word(hdspm->pci,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006500 PCI_CLASS_REVISION, &hdspm->firmware_rev);
Remy Bruno3cee5a62006-10-16 12:46:32 +02006501
Takashi Iwai763f3562005-06-03 11:25:34 +02006502 strcpy(card->mixername, "Xilinx FPGA");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006503 strcpy(card->driver, "HDSPM");
6504
6505 switch (hdspm->firmware_rev) {
6506 case HDSPM_MADI_REV:
Adrian Knothefef0542011-06-12 17:26:19 +02006507 case HDSPM_MADI_OLD_REV:
Adrian Knoth5f8b4d52011-07-29 03:11:04 +02006508 case HDSPM_MADI_ANCIENT_REV:
Adrian Knoth0dca1792011-01-26 19:32:14 +01006509 hdspm->io_type = MADI;
6510 hdspm->card_name = "RME MADI";
6511 hdspm->midiPorts = 3;
6512 break;
6513 case HDSPM_RAYDAT_REV:
6514 hdspm->io_type = RayDAT;
6515 hdspm->card_name = "RME RayDAT";
6516 hdspm->midiPorts = 2;
6517 break;
6518 case HDSPM_AIO_REV:
6519 hdspm->io_type = AIO;
6520 hdspm->card_name = "RME AIO";
6521 hdspm->midiPorts = 1;
6522 break;
6523 case HDSPM_MADIFACE_REV:
6524 hdspm->io_type = MADIface;
6525 hdspm->card_name = "RME MADIface";
6526 hdspm->midiPorts = 1;
6527 break;
6528 case HDSPM_AES_REV:
Adrian Knoth526ea862011-02-28 15:14:48 +01006529 case HDSPM_AES32_REV:
Adrian Knothbdd32552011-03-07 19:10:11 +01006530 case HDSPM_AES32_OLD_REV:
Adrian Knoth0dca1792011-01-26 19:32:14 +01006531 hdspm->io_type = AES32;
6532 hdspm->card_name = "RME AES32";
6533 hdspm->midiPorts = 2;
6534 break;
Adrian Knoth5027f342011-02-28 15:14:49 +01006535 default:
6536 snd_printk(KERN_ERR "HDSPM: unknown firmware revision %x\n",
6537 hdspm->firmware_rev);
6538 return -ENODEV;
Remy Bruno3cee5a62006-10-16 12:46:32 +02006539 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006540
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006541 err = pci_enable_device(pci);
6542 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006543 return err;
6544
6545 pci_set_master(hdspm->pci);
6546
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006547 err = pci_request_regions(pci, "hdspm");
6548 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006549 return err;
6550
6551 hdspm->port = pci_resource_start(pci, 0);
6552 io_extent = pci_resource_len(pci, 0);
6553
6554 snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006555 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006556
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006557 hdspm->iobase = ioremap_nocache(hdspm->port, io_extent);
6558 if (!hdspm->iobase) {
6559 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006560 "unable to remap region 0x%lx-0x%lx\n",
6561 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006562 return -EBUSY;
6563 }
6564 snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006565 (unsigned long)hdspm->iobase, hdspm->port,
6566 hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006567
6568 if (request_irq(pci->irq, snd_hdspm_interrupt,
Takashi Iwai934c2b62011-06-10 16:36:37 +02006569 IRQF_SHARED, KBUILD_MODNAME, hdspm)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006570 snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
6571 return -EBUSY;
6572 }
6573
6574 snd_printdd("use IRQ %d\n", pci->irq);
6575
6576 hdspm->irq = pci->irq;
Takashi Iwai763f3562005-06-03 11:25:34 +02006577
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006578 snd_printdd("kmalloc Mixer memory of %zd Bytes\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006579 sizeof(struct hdspm_mixer));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006580 hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL);
6581 if (!hdspm->mixer) {
6582 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006583 "unable to kmalloc Mixer memory of %d Bytes\n",
6584 (int)sizeof(struct hdspm_mixer));
Takashi Iwai763f3562005-06-03 11:25:34 +02006585 return err;
6586 }
6587
Adrian Knoth0dca1792011-01-26 19:32:14 +01006588 hdspm->port_names_in = NULL;
6589 hdspm->port_names_out = NULL;
6590
6591 switch (hdspm->io_type) {
6592 case AES32:
Adrian Knothd2d10a22011-02-28 15:14:47 +01006593 hdspm->ss_in_channels = hdspm->ss_out_channels = AES32_CHANNELS;
6594 hdspm->ds_in_channels = hdspm->ds_out_channels = AES32_CHANNELS;
6595 hdspm->qs_in_channels = hdspm->qs_out_channels = AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006596
6597 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6598 channel_map_aes32;
6599 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6600 channel_map_aes32;
6601 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6602 channel_map_aes32;
6603 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6604 texts_ports_aes32;
6605 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6606 texts_ports_aes32;
6607 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6608 texts_ports_aes32;
6609
Adrian Knothd2d10a22011-02-28 15:14:47 +01006610 hdspm->max_channels_out = hdspm->max_channels_in =
6611 AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006612 hdspm->port_names_in = hdspm->port_names_out =
6613 texts_ports_aes32;
6614 hdspm->channel_map_in = hdspm->channel_map_out =
6615 channel_map_aes32;
6616
Adrian Knoth0dca1792011-01-26 19:32:14 +01006617 break;
6618
6619 case MADI:
6620 case MADIface:
6621 hdspm->ss_in_channels = hdspm->ss_out_channels =
6622 MADI_SS_CHANNELS;
6623 hdspm->ds_in_channels = hdspm->ds_out_channels =
6624 MADI_DS_CHANNELS;
6625 hdspm->qs_in_channels = hdspm->qs_out_channels =
6626 MADI_QS_CHANNELS;
6627
6628 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6629 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006630 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006631 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006632 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006633 channel_map_unity_ss;
6634
6635 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6636 texts_ports_madi;
6637 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6638 texts_ports_madi;
6639 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6640 texts_ports_madi;
6641 break;
6642
6643 case AIO:
6644 if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) {
6645 snd_printk(KERN_INFO "HDSPM: AEB input board found, but not supported\n");
6646 }
6647
6648 hdspm->ss_in_channels = AIO_IN_SS_CHANNELS;
6649 hdspm->ds_in_channels = AIO_IN_DS_CHANNELS;
6650 hdspm->qs_in_channels = AIO_IN_QS_CHANNELS;
6651 hdspm->ss_out_channels = AIO_OUT_SS_CHANNELS;
6652 hdspm->ds_out_channels = AIO_OUT_DS_CHANNELS;
6653 hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS;
6654
6655 hdspm->channel_map_out_ss = channel_map_aio_out_ss;
6656 hdspm->channel_map_out_ds = channel_map_aio_out_ds;
6657 hdspm->channel_map_out_qs = channel_map_aio_out_qs;
6658
6659 hdspm->channel_map_in_ss = channel_map_aio_in_ss;
6660 hdspm->channel_map_in_ds = channel_map_aio_in_ds;
6661 hdspm->channel_map_in_qs = channel_map_aio_in_qs;
6662
6663 hdspm->port_names_in_ss = texts_ports_aio_in_ss;
6664 hdspm->port_names_out_ss = texts_ports_aio_out_ss;
6665 hdspm->port_names_in_ds = texts_ports_aio_in_ds;
6666 hdspm->port_names_out_ds = texts_ports_aio_out_ds;
6667 hdspm->port_names_in_qs = texts_ports_aio_in_qs;
6668 hdspm->port_names_out_qs = texts_ports_aio_out_qs;
6669
6670 break;
6671
6672 case RayDAT:
6673 hdspm->ss_in_channels = hdspm->ss_out_channels =
6674 RAYDAT_SS_CHANNELS;
6675 hdspm->ds_in_channels = hdspm->ds_out_channels =
6676 RAYDAT_DS_CHANNELS;
6677 hdspm->qs_in_channels = hdspm->qs_out_channels =
6678 RAYDAT_QS_CHANNELS;
6679
6680 hdspm->max_channels_in = RAYDAT_SS_CHANNELS;
6681 hdspm->max_channels_out = RAYDAT_SS_CHANNELS;
6682
6683 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6684 channel_map_raydat_ss;
6685 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6686 channel_map_raydat_ds;
6687 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6688 channel_map_raydat_qs;
6689 hdspm->channel_map_in = hdspm->channel_map_out =
6690 channel_map_raydat_ss;
6691
6692 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6693 texts_ports_raydat_ss;
6694 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6695 texts_ports_raydat_ds;
6696 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6697 texts_ports_raydat_qs;
6698
6699
6700 break;
6701
6702 }
6703
6704 /* TCO detection */
6705 switch (hdspm->io_type) {
6706 case AIO:
6707 case RayDAT:
6708 if (hdspm_read(hdspm, HDSPM_statusRegister2) &
6709 HDSPM_s2_tco_detect) {
6710 hdspm->midiPorts++;
6711 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6712 GFP_KERNEL);
6713 if (NULL != hdspm->tco) {
6714 hdspm_tco_write(hdspm);
6715 }
6716 snd_printk(KERN_INFO "HDSPM: AIO/RayDAT TCO module found\n");
6717 } else {
6718 hdspm->tco = NULL;
6719 }
6720 break;
6721
6722 case MADI:
6723 if (hdspm_read(hdspm, HDSPM_statusRegister) & HDSPM_tco_detect) {
6724 hdspm->midiPorts++;
6725 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6726 GFP_KERNEL);
6727 if (NULL != hdspm->tco) {
6728 hdspm_tco_write(hdspm);
6729 }
6730 snd_printk(KERN_INFO "HDSPM: MADI TCO module found\n");
6731 } else {
6732 hdspm->tco = NULL;
6733 }
6734 break;
6735
6736 default:
6737 hdspm->tco = NULL;
6738 }
6739
6740 /* texts */
6741 switch (hdspm->io_type) {
6742 case AES32:
6743 if (hdspm->tco) {
6744 hdspm->texts_autosync = texts_autosync_aes_tco;
6745 hdspm->texts_autosync_items = 10;
6746 } else {
6747 hdspm->texts_autosync = texts_autosync_aes;
6748 hdspm->texts_autosync_items = 9;
6749 }
6750 break;
6751
6752 case MADI:
6753 if (hdspm->tco) {
6754 hdspm->texts_autosync = texts_autosync_madi_tco;
6755 hdspm->texts_autosync_items = 4;
6756 } else {
6757 hdspm->texts_autosync = texts_autosync_madi;
6758 hdspm->texts_autosync_items = 3;
6759 }
6760 break;
6761
6762 case MADIface:
6763
6764 break;
6765
6766 case RayDAT:
6767 if (hdspm->tco) {
6768 hdspm->texts_autosync = texts_autosync_raydat_tco;
6769 hdspm->texts_autosync_items = 9;
6770 } else {
6771 hdspm->texts_autosync = texts_autosync_raydat;
6772 hdspm->texts_autosync_items = 8;
6773 }
6774 break;
6775
6776 case AIO:
6777 if (hdspm->tco) {
6778 hdspm->texts_autosync = texts_autosync_aio_tco;
6779 hdspm->texts_autosync_items = 6;
6780 } else {
6781 hdspm->texts_autosync = texts_autosync_aio;
6782 hdspm->texts_autosync_items = 5;
6783 }
6784 break;
6785
6786 }
6787
6788 tasklet_init(&hdspm->midi_tasklet,
6789 hdspm_midi_tasklet, (unsigned long) hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006790
6791 snd_printdd("create alsa devices.\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006792 err = snd_hdspm_create_alsa_devices(card, hdspm);
6793 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006794 return err;
6795
6796 snd_hdspm_initialize_midi_flush(hdspm);
6797
6798 return 0;
6799}
6800
Adrian Knoth0dca1792011-01-26 19:32:14 +01006801
Takashi Iwai98274f02005-11-17 14:52:34 +01006802static int snd_hdspm_free(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006803{
6804
6805 if (hdspm->port) {
6806
6807 /* stop th audio, and cancel all interrupts */
6808 hdspm->control_register &=
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006809 ~(HDSPM_Start | HDSPM_AudioInterruptEnable |
Adrian Knoth0dca1792011-01-26 19:32:14 +01006810 HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable |
6811 HDSPM_Midi2InterruptEnable | HDSPM_Midi3InterruptEnable);
Takashi Iwai763f3562005-06-03 11:25:34 +02006812 hdspm_write(hdspm, HDSPM_controlRegister,
6813 hdspm->control_register);
6814 }
6815
6816 if (hdspm->irq >= 0)
6817 free_irq(hdspm->irq, (void *) hdspm);
6818
Jesper Juhlfc584222005-10-24 15:11:28 +02006819 kfree(hdspm->mixer);
Takashi Iwai763f3562005-06-03 11:25:34 +02006820
6821 if (hdspm->iobase)
6822 iounmap(hdspm->iobase);
6823
Takashi Iwai763f3562005-06-03 11:25:34 +02006824 if (hdspm->port)
6825 pci_release_regions(hdspm->pci);
6826
6827 pci_disable_device(hdspm->pci);
6828 return 0;
6829}
6830
Adrian Knoth0dca1792011-01-26 19:32:14 +01006831
Takashi Iwai98274f02005-11-17 14:52:34 +01006832static void snd_hdspm_card_free(struct snd_card *card)
Takashi Iwai763f3562005-06-03 11:25:34 +02006833{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006834 struct hdspm *hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006835
6836 if (hdspm)
6837 snd_hdspm_free(hdspm);
6838}
6839
Adrian Knoth0dca1792011-01-26 19:32:14 +01006840
Takashi Iwai763f3562005-06-03 11:25:34 +02006841static int __devinit snd_hdspm_probe(struct pci_dev *pci,
6842 const struct pci_device_id *pci_id)
6843{
6844 static int dev;
Takashi Iwai98274f02005-11-17 14:52:34 +01006845 struct hdspm *hdspm;
6846 struct snd_card *card;
Takashi Iwai763f3562005-06-03 11:25:34 +02006847 int err;
6848
6849 if (dev >= SNDRV_CARDS)
6850 return -ENODEV;
6851 if (!enable[dev]) {
6852 dev++;
6853 return -ENOENT;
6854 }
6855
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006856 err = snd_card_create(index[dev], id[dev],
Adrian Knoth0dca1792011-01-26 19:32:14 +01006857 THIS_MODULE, sizeof(struct hdspm), &card);
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006858 if (err < 0)
6859 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006860
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006861 hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006862 card->private_free = snd_hdspm_card_free;
6863 hdspm->dev = dev;
6864 hdspm->pci = pci;
6865
Takashi Iwaic187c042007-02-19 15:27:33 +01006866 snd_card_set_dev(card, &pci->dev);
6867
Adrian Knoth0dca1792011-01-26 19:32:14 +01006868 err = snd_hdspm_create(card, hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006869 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006870 snd_card_free(card);
6871 return err;
6872 }
6873
Adrian Knoth0dca1792011-01-26 19:32:14 +01006874 if (hdspm->io_type != MADIface) {
6875 sprintf(card->shortname, "%s_%x",
6876 hdspm->card_name,
6877 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF);
6878 sprintf(card->longname, "%s S/N 0x%x at 0x%lx, irq %d",
6879 hdspm->card_name,
6880 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF,
6881 hdspm->port, hdspm->irq);
6882 } else {
6883 sprintf(card->shortname, "%s", hdspm->card_name);
6884 sprintf(card->longname, "%s at 0x%lx, irq %d",
6885 hdspm->card_name, hdspm->port, hdspm->irq);
6886 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006887
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006888 err = snd_card_register(card);
6889 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006890 snd_card_free(card);
6891 return err;
6892 }
6893
6894 pci_set_drvdata(pci, card);
6895
6896 dev++;
6897 return 0;
6898}
6899
6900static void __devexit snd_hdspm_remove(struct pci_dev *pci)
6901{
6902 snd_card_free(pci_get_drvdata(pci));
6903 pci_set_drvdata(pci, NULL);
6904}
6905
6906static struct pci_driver driver = {
Takashi Iwai3733e422011-06-10 16:20:20 +02006907 .name = KBUILD_MODNAME,
Takashi Iwai763f3562005-06-03 11:25:34 +02006908 .id_table = snd_hdspm_ids,
6909 .probe = snd_hdspm_probe,
6910 .remove = __devexit_p(snd_hdspm_remove),
6911};
6912
6913
6914static int __init alsa_card_hdspm_init(void)
6915{
6916 return pci_register_driver(&driver);
6917}
6918
6919static void __exit alsa_card_hdspm_exit(void)
6920{
6921 pci_unregister_driver(&driver);
6922}
6923
6924module_init(alsa_card_hdspm_init)
6925module_exit(alsa_card_hdspm_exit)