blob: e070ea85c30a3ae9e7b10812fd2df4c17c82561a [file] [log] [blame]
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001/*
Takashi Iwai763f3562005-06-03 11:25:34 +02002 * ALSA driver for RME Hammerfall DSP MADI audio interface(s)
3 *
4 * Copyright (c) 2003 Winfried Ritsch (IEM)
5 * code based on hdsp.c Paul Davis
6 * Marcus Andersson
7 * Thomas Charbonnel
Remy Bruno3cee5a62006-10-16 12:46:32 +02008 * Modified 2006-06-01 for AES32 support by Remy Bruno
9 * <remy.bruno@trinnov.com>
Takashi Iwai763f3562005-06-03 11:25:34 +020010 *
Adrian Knoth0dca1792011-01-26 19:32:14 +010011 * Modified 2009-04-13 for proper metering by Florian Faber
12 * <faber@faberman.de>
13 *
14 * Modified 2009-04-14 for native float support by Florian Faber
15 * <faber@faberman.de>
16 *
17 * Modified 2009-04-26 fixed bug in rms metering by Florian Faber
18 * <faber@faberman.de>
19 *
20 * Modified 2009-04-30 added hw serial number support by Florian Faber
21 *
22 * Modified 2011-01-14 added S/PDIF input on RayDATs by Adrian Knoth
23 *
24 * Modified 2011-01-25 variable period sizes on RayDAT/AIO by Adrian Knoth
25 *
Takashi Iwai763f3562005-06-03 11:25:34 +020026 * This program is free software; you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License as published by
28 * the Free Software Foundation; either version 2 of the License, or
29 * (at your option) any later version.
30 *
31 * This program is distributed in the hope that it will be useful,
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 * GNU General Public License for more details.
35 *
36 * You should have received a copy of the GNU General Public License
37 * along with this program; if not, write to the Free Software
38 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 *
40 */
Takashi Iwai763f3562005-06-03 11:25:34 +020041#include <linux/init.h>
42#include <linux/delay.h>
43#include <linux/interrupt.h>
Paul Gortmaker65a77212011-07-15 13:13:37 -040044#include <linux/module.h>
Takashi Iwai763f3562005-06-03 11:25:34 +020045#include <linux/slab.h>
46#include <linux/pci.h>
Takashi Iwai3f7440a2009-06-05 17:40:04 +020047#include <linux/math64.h>
Takashi Iwai763f3562005-06-03 11:25:34 +020048#include <asm/io.h>
49
50#include <sound/core.h>
51#include <sound/control.h>
52#include <sound/pcm.h>
Adrian Knoth0dca1792011-01-26 19:32:14 +010053#include <sound/pcm_params.h>
Takashi Iwai763f3562005-06-03 11:25:34 +020054#include <sound/info.h>
55#include <sound/asoundef.h>
56#include <sound/rawmidi.h>
57#include <sound/hwdep.h>
58#include <sound/initval.h>
59
60#include <sound/hdspm.h>
61
62static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
63static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
Rusty Russella67ff6a2011-12-15 13:49:36 +103064static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
Takashi Iwai763f3562005-06-03 11:25:34 +020065
Takashi Iwai763f3562005-06-03 11:25:34 +020066module_param_array(index, int, NULL, 0444);
67MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");
68
69module_param_array(id, charp, NULL, 0444);
70MODULE_PARM_DESC(id, "ID string for RME HDSPM interface.");
71
72module_param_array(enable, bool, NULL, 0444);
73MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");
74
Takashi Iwai763f3562005-06-03 11:25:34 +020075
76MODULE_AUTHOR
Adrian Knoth0dca1792011-01-26 19:32:14 +010077(
78 "Winfried Ritsch <ritsch_AT_iem.at>, "
79 "Paul Davis <paul@linuxaudiosystems.com>, "
80 "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, "
81 "Remy Bruno <remy.bruno@trinnov.com>, "
82 "Florian Faber <faberman@linuxproaudio.org>, "
83 "Adrian Knoth <adi@drcomp.erfurt.thur.de>"
84);
Takashi Iwai763f3562005-06-03 11:25:34 +020085MODULE_DESCRIPTION("RME HDSPM");
86MODULE_LICENSE("GPL");
87MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
88
Adrian Knoth0dca1792011-01-26 19:32:14 +010089/* --- Write registers. ---
Takashi Iwai763f3562005-06-03 11:25:34 +020090 These are defined as byte-offsets from the iobase value. */
91
Adrian Knoth0dca1792011-01-26 19:32:14 +010092#define HDSPM_WR_SETTINGS 0
93#define HDSPM_outputBufferAddress 32
94#define HDSPM_inputBufferAddress 36
Takashi Iwai763f3562005-06-03 11:25:34 +020095#define HDSPM_controlRegister 64
96#define HDSPM_interruptConfirmation 96
97#define HDSPM_control2Reg 256 /* not in specs ???????? */
Remy Brunoffb2c3c2007-03-07 19:08:46 +010098#define HDSPM_freqReg 256 /* for AES32 */
Adrian Knoth0dca1792011-01-26 19:32:14 +010099#define HDSPM_midiDataOut0 352 /* just believe in old code */
100#define HDSPM_midiDataOut1 356
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100101#define HDSPM_eeprom_wr 384 /* for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200102
103/* DMA enable for 64 channels, only Bit 0 is relevant */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100104#define HDSPM_outputEnableBase 512 /* 512-767 input DMA */
Takashi Iwai763f3562005-06-03 11:25:34 +0200105#define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */
106
Adrian Knoth0dca1792011-01-26 19:32:14 +0100107/* 16 page addresses for each of the 64 channels DMA buffer in and out
Takashi Iwai763f3562005-06-03 11:25:34 +0200108 (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */
109#define HDSPM_pageAddressBufferOut 8192
110#define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4)
111
112#define HDSPM_MADI_mixerBase 32768 /* 32768-65535 for 2x64x64 Fader */
113
114#define HDSPM_MATRIX_MIXER_SIZE 8192 /* = 2*64*64 * 4 Byte => 32kB */
115
116/* --- Read registers. ---
117 These are defined as byte-offsets from the iobase value */
118#define HDSPM_statusRegister 0
Remy Bruno3cee5a62006-10-16 12:46:32 +0200119/*#define HDSPM_statusRegister2 96 */
120/* after RME Windows driver sources, status2 is 4-byte word # 48 = word at
121 * offset 192, for AES32 *and* MADI
122 * => need to check that offset 192 is working on MADI */
123#define HDSPM_statusRegister2 192
124#define HDSPM_timecodeRegister 128
Takashi Iwai763f3562005-06-03 11:25:34 +0200125
Adrian Knoth0dca1792011-01-26 19:32:14 +0100126/* AIO, RayDAT */
127#define HDSPM_RD_STATUS_0 0
128#define HDSPM_RD_STATUS_1 64
129#define HDSPM_RD_STATUS_2 128
130#define HDSPM_RD_STATUS_3 192
131
132#define HDSPM_RD_TCO 256
133#define HDSPM_RD_PLL_FREQ 512
134#define HDSPM_WR_TCO 128
135
136#define HDSPM_TCO1_TCO_lock 0x00000001
137#define HDSPM_TCO1_WCK_Input_Range_LSB 0x00000002
138#define HDSPM_TCO1_WCK_Input_Range_MSB 0x00000004
139#define HDSPM_TCO1_LTC_Input_valid 0x00000008
140#define HDSPM_TCO1_WCK_Input_valid 0x00000010
141#define HDSPM_TCO1_Video_Input_Format_NTSC 0x00000020
142#define HDSPM_TCO1_Video_Input_Format_PAL 0x00000040
143
144#define HDSPM_TCO1_set_TC 0x00000100
145#define HDSPM_TCO1_set_drop_frame_flag 0x00000200
146#define HDSPM_TCO1_LTC_Format_LSB 0x00000400
147#define HDSPM_TCO1_LTC_Format_MSB 0x00000800
148
149#define HDSPM_TCO2_TC_run 0x00010000
150#define HDSPM_TCO2_WCK_IO_ratio_LSB 0x00020000
151#define HDSPM_TCO2_WCK_IO_ratio_MSB 0x00040000
152#define HDSPM_TCO2_set_num_drop_frames_LSB 0x00080000
153#define HDSPM_TCO2_set_num_drop_frames_MSB 0x00100000
154#define HDSPM_TCO2_set_jam_sync 0x00200000
155#define HDSPM_TCO2_set_flywheel 0x00400000
156
157#define HDSPM_TCO2_set_01_4 0x01000000
158#define HDSPM_TCO2_set_pull_down 0x02000000
159#define HDSPM_TCO2_set_pull_up 0x04000000
160#define HDSPM_TCO2_set_freq 0x08000000
161#define HDSPM_TCO2_set_term_75R 0x10000000
162#define HDSPM_TCO2_set_input_LSB 0x20000000
163#define HDSPM_TCO2_set_input_MSB 0x40000000
164#define HDSPM_TCO2_set_freq_from_app 0x80000000
165
166
167#define HDSPM_midiDataOut0 352
168#define HDSPM_midiDataOut1 356
169#define HDSPM_midiDataOut2 368
170
Takashi Iwai763f3562005-06-03 11:25:34 +0200171#define HDSPM_midiDataIn0 360
172#define HDSPM_midiDataIn1 364
Adrian Knoth0dca1792011-01-26 19:32:14 +0100173#define HDSPM_midiDataIn2 372
174#define HDSPM_midiDataIn3 376
Takashi Iwai763f3562005-06-03 11:25:34 +0200175
176/* status is data bytes in MIDI-FIFO (0-128) */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100177#define HDSPM_midiStatusOut0 384
178#define HDSPM_midiStatusOut1 388
179#define HDSPM_midiStatusOut2 400
180
181#define HDSPM_midiStatusIn0 392
182#define HDSPM_midiStatusIn1 396
183#define HDSPM_midiStatusIn2 404
184#define HDSPM_midiStatusIn3 408
Takashi Iwai763f3562005-06-03 11:25:34 +0200185
186
187/* the meters are regular i/o-mapped registers, but offset
188 considerably from the rest. the peak registers are reset
Adrian Knoth0dca1792011-01-26 19:32:14 +0100189 when read; the least-significant 4 bits are full-scale counters;
Takashi Iwai763f3562005-06-03 11:25:34 +0200190 the actual peak value is in the most-significant 24 bits.
191*/
Adrian Knoth0dca1792011-01-26 19:32:14 +0100192
193#define HDSPM_MADI_INPUT_PEAK 4096
194#define HDSPM_MADI_PLAYBACK_PEAK 4352
195#define HDSPM_MADI_OUTPUT_PEAK 4608
196
197#define HDSPM_MADI_INPUT_RMS_L 6144
198#define HDSPM_MADI_PLAYBACK_RMS_L 6400
199#define HDSPM_MADI_OUTPUT_RMS_L 6656
200
201#define HDSPM_MADI_INPUT_RMS_H 7168
202#define HDSPM_MADI_PLAYBACK_RMS_H 7424
203#define HDSPM_MADI_OUTPUT_RMS_H 7680
Takashi Iwai763f3562005-06-03 11:25:34 +0200204
205/* --- Control Register bits --------- */
206#define HDSPM_Start (1<<0) /* start engine */
207
208#define HDSPM_Latency0 (1<<1) /* buffer size = 2^n */
209#define HDSPM_Latency1 (1<<2) /* where n is defined */
210#define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */
211
Adrian Knoth0dca1792011-01-26 19:32:14 +0100212#define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Autosync */
213#define HDSPM_c0Master 0x1 /* Master clock bit in settings
214 register [RayDAT, AIO] */
Takashi Iwai763f3562005-06-03 11:25:34 +0200215
216#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */
217
218#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */
219#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */
220#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200221#define HDSPM_QuadSpeed (1<<31) /* quad speed bit */
Takashi Iwai763f3562005-06-03 11:25:34 +0200222
Remy Bruno3cee5a62006-10-16 12:46:32 +0200223#define HDSPM_Professional (1<<9) /* Professional */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200224#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200225 56channelMODE=0 */ /* MADI ONLY*/
226#define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200227
Adrian Knoth0dca1792011-01-26 19:32:14 +0100228#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200229 0=off, 1=on */ /* MADI ONLY */
230#define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200231
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200232#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax
233 * -- MADI ONLY
234 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200235#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
236
Remy Bruno3cee5a62006-10-16 12:46:32 +0200237#define HDSPM_SyncRef2 (1<<13)
238#define HDSPM_SyncRef3 (1<<25)
Takashi Iwai763f3562005-06-03 11:25:34 +0200239
Remy Bruno3cee5a62006-10-16 12:46:32 +0200240#define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100241#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use
Takashi Iwai763f3562005-06-03 11:25:34 +0200242 AES additional bits in
243 lower 5 Audiodatabits ??? */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200244#define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */
245#define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200246
Adrian Knoth0dca1792011-01-26 19:32:14 +0100247#define HDSPM_Midi0InterruptEnable 0x0400000
248#define HDSPM_Midi1InterruptEnable 0x0800000
249#define HDSPM_Midi2InterruptEnable 0x0200000
250#define HDSPM_Midi3InterruptEnable 0x4000000
Takashi Iwai763f3562005-06-03 11:25:34 +0200251
252#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100253#define HDSPe_FLOAT_FORMAT 0x2000000
Takashi Iwai763f3562005-06-03 11:25:34 +0200254
Remy Bruno3cee5a62006-10-16 12:46:32 +0200255#define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */
256#define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */
257#define HDSPM_QS_QuadWire (1<<28) /* AES32 ONLY */
258
259#define HDSPM_wclk_sel (1<<30)
Takashi Iwai763f3562005-06-03 11:25:34 +0200260
261/* --- bit helper defines */
262#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200263#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|\
264 HDSPM_DoubleSpeed|HDSPM_QuadSpeed)
Takashi Iwai763f3562005-06-03 11:25:34 +0200265#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1)
266#define HDSPM_InputOptical 0
267#define HDSPM_InputCoaxial (HDSPM_InputSelect0)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200268#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\
269 HDSPM_SyncRef2|HDSPM_SyncRef3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200270
Adrian Knoth0dca1792011-01-26 19:32:14 +0100271#define HDSPM_c0_SyncRef0 0x2
272#define HDSPM_c0_SyncRef1 0x4
273#define HDSPM_c0_SyncRef2 0x8
274#define HDSPM_c0_SyncRef3 0x10
275#define HDSPM_c0_SyncRefMask (HDSPM_c0_SyncRef0 | HDSPM_c0_SyncRef1 |\
276 HDSPM_c0_SyncRef2 | HDSPM_c0_SyncRef3)
277
278#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */
279#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */
280#define HDSPM_SYNC_FROM_TCO 2
281#define HDSPM_SYNC_FROM_SYNC_IN 3
Takashi Iwai763f3562005-06-03 11:25:34 +0200282
283#define HDSPM_Frequency32KHz HDSPM_Frequency0
284#define HDSPM_Frequency44_1KHz HDSPM_Frequency1
285#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0)
286#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0)
287#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200288#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|\
289 HDSPM_Frequency0)
Remy Bruno3cee5a62006-10-16 12:46:32 +0200290#define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0)
291#define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200292#define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\
293 HDSPM_Frequency0)
Takashi Iwai763f3562005-06-03 11:25:34 +0200294
Takashi Iwai763f3562005-06-03 11:25:34 +0200295
296/* Synccheck Status */
297#define HDSPM_SYNC_CHECK_NO_LOCK 0
298#define HDSPM_SYNC_CHECK_LOCK 1
299#define HDSPM_SYNC_CHECK_SYNC 2
300
301/* AutoSync References - used by "autosync_ref" control switch */
302#define HDSPM_AUTOSYNC_FROM_WORD 0
303#define HDSPM_AUTOSYNC_FROM_MADI 1
Adrian Knoth0dca1792011-01-26 19:32:14 +0100304#define HDSPM_AUTOSYNC_FROM_TCO 2
305#define HDSPM_AUTOSYNC_FROM_SYNC_IN 3
306#define HDSPM_AUTOSYNC_FROM_NONE 4
Takashi Iwai763f3562005-06-03 11:25:34 +0200307
308/* Possible sources of MADI input */
309#define HDSPM_OPTICAL 0 /* optical */
310#define HDSPM_COAXIAL 1 /* BNC */
311
312#define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask)
Adrian Knoth0dca1792011-01-26 19:32:14 +0100313#define hdspm_decode_latency(x) ((((x) & HDSPM_LatencyMask)>>1))
Takashi Iwai763f3562005-06-03 11:25:34 +0200314
315#define hdspm_encode_in(x) (((x)&0x3)<<14)
316#define hdspm_decode_in(x) (((x)>>14)&0x3)
317
318/* --- control2 register bits --- */
319#define HDSPM_TMS (1<<0)
320#define HDSPM_TCK (1<<1)
321#define HDSPM_TDI (1<<2)
322#define HDSPM_JTAG (1<<3)
323#define HDSPM_PWDN (1<<4)
324#define HDSPM_PROGRAM (1<<5)
325#define HDSPM_CONFIG_MODE_0 (1<<6)
326#define HDSPM_CONFIG_MODE_1 (1<<7)
327/*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/
328#define HDSPM_BIGENDIAN_MODE (1<<9)
329#define HDSPM_RD_MULTIPLE (1<<10)
330
Remy Bruno3cee5a62006-10-16 12:46:32 +0200331/* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200332 that do not conflict with specific bits for AES32 seem to be valid also
333 for the AES32
334 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200335#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200336#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn MODE=0 */
337#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1
338 * (like inp0)
339 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100340
Takashi Iwai763f3562005-06-03 11:25:34 +0200341#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100342#define HDSPM_madiSync (1<<18) /* MADI is in sync */
343
344#define HDSPM_tcoLock 0x00000020 /* Optional TCO locked status FOR HDSPe MADI! */
345#define HDSPM_tcoSync 0x10000000 /* Optional TCO sync status */
346
347#define HDSPM_syncInLock 0x00010000 /* Sync In lock status FOR HDSPe MADI! */
348#define HDSPM_syncInSync 0x00020000 /* Sync In sync status FOR HDSPe MADI! */
Takashi Iwai763f3562005-06-03 11:25:34 +0200349
350#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100351 /* since 64byte accurate, last 6 bits are not used */
Takashi Iwai763f3562005-06-03 11:25:34 +0200352
Adrian Knoth0dca1792011-01-26 19:32:14 +0100353
354
Takashi Iwai763f3562005-06-03 11:25:34 +0200355#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */
356
357#define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */
358#define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */
359#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */
360#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */
361
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200362#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with
363 * Interrupt
364 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100365#define HDSPM_tco_detect 0x08000000
366#define HDSPM_tco_lock 0x20000000
367
368#define HDSPM_s2_tco_detect 0x00000040
369#define HDSPM_s2_AEBO_D 0x00000080
370#define HDSPM_s2_AEBI_D 0x00000100
371
372
373#define HDSPM_midi0IRQPending 0x40000000
374#define HDSPM_midi1IRQPending 0x80000000
375#define HDSPM_midi2IRQPending 0x20000000
376#define HDSPM_midi2IRQPendingAES 0x00000020
377#define HDSPM_midi3IRQPending 0x00200000
Takashi Iwai763f3562005-06-03 11:25:34 +0200378
379/* --- status bit helpers */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200380#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\
381 HDSPM_madiFreq2|HDSPM_madiFreq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200382#define HDSPM_madiFreq32 (HDSPM_madiFreq0)
383#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1)
384#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1)
385#define HDSPM_madiFreq64 (HDSPM_madiFreq2)
386#define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2)
387#define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2)
388#define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2)
389#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
390#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0)
391
Remy Bruno3cee5a62006-10-16 12:46:32 +0200392/* Status2 Register bits */ /* MADI ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200393
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300394#define HDSPM_version0 (1<<0) /* not really defined but I guess */
Takashi Iwai763f3562005-06-03 11:25:34 +0200395#define HDSPM_version1 (1<<1) /* in former cards it was ??? */
396#define HDSPM_version2 (1<<2)
397
398#define HDSPM_wcLock (1<<3) /* Wordclock is detected and locked */
399#define HDSPM_wcSync (1<<4) /* Wordclock is in sync with systemclock */
400
401#define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */
402#define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */
Adrian Knotha8cd7142013-05-31 12:57:09 +0200403#define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, 111=128 */
404#define HDSPM_wc_freq3 0x800 /* 1000=176.4, 1001=192 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200405
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
Adrian Knotha8cd7142013-05-31 12:57:09 +0200415#define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2|\
416 HDSPM_wc_freq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200417#define HDSPM_wcFreq32 (HDSPM_wc_freq0)
418#define HDSPM_wcFreq44_1 (HDSPM_wc_freq1)
419#define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1)
420#define HDSPM_wcFreq64 (HDSPM_wc_freq2)
421#define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2)
422#define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2)
Adrian Knotha8cd7142013-05-31 12:57:09 +0200423#define HDSPM_wcFreq128 (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2)
424#define HDSPM_wcFreq176_4 (HDSPM_wc_freq3)
425#define HDSPM_wcFreq192 (HDSPM_wc_freq0|HDSPM_wc_freq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200426
Adrian Knoth0dca1792011-01-26 19:32:14 +0100427#define HDSPM_status1_F_0 0x0400000
428#define HDSPM_status1_F_1 0x0800000
429#define HDSPM_status1_F_2 0x1000000
430#define HDSPM_status1_F_3 0x2000000
431#define HDSPM_status1_freqMask (HDSPM_status1_F_0|HDSPM_status1_F_1|HDSPM_status1_F_2|HDSPM_status1_F_3)
432
Takashi Iwai763f3562005-06-03 11:25:34 +0200433
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200434#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
435 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200436#define HDSPM_SelSyncRef_WORD 0
437#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0)
Adrian Knoth0dca1792011-01-26 19:32:14 +0100438#define HDSPM_SelSyncRef_TCO (HDSPM_SelSyncRef1)
439#define HDSPM_SelSyncRef_SyncIn (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200440#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
441 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200442
Remy Bruno3cee5a62006-10-16 12:46:32 +0200443/*
444 For AES32, bits for status, status2 and timecode are different
445*/
446/* status */
447#define HDSPM_AES32_wcLock 0x0200000
Andre Schramm56bde0f2013-01-09 14:40:18 +0100448#define HDSPM_AES32_wcSync 0x0100000
Remy Bruno3cee5a62006-10-16 12:46:32 +0200449#define HDSPM_AES32_wcFreq_bit 22
Adrian Knoth0dca1792011-01-26 19:32:14 +0100450/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function
Remy Bruno3cee5a62006-10-16 12:46:32 +0200451 HDSPM_bit2freq */
452#define HDSPM_AES32_syncref_bit 16
453/* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */
454
455#define HDSPM_AES32_AUTOSYNC_FROM_WORD 0
456#define HDSPM_AES32_AUTOSYNC_FROM_AES1 1
457#define HDSPM_AES32_AUTOSYNC_FROM_AES2 2
458#define HDSPM_AES32_AUTOSYNC_FROM_AES3 3
459#define HDSPM_AES32_AUTOSYNC_FROM_AES4 4
460#define HDSPM_AES32_AUTOSYNC_FROM_AES5 5
461#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6
462#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7
463#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8
Remy Bruno65345992007-08-31 12:21:08 +0200464#define HDSPM_AES32_AUTOSYNC_FROM_NONE 9
Remy Bruno3cee5a62006-10-16 12:46:32 +0200465
466/* status2 */
467/* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */
468#define HDSPM_LockAES 0x80
469#define HDSPM_LockAES1 0x80
470#define HDSPM_LockAES2 0x40
471#define HDSPM_LockAES3 0x20
472#define HDSPM_LockAES4 0x10
473#define HDSPM_LockAES5 0x8
474#define HDSPM_LockAES6 0x4
475#define HDSPM_LockAES7 0x2
476#define HDSPM_LockAES8 0x1
477/*
478 Timecode
479 After windows driver sources, bits 4*i to 4*i+3 give the input frequency on
480 AES i+1
481 bits 3210
482 0001 32kHz
483 0010 44.1kHz
484 0011 48kHz
485 0100 64kHz
486 0101 88.2kHz
487 0110 96kHz
488 0111 128kHz
489 1000 176.4kHz
490 1001 192kHz
491 NB: Timecode register doesn't seem to work on AES32 card revision 230
492*/
493
Takashi Iwai763f3562005-06-03 11:25:34 +0200494/* Mixer Values */
495#define UNITY_GAIN 32768 /* = 65536/2 */
496#define MINUS_INFINITY_GAIN 0
497
Takashi Iwai763f3562005-06-03 11:25:34 +0200498/* Number of channels for different Speed Modes */
499#define MADI_SS_CHANNELS 64
500#define MADI_DS_CHANNELS 32
501#define MADI_QS_CHANNELS 16
502
Adrian Knoth0dca1792011-01-26 19:32:14 +0100503#define RAYDAT_SS_CHANNELS 36
504#define RAYDAT_DS_CHANNELS 20
505#define RAYDAT_QS_CHANNELS 12
506
507#define AIO_IN_SS_CHANNELS 14
508#define AIO_IN_DS_CHANNELS 10
509#define AIO_IN_QS_CHANNELS 8
510#define AIO_OUT_SS_CHANNELS 16
511#define AIO_OUT_DS_CHANNELS 12
512#define AIO_OUT_QS_CHANNELS 10
513
Adrian Knothd2d10a22011-02-28 15:14:47 +0100514#define AES32_CHANNELS 16
515
Takashi Iwai763f3562005-06-03 11:25:34 +0200516/* the size of a substream (1 mono data stream) */
517#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024)
518#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
519
520/* the size of the area we need to allocate for DMA transfers. the
521 size is the same regardless of the number of channels, and
Adrian Knoth0dca1792011-01-26 19:32:14 +0100522 also the latency to use.
Takashi Iwai763f3562005-06-03 11:25:34 +0200523 for one direction !!!
524*/
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100525#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
Takashi Iwai763f3562005-06-03 11:25:34 +0200526#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
527
Adrian Knoth0dca1792011-01-26 19:32:14 +0100528#define HDSPM_RAYDAT_REV 211
529#define HDSPM_AIO_REV 212
530#define HDSPM_MADIFACE_REV 213
Remy Bruno3cee5a62006-10-16 12:46:32 +0200531
Remy Bruno65345992007-08-31 12:21:08 +0200532/* speed factor modes */
533#define HDSPM_SPEED_SINGLE 0
534#define HDSPM_SPEED_DOUBLE 1
535#define HDSPM_SPEED_QUAD 2
Adrian Knoth0dca1792011-01-26 19:32:14 +0100536
Remy Bruno65345992007-08-31 12:21:08 +0200537/* names for speed modes */
538static char *hdspm_speed_names[] = { "single", "double", "quad" };
539
Adrian Knoth0dca1792011-01-26 19:32:14 +0100540static char *texts_autosync_aes_tco[] = { "Word Clock",
541 "AES1", "AES2", "AES3", "AES4",
542 "AES5", "AES6", "AES7", "AES8",
543 "TCO" };
544static char *texts_autosync_aes[] = { "Word Clock",
545 "AES1", "AES2", "AES3", "AES4",
546 "AES5", "AES6", "AES7", "AES8" };
547static char *texts_autosync_madi_tco[] = { "Word Clock",
548 "MADI", "TCO", "Sync In" };
549static char *texts_autosync_madi[] = { "Word Clock",
550 "MADI", "Sync In" };
551
552static char *texts_autosync_raydat_tco[] = {
553 "Word Clock",
554 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
555 "AES", "SPDIF", "TCO", "Sync In"
556};
557static char *texts_autosync_raydat[] = {
558 "Word Clock",
559 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
560 "AES", "SPDIF", "Sync In"
561};
562static char *texts_autosync_aio_tco[] = {
563 "Word Clock",
564 "ADAT", "AES", "SPDIF", "TCO", "Sync In"
565};
566static char *texts_autosync_aio[] = { "Word Clock",
567 "ADAT", "AES", "SPDIF", "Sync In" };
568
569static char *texts_freq[] = {
570 "No Lock",
571 "32 kHz",
572 "44.1 kHz",
573 "48 kHz",
574 "64 kHz",
575 "88.2 kHz",
576 "96 kHz",
577 "128 kHz",
578 "176.4 kHz",
579 "192 kHz"
580};
581
Adrian Knoth0dca1792011-01-26 19:32:14 +0100582static char *texts_ports_madi[] = {
583 "MADI.1", "MADI.2", "MADI.3", "MADI.4", "MADI.5", "MADI.6",
584 "MADI.7", "MADI.8", "MADI.9", "MADI.10", "MADI.11", "MADI.12",
585 "MADI.13", "MADI.14", "MADI.15", "MADI.16", "MADI.17", "MADI.18",
586 "MADI.19", "MADI.20", "MADI.21", "MADI.22", "MADI.23", "MADI.24",
587 "MADI.25", "MADI.26", "MADI.27", "MADI.28", "MADI.29", "MADI.30",
588 "MADI.31", "MADI.32", "MADI.33", "MADI.34", "MADI.35", "MADI.36",
589 "MADI.37", "MADI.38", "MADI.39", "MADI.40", "MADI.41", "MADI.42",
590 "MADI.43", "MADI.44", "MADI.45", "MADI.46", "MADI.47", "MADI.48",
591 "MADI.49", "MADI.50", "MADI.51", "MADI.52", "MADI.53", "MADI.54",
592 "MADI.55", "MADI.56", "MADI.57", "MADI.58", "MADI.59", "MADI.60",
593 "MADI.61", "MADI.62", "MADI.63", "MADI.64",
594};
595
596
597static char *texts_ports_raydat_ss[] = {
598 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT1.5", "ADAT1.6",
599 "ADAT1.7", "ADAT1.8", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
600 "ADAT2.5", "ADAT2.6", "ADAT2.7", "ADAT2.8", "ADAT3.1", "ADAT3.2",
601 "ADAT3.3", "ADAT3.4", "ADAT3.5", "ADAT3.6", "ADAT3.7", "ADAT3.8",
602 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4", "ADAT4.5", "ADAT4.6",
603 "ADAT4.7", "ADAT4.8",
604 "AES.L", "AES.R",
605 "SPDIF.L", "SPDIF.R"
606};
607
608static char *texts_ports_raydat_ds[] = {
609 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4",
610 "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
611 "ADAT3.1", "ADAT3.2", "ADAT3.3", "ADAT3.4",
612 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4",
613 "AES.L", "AES.R",
614 "SPDIF.L", "SPDIF.R"
615};
616
617static char *texts_ports_raydat_qs[] = {
618 "ADAT1.1", "ADAT1.2",
619 "ADAT2.1", "ADAT2.2",
620 "ADAT3.1", "ADAT3.2",
621 "ADAT4.1", "ADAT4.2",
622 "AES.L", "AES.R",
623 "SPDIF.L", "SPDIF.R"
624};
625
626
627static char *texts_ports_aio_in_ss[] = {
628 "Analogue.L", "Analogue.R",
629 "AES.L", "AES.R",
630 "SPDIF.L", "SPDIF.R",
631 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
632 "ADAT.7", "ADAT.8"
633};
634
635static char *texts_ports_aio_out_ss[] = {
636 "Analogue.L", "Analogue.R",
637 "AES.L", "AES.R",
638 "SPDIF.L", "SPDIF.R",
639 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
640 "ADAT.7", "ADAT.8",
641 "Phone.L", "Phone.R"
642};
643
644static char *texts_ports_aio_in_ds[] = {
645 "Analogue.L", "Analogue.R",
646 "AES.L", "AES.R",
647 "SPDIF.L", "SPDIF.R",
648 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
649};
650
651static char *texts_ports_aio_out_ds[] = {
652 "Analogue.L", "Analogue.R",
653 "AES.L", "AES.R",
654 "SPDIF.L", "SPDIF.R",
655 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
656 "Phone.L", "Phone.R"
657};
658
659static char *texts_ports_aio_in_qs[] = {
660 "Analogue.L", "Analogue.R",
661 "AES.L", "AES.R",
662 "SPDIF.L", "SPDIF.R",
663 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
664};
665
666static char *texts_ports_aio_out_qs[] = {
667 "Analogue.L", "Analogue.R",
668 "AES.L", "AES.R",
669 "SPDIF.L", "SPDIF.R",
670 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
671 "Phone.L", "Phone.R"
672};
673
Adrian Knoth432d2502011-02-23 11:43:08 +0100674static char *texts_ports_aes32[] = {
675 "AES.1", "AES.2", "AES.3", "AES.4", "AES.5", "AES.6", "AES.7",
676 "AES.8", "AES.9.", "AES.10", "AES.11", "AES.12", "AES.13", "AES.14",
677 "AES.15", "AES.16"
678};
679
Adrian Knoth55a57602011-01-27 11:23:15 +0100680/* These tables map the ALSA channels 1..N to the channels that we
681 need to use in order to find the relevant channel buffer. RME
682 refers to this kind of mapping as between "the ADAT channel and
683 the DMA channel." We index it using the logical audio channel,
684 and the value is the DMA channel (i.e. channel buffer number)
685 where the data for that channel can be read/written from/to.
686*/
687
688static char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = {
689 0, 1, 2, 3, 4, 5, 6, 7,
690 8, 9, 10, 11, 12, 13, 14, 15,
691 16, 17, 18, 19, 20, 21, 22, 23,
692 24, 25, 26, 27, 28, 29, 30, 31,
693 32, 33, 34, 35, 36, 37, 38, 39,
694 40, 41, 42, 43, 44, 45, 46, 47,
695 48, 49, 50, 51, 52, 53, 54, 55,
696 56, 57, 58, 59, 60, 61, 62, 63
697};
698
Adrian Knoth55a57602011-01-27 11:23:15 +0100699static char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = {
700 4, 5, 6, 7, 8, 9, 10, 11, /* ADAT 1 */
701 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT 2 */
702 20, 21, 22, 23, 24, 25, 26, 27, /* ADAT 3 */
703 28, 29, 30, 31, 32, 33, 34, 35, /* ADAT 4 */
704 0, 1, /* AES */
705 2, 3, /* SPDIF */
706 -1, -1, -1, -1,
707 -1, -1, -1, -1, -1, -1, -1, -1,
708 -1, -1, -1, -1, -1, -1, -1, -1,
709 -1, -1, -1, -1, -1, -1, -1, -1,
710};
711
712static char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = {
713 4, 5, 6, 7, /* ADAT 1 */
714 8, 9, 10, 11, /* ADAT 2 */
715 12, 13, 14, 15, /* ADAT 3 */
716 16, 17, 18, 19, /* ADAT 4 */
717 0, 1, /* AES */
718 2, 3, /* SPDIF */
719 -1, -1, -1, -1,
720 -1, -1, -1, -1, -1, -1, -1, -1,
721 -1, -1, -1, -1, -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};
726
727static char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = {
728 4, 5, /* ADAT 1 */
729 6, 7, /* ADAT 2 */
730 8, 9, /* ADAT 3 */
731 10, 11, /* ADAT 4 */
732 0, 1, /* AES */
733 2, 3, /* SPDIF */
734 -1, -1, -1, -1,
735 -1, -1, -1, -1, -1, -1, -1, -1,
736 -1, -1, -1, -1, -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};
742
743static char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = {
744 0, 1, /* line in */
745 8, 9, /* aes in, */
746 10, 11, /* spdif in */
747 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT in */
748 -1, -1,
749 -1, -1, -1, -1, -1, -1, -1, -1,
750 -1, -1, -1, -1, -1, -1, -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};
756
757static char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = {
758 0, 1, /* line out */
759 8, 9, /* aes out */
760 10, 11, /* spdif out */
761 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT out */
762 6, 7, /* phone out */
763 -1, -1, -1, -1, -1, -1, -1, -1,
764 -1, -1, -1, -1, -1, -1, -1, -1,
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};
770
771static char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = {
772 0, 1, /* line in */
773 8, 9, /* aes in */
774 10, 11, /* spdif in */
775 12, 14, 16, 18, /* adat in */
776 -1, -1, -1, -1, -1, -1,
777 -1, -1, -1, -1, -1, -1, -1, -1,
778 -1, -1, -1, -1, -1, -1, -1, -1,
779 -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};
784
785static char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = {
786 0, 1, /* line out */
787 8, 9, /* aes out */
788 10, 11, /* spdif out */
789 12, 14, 16, 18, /* adat out */
790 6, 7, /* phone out */
791 -1, -1, -1, -1,
792 -1, -1, -1, -1, -1, -1, -1, -1,
793 -1, -1, -1, -1, -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};
799
800static char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = {
801 0, 1, /* line in */
802 8, 9, /* aes in */
803 10, 11, /* spdif in */
804 12, 16, /* adat in */
805 -1, -1, -1, -1, -1, -1, -1, -1,
806 -1, -1, -1, -1, -1, -1, -1, -1,
807 -1, -1, -1, -1, -1, -1, -1, -1,
808 -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};
813
814static char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = {
815 0, 1, /* line out */
816 8, 9, /* aes out */
817 10, 11, /* spdif out */
818 12, 16, /* adat out */
819 6, 7, /* phone out */
820 -1, -1, -1, -1, -1, -1,
821 -1, -1, -1, -1, -1, -1, -1, -1,
822 -1, -1, -1, -1, -1, -1, -1, -1,
823 -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};
828
Adrian Knoth432d2502011-02-23 11:43:08 +0100829static char channel_map_aes32[HDSPM_MAX_CHANNELS] = {
830 0, 1, 2, 3, 4, 5, 6, 7,
831 8, 9, 10, 11, 12, 13, 14, 15,
832 -1, -1, -1, -1, -1, -1, -1, -1,
833 -1, -1, -1, -1, -1, -1, -1, -1,
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};
839
Takashi Iwai98274f02005-11-17 14:52:34 +0100840struct hdspm_midi {
841 struct hdspm *hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +0200842 int id;
Takashi Iwai98274f02005-11-17 14:52:34 +0100843 struct snd_rawmidi *rmidi;
844 struct snd_rawmidi_substream *input;
845 struct snd_rawmidi_substream *output;
Takashi Iwai763f3562005-06-03 11:25:34 +0200846 char istimer; /* timer in use */
847 struct timer_list timer;
848 spinlock_t lock;
849 int pending;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100850 int dataIn;
851 int statusIn;
852 int dataOut;
853 int statusOut;
854 int ie;
855 int irq;
856};
857
858struct hdspm_tco {
859 int input;
860 int framerate;
861 int wordclock;
862 int samplerate;
863 int pull;
864 int term; /* 0 = off, 1 = on */
Takashi Iwai763f3562005-06-03 11:25:34 +0200865};
866
Takashi Iwai98274f02005-11-17 14:52:34 +0100867struct hdspm {
Takashi Iwai763f3562005-06-03 11:25:34 +0200868 spinlock_t lock;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200869 /* only one playback and/or capture stream */
870 struct snd_pcm_substream *capture_substream;
871 struct snd_pcm_substream *playback_substream;
Takashi Iwai763f3562005-06-03 11:25:34 +0200872
873 char *card_name; /* for procinfo */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200874 unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
875
Adrian Knoth0dca1792011-01-26 19:32:14 +0100876 uint8_t io_type;
Takashi Iwai763f3562005-06-03 11:25:34 +0200877
Takashi Iwai763f3562005-06-03 11:25:34 +0200878 int monitor_outs; /* set up monitoring outs init flag */
879
880 u32 control_register; /* cached value */
881 u32 control2_register; /* cached value */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100882 u32 settings_register;
Takashi Iwai763f3562005-06-03 11:25:34 +0200883
Adrian Knoth0dca1792011-01-26 19:32:14 +0100884 struct hdspm_midi midi[4];
Takashi Iwai763f3562005-06-03 11:25:34 +0200885 struct tasklet_struct midi_tasklet;
886
887 size_t period_bytes;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100888 unsigned char ss_in_channels;
889 unsigned char ds_in_channels;
890 unsigned char qs_in_channels;
891 unsigned char ss_out_channels;
892 unsigned char ds_out_channels;
893 unsigned char qs_out_channels;
894
895 unsigned char max_channels_in;
896 unsigned char max_channels_out;
897
Takashi Iwai286bed02011-06-30 12:45:36 +0200898 signed char *channel_map_in;
899 signed char *channel_map_out;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100900
Takashi Iwai286bed02011-06-30 12:45:36 +0200901 signed char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs;
902 signed char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100903
904 char **port_names_in;
905 char **port_names_out;
906
907 char **port_names_in_ss, **port_names_in_ds, **port_names_in_qs;
908 char **port_names_out_ss, **port_names_out_ds, **port_names_out_qs;
Takashi Iwai763f3562005-06-03 11:25:34 +0200909
910 unsigned char *playback_buffer; /* suitably aligned address */
911 unsigned char *capture_buffer; /* suitably aligned address */
912
913 pid_t capture_pid; /* process id which uses capture */
914 pid_t playback_pid; /* process id which uses capture */
915 int running; /* running status */
916
917 int last_external_sample_rate; /* samplerate mystic ... */
918 int last_internal_sample_rate;
919 int system_sample_rate;
920
Takashi Iwai763f3562005-06-03 11:25:34 +0200921 int dev; /* Hardware vars... */
922 int irq;
923 unsigned long port;
924 void __iomem *iobase;
925
926 int irq_count; /* for debug */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100927 int midiPorts;
Takashi Iwai763f3562005-06-03 11:25:34 +0200928
Takashi Iwai98274f02005-11-17 14:52:34 +0100929 struct snd_card *card; /* one card */
930 struct snd_pcm *pcm; /* has one pcm */
931 struct snd_hwdep *hwdep; /* and a hwdep for additional ioctl */
Takashi Iwai763f3562005-06-03 11:25:34 +0200932 struct pci_dev *pci; /* and an pci info */
933
934 /* Mixer vars */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200935 /* fast alsa mixer */
936 struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS];
937 /* but input to much, so not used */
938 struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS];
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300939 /* full mixer accessible over mixer ioctl or hwdep-device */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200940 struct hdspm_mixer *mixer;
Takashi Iwai763f3562005-06-03 11:25:34 +0200941
Adrian Knoth0dca1792011-01-26 19:32:14 +0100942 struct hdspm_tco *tco; /* NULL if no TCO detected */
Takashi Iwai763f3562005-06-03 11:25:34 +0200943
Adrian Knoth0dca1792011-01-26 19:32:14 +0100944 char **texts_autosync;
945 int texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +0200946
Adrian Knoth0dca1792011-01-26 19:32:14 +0100947 cycles_t last_interrupt;
Jaroslav Kysela730a5862011-01-27 13:03:15 +0100948
Adrian Knoth7d53a632012-01-04 14:31:16 +0100949 unsigned int serial;
950
Jaroslav Kysela730a5862011-01-27 13:03:15 +0100951 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 */
Bill Pembertone23e7a12012-12-06 12:35:10 -0500970static int snd_hdspm_create_alsa_devices(struct snd_card *card,
971 struct hdspm *hdspm);
972static int 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);
Adrian Knoth3f7bf912013-03-10 00:37:21 +0100976static inline int hdspm_get_pll_freq(struct hdspm *hdspm);
Adrian Knoth0dca1792011-01-26 19:32:14 +0100977static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
978static int hdspm_autosync_ref(struct hdspm *hdspm);
979static int snd_hdspm_set_defaults(struct hdspm *hdspm);
Adrian Knoth21a164d2012-10-19 17:42:23 +0200980static int hdspm_system_clock_mode(struct hdspm *hdspm);
Adrian Knoth0dca1792011-01-26 19:32:14 +0100981static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +0200982 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +0200983 unsigned int reg, int channels);
984
Remy Bruno3cee5a62006-10-16 12:46:32 +0200985static inline int HDSPM_bit2freq(int n)
986{
Denys Vlasenko62cef822008-04-14 13:04:18 +0200987 static const int bit2freq_tab[] = {
988 0, 32000, 44100, 48000, 64000, 88200,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200989 96000, 128000, 176400, 192000 };
990 if (n < 1 || n > 9)
991 return 0;
992 return bit2freq_tab[n];
993}
994
Adrian Knoth0dca1792011-01-26 19:32:14 +0100995/* Write/read to/from HDSPM with Adresses in Bytes
Takashi Iwai763f3562005-06-03 11:25:34 +0200996 not words but only 32Bit writes are allowed */
997
Takashi Iwai98274f02005-11-17 14:52:34 +0100998static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
Takashi Iwai763f3562005-06-03 11:25:34 +0200999 unsigned int val)
1000{
1001 writel(val, hdspm->iobase + reg);
1002}
1003
Takashi Iwai98274f02005-11-17 14:52:34 +01001004static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
Takashi Iwai763f3562005-06-03 11:25:34 +02001005{
1006 return readl(hdspm->iobase + reg);
1007}
1008
Adrian Knoth0dca1792011-01-26 19:32:14 +01001009/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
1010 mixer is write only on hardware so we have to cache him for read
Takashi Iwai763f3562005-06-03 11:25:34 +02001011 each fader is a u32, but uses only the first 16 bit */
1012
Takashi Iwai98274f02005-11-17 14:52:34 +01001013static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001014 unsigned int in)
1015{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001016 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001017 return 0;
1018
1019 return hdspm->mixer->ch[chan].in[in];
1020}
1021
Takashi Iwai98274f02005-11-17 14:52:34 +01001022static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001023 unsigned int pb)
1024{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001025 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001026 return 0;
1027 return hdspm->mixer->ch[chan].pb[pb];
1028}
1029
Denys Vlasenko62cef822008-04-14 13:04:18 +02001030static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001031 unsigned int in, unsigned short data)
1032{
1033 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
1034 return -1;
1035
1036 hdspm_write(hdspm,
1037 HDSPM_MADI_mixerBase +
1038 ((in + 128 * chan) * sizeof(u32)),
1039 (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
1040 return 0;
1041}
1042
Denys Vlasenko62cef822008-04-14 13:04:18 +02001043static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001044 unsigned int pb, unsigned short data)
1045{
1046 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
1047 return -1;
1048
1049 hdspm_write(hdspm,
1050 HDSPM_MADI_mixerBase +
1051 ((64 + pb + 128 * chan) * sizeof(u32)),
1052 (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
1053 return 0;
1054}
1055
1056
1057/* enable DMA for specific channels, now available for DSP-MADI */
Takashi Iwai98274f02005-11-17 14:52:34 +01001058static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001059{
1060 hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
1061}
1062
Takashi Iwai98274f02005-11-17 14:52:34 +01001063static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001064{
1065 hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
1066}
1067
1068/* check if same process is writing and reading */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001069static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001070{
1071 unsigned long flags;
1072 int ret = 1;
1073
1074 spin_lock_irqsave(&hdspm->lock, flags);
1075 if ((hdspm->playback_pid != hdspm->capture_pid) &&
1076 (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
1077 ret = 0;
1078 }
1079 spin_unlock_irqrestore(&hdspm->lock, flags);
1080 return ret;
1081}
1082
Adrian Knothfcdc4ba2013-03-10 00:37:22 +01001083/* round arbitary sample rates to commonly known rates */
1084static int hdspm_round_frequency(int rate)
1085{
1086 if (rate < 38050)
1087 return 32000;
1088 if (rate < 46008)
1089 return 44100;
1090 else
1091 return 48000;
1092}
1093
1094static int hdspm_tco_sync_check(struct hdspm *hdspm);
1095static int hdspm_sync_in_sync_check(struct hdspm *hdspm);
1096
Takashi Iwai763f3562005-06-03 11:25:34 +02001097/* check for external sample rate */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001098static int hdspm_external_sample_rate(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001099{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001100 unsigned int status, status2, timecode;
1101 int syncref, rate = 0, rate_bits;
Takashi Iwai763f3562005-06-03 11:25:34 +02001102
Adrian Knoth0dca1792011-01-26 19:32:14 +01001103 switch (hdspm->io_type) {
1104 case AES32:
1105 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1106 status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01001107 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001108
1109 syncref = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001110
Remy Bruno3cee5a62006-10-16 12:46:32 +02001111 if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD &&
1112 status & HDSPM_AES32_wcLock)
Adrian Knoth0dca1792011-01-26 19:32:14 +01001113 return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF);
1114
Remy Bruno3cee5a62006-10-16 12:46:32 +02001115 if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001116 syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
1117 status2 & (HDSPM_LockAES >>
1118 (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1)))
1119 return HDSPM_bit2freq((timecode >> (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF);
Remy Bruno3cee5a62006-10-16 12:46:32 +02001120 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001121 break;
1122
1123 case MADIface:
1124 status = hdspm_read(hdspm, HDSPM_statusRegister);
1125
1126 if (!(status & HDSPM_madiLock)) {
1127 rate = 0; /* no lock */
1128 } else {
1129 switch (status & (HDSPM_status1_freqMask)) {
1130 case HDSPM_status1_F_0*1:
1131 rate = 32000; break;
1132 case HDSPM_status1_F_0*2:
1133 rate = 44100; break;
1134 case HDSPM_status1_F_0*3:
1135 rate = 48000; break;
1136 case HDSPM_status1_F_0*4:
1137 rate = 64000; break;
1138 case HDSPM_status1_F_0*5:
1139 rate = 88200; break;
1140 case HDSPM_status1_F_0*6:
1141 rate = 96000; break;
1142 case HDSPM_status1_F_0*7:
1143 rate = 128000; break;
1144 case HDSPM_status1_F_0*8:
1145 rate = 176400; break;
1146 case HDSPM_status1_F_0*9:
1147 rate = 192000; break;
1148 default:
1149 rate = 0; break;
1150 }
1151 }
1152
1153 break;
1154
1155 case MADI:
1156 case AIO:
1157 case RayDAT:
1158 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1159 status = hdspm_read(hdspm, HDSPM_statusRegister);
1160 rate = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02001161
Remy Bruno3cee5a62006-10-16 12:46:32 +02001162 /* if wordclock has synced freq and wordclock is valid */
1163 if ((status2 & HDSPM_wcLock) != 0 &&
Adrian Knothfedf1532011-06-12 17:26:18 +02001164 (status2 & HDSPM_SelSyncRef0) == 0) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02001165
1166 rate_bits = status2 & HDSPM_wcFreqMask;
1167
Adrian Knoth0dca1792011-01-26 19:32:14 +01001168
Remy Bruno3cee5a62006-10-16 12:46:32 +02001169 switch (rate_bits) {
1170 case HDSPM_wcFreq32:
1171 rate = 32000;
1172 break;
1173 case HDSPM_wcFreq44_1:
1174 rate = 44100;
1175 break;
1176 case HDSPM_wcFreq48:
1177 rate = 48000;
1178 break;
1179 case HDSPM_wcFreq64:
1180 rate = 64000;
1181 break;
1182 case HDSPM_wcFreq88_2:
1183 rate = 88200;
1184 break;
1185 case HDSPM_wcFreq96:
1186 rate = 96000;
1187 break;
Adrian Knotha8cd7142013-05-31 12:57:09 +02001188 case HDSPM_wcFreq128:
1189 rate = 128000;
1190 break;
1191 case HDSPM_wcFreq176_4:
1192 rate = 176400;
1193 break;
1194 case HDSPM_wcFreq192:
1195 rate = 192000;
1196 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001197 default:
1198 rate = 0;
1199 break;
1200 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001201 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001202
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001203 /* if rate detected and Syncref is Word than have it,
1204 * word has priority to MADI
1205 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001206 if (rate != 0 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001207 (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
Remy Bruno3cee5a62006-10-16 12:46:32 +02001208 return rate;
1209
Adrian Knoth0dca1792011-01-26 19:32:14 +01001210 /* maybe a madi input (which is taken if sel sync is madi) */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001211 if (status & HDSPM_madiLock) {
1212 rate_bits = status & HDSPM_madiFreqMask;
1213
1214 switch (rate_bits) {
1215 case HDSPM_madiFreq32:
1216 rate = 32000;
1217 break;
1218 case HDSPM_madiFreq44_1:
1219 rate = 44100;
1220 break;
1221 case HDSPM_madiFreq48:
1222 rate = 48000;
1223 break;
1224 case HDSPM_madiFreq64:
1225 rate = 64000;
1226 break;
1227 case HDSPM_madiFreq88_2:
1228 rate = 88200;
1229 break;
1230 case HDSPM_madiFreq96:
1231 rate = 96000;
1232 break;
1233 case HDSPM_madiFreq128:
1234 rate = 128000;
1235 break;
1236 case HDSPM_madiFreq176_4:
1237 rate = 176400;
1238 break;
1239 case HDSPM_madiFreq192:
1240 rate = 192000;
1241 break;
1242 default:
1243 rate = 0;
1244 break;
1245 }
Adrian Knothd12c51d2011-07-29 03:11:03 +02001246
Adrian Knothfcdc4ba2013-03-10 00:37:22 +01001247 } /* endif HDSPM_madiLock */
1248
1249 /* check sample rate from TCO or SYNC_IN */
1250 {
1251 bool is_valid_input = 0;
1252 bool has_sync = 0;
1253
1254 syncref = hdspm_autosync_ref(hdspm);
1255 if (HDSPM_AUTOSYNC_FROM_TCO == syncref) {
1256 is_valid_input = 1;
1257 has_sync = (HDSPM_SYNC_CHECK_SYNC ==
1258 hdspm_tco_sync_check(hdspm));
1259 } else if (HDSPM_AUTOSYNC_FROM_SYNC_IN == syncref) {
1260 is_valid_input = 1;
1261 has_sync = (HDSPM_SYNC_CHECK_SYNC ==
1262 hdspm_sync_in_sync_check(hdspm));
Adrian Knothd12c51d2011-07-29 03:11:03 +02001263 }
Adrian Knothfcdc4ba2013-03-10 00:37:22 +01001264
1265 if (is_valid_input && has_sync) {
1266 rate = hdspm_round_frequency(
1267 hdspm_get_pll_freq(hdspm));
1268 }
1269 }
1270
1271 /* QS and DS rates normally can not be detected
1272 * automatically by the card. Only exception is MADI
1273 * in 96k frame mode.
1274 *
1275 * So if we read SS values (32 .. 48k), check for
1276 * user-provided DS/QS bits in the control register
1277 * and multiply the base frequency accordingly.
1278 */
1279 if (rate <= 48000) {
1280 if (hdspm->control_register & HDSPM_QuadSpeed)
1281 rate *= 4;
1282 else if (hdspm->control_register &
1283 HDSPM_DoubleSpeed)
1284 rate *= 2;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001285 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001286 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001287 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001288
1289 return rate;
Takashi Iwai763f3562005-06-03 11:25:34 +02001290}
1291
Adrian Knoth7cb155f2011-08-15 00:22:53 +02001292/* return latency in samples per period */
1293static int hdspm_get_latency(struct hdspm *hdspm)
1294{
1295 int n;
1296
1297 n = hdspm_decode_latency(hdspm->control_register);
1298
1299 /* Special case for new RME cards with 32 samples period size.
1300 * The three latency bits in the control register
1301 * (HDSP_LatencyMask) encode latency values of 64 samples as
1302 * 0, 128 samples as 1 ... 4096 samples as 6. For old cards, 7
1303 * denotes 8192 samples, but on new cards like RayDAT or AIO,
1304 * it corresponds to 32 samples.
1305 */
1306 if ((7 == n) && (RayDAT == hdspm->io_type || AIO == hdspm->io_type))
1307 n = -1;
1308
1309 return 1 << (n + 6);
1310}
1311
Takashi Iwai763f3562005-06-03 11:25:34 +02001312/* Latency function */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001313static inline void hdspm_compute_period_size(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001314{
Adrian Knoth7cb155f2011-08-15 00:22:53 +02001315 hdspm->period_bytes = 4 * hdspm_get_latency(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001316}
1317
Adrian Knoth0dca1792011-01-26 19:32:14 +01001318
1319static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001320{
1321 int position;
1322
1323 position = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth483cee72011-02-23 11:43:09 +01001324
1325 switch (hdspm->io_type) {
1326 case RayDAT:
1327 case AIO:
1328 position &= HDSPM_BufferPositionMask;
1329 position /= 4; /* Bytes per sample */
1330 break;
1331 default:
1332 position = (position & HDSPM_BufferID) ?
1333 (hdspm->period_bytes / 4) : 0;
1334 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001335
1336 return position;
1337}
1338
1339
Takashi Iwai98274f02005-11-17 14:52:34 +01001340static inline void hdspm_start_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001341{
1342 s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
1343 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1344}
1345
Takashi Iwai98274f02005-11-17 14:52:34 +01001346static inline void hdspm_stop_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001347{
1348 s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
1349 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1350}
1351
1352/* should I silence all or only opened ones ? doit all for first even is 4MB*/
Denys Vlasenko62cef822008-04-14 13:04:18 +02001353static void hdspm_silence_playback(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001354{
1355 int i;
1356 int n = hdspm->period_bytes;
1357 void *buf = hdspm->playback_buffer;
1358
Remy Bruno3cee5a62006-10-16 12:46:32 +02001359 if (buf == NULL)
1360 return;
Takashi Iwai763f3562005-06-03 11:25:34 +02001361
1362 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
1363 memset(buf, 0, n);
1364 buf += HDSPM_CHANNEL_BUFFER_BYTES;
1365 }
1366}
1367
Adrian Knoth0dca1792011-01-26 19:32:14 +01001368static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames)
Takashi Iwai763f3562005-06-03 11:25:34 +02001369{
1370 int n;
1371
1372 spin_lock_irq(&s->lock);
1373
Adrian Knoth2e610272011-08-15 00:22:54 +02001374 if (32 == frames) {
1375 /* Special case for new RME cards like RayDAT/AIO which
1376 * support period sizes of 32 samples. Since latency is
1377 * encoded in the three bits of HDSP_LatencyMask, we can only
1378 * have values from 0 .. 7. While 0 still means 64 samples and
1379 * 6 represents 4096 samples on all cards, 7 represents 8192
1380 * on older cards and 32 samples on new cards.
1381 *
1382 * In other words, period size in samples is calculated by
1383 * 2^(n+6) with n ranging from 0 .. 7.
1384 */
1385 n = 7;
1386 } else {
1387 frames >>= 7;
1388 n = 0;
1389 while (frames) {
1390 n++;
1391 frames >>= 1;
1392 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001393 }
Adrian Knoth2e610272011-08-15 00:22:54 +02001394
Takashi Iwai763f3562005-06-03 11:25:34 +02001395 s->control_register &= ~HDSPM_LatencyMask;
1396 s->control_register |= hdspm_encode_latency(n);
1397
1398 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1399
1400 hdspm_compute_period_size(s);
1401
1402 spin_unlock_irq(&s->lock);
1403
1404 return 0;
1405}
1406
Adrian Knoth0dca1792011-01-26 19:32:14 +01001407static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period)
1408{
1409 u64 freq_const;
1410
1411 if (period == 0)
1412 return 0;
1413
1414 switch (hdspm->io_type) {
1415 case MADI:
1416 case AES32:
1417 freq_const = 110069313433624ULL;
1418 break;
1419 case RayDAT:
1420 case AIO:
1421 freq_const = 104857600000000ULL;
1422 break;
1423 case MADIface:
1424 freq_const = 131072000000000ULL;
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001425 break;
1426 default:
1427 snd_BUG();
1428 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001429 }
1430
1431 return div_u64(freq_const, period);
1432}
1433
1434
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001435static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
1436{
1437 u64 n;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001438
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001439 if (rate >= 112000)
1440 rate /= 4;
1441 else if (rate >= 56000)
1442 rate /= 2;
1443
Adrian Knoth0dca1792011-01-26 19:32:14 +01001444 switch (hdspm->io_type) {
1445 case MADIface:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001446 n = 131072000000000ULL; /* 125 MHz */
1447 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001448 case MADI:
1449 case AES32:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001450 n = 110069313433624ULL; /* 105 MHz */
1451 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001452 case RayDAT:
1453 case AIO:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001454 n = 104857600000000ULL; /* 100 MHz */
1455 break;
1456 default:
1457 snd_BUG();
1458 return;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001459 }
1460
Takashi Iwai3f7440a2009-06-05 17:40:04 +02001461 n = div_u64(n, rate);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001462 /* n should be less than 2^32 for being written to FREQ register */
Takashi Iwaida3cec32008-08-08 17:12:14 +02001463 snd_BUG_ON(n >> 32);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001464 hdspm_write(hdspm, HDSPM_freqReg, (u32)n);
1465}
Takashi Iwai763f3562005-06-03 11:25:34 +02001466
1467/* dummy set rate lets see what happens */
Takashi Iwai98274f02005-11-17 14:52:34 +01001468static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
Takashi Iwai763f3562005-06-03 11:25:34 +02001469{
Takashi Iwai763f3562005-06-03 11:25:34 +02001470 int current_rate;
1471 int rate_bits;
1472 int not_set = 0;
Remy Bruno65345992007-08-31 12:21:08 +02001473 int current_speed, target_speed;
Takashi Iwai763f3562005-06-03 11:25:34 +02001474
1475 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
1476 it (e.g. during module initialization).
1477 */
1478
1479 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
1480
Adrian Knoth0dca1792011-01-26 19:32:14 +01001481 /* SLAVE --- */
Takashi Iwai763f3562005-06-03 11:25:34 +02001482 if (called_internally) {
1483
Adrian Knoth0dca1792011-01-26 19:32:14 +01001484 /* request from ctl or card initialization
1485 just make a warning an remember setting
1486 for future master mode switching */
1487
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001488 snd_printk(KERN_WARNING "HDSPM: "
1489 "Warning: device is not running "
1490 "as a clock master.\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001491 not_set = 1;
1492 } else {
1493
1494 /* hw_param request while in AutoSync mode */
1495 int external_freq =
1496 hdspm_external_sample_rate(hdspm);
1497
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001498 if (hdspm_autosync_ref(hdspm) ==
1499 HDSPM_AUTOSYNC_FROM_NONE) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001500
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001501 snd_printk(KERN_WARNING "HDSPM: "
1502 "Detected no Externel Sync \n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001503 not_set = 1;
1504
1505 } else if (rate != external_freq) {
1506
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001507 snd_printk(KERN_WARNING "HDSPM: "
1508 "Warning: No AutoSync source for "
1509 "requested rate\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001510 not_set = 1;
1511 }
1512 }
1513 }
1514
1515 current_rate = hdspm->system_sample_rate;
1516
1517 /* Changing between Singe, Double and Quad speed is not
1518 allowed if any substreams are open. This is because such a change
1519 causes a shift in the location of the DMA buffers and a reduction
1520 in the number of available buffers.
1521
1522 Note that a similar but essentially insoluble problem exists for
1523 externally-driven rate changes. All we can do is to flag rate
Adrian Knoth0dca1792011-01-26 19:32:14 +01001524 changes in the read/write routines.
Takashi Iwai763f3562005-06-03 11:25:34 +02001525 */
1526
Remy Bruno65345992007-08-31 12:21:08 +02001527 if (current_rate <= 48000)
1528 current_speed = HDSPM_SPEED_SINGLE;
1529 else if (current_rate <= 96000)
1530 current_speed = HDSPM_SPEED_DOUBLE;
1531 else
1532 current_speed = HDSPM_SPEED_QUAD;
1533
1534 if (rate <= 48000)
1535 target_speed = HDSPM_SPEED_SINGLE;
1536 else if (rate <= 96000)
1537 target_speed = HDSPM_SPEED_DOUBLE;
1538 else
1539 target_speed = HDSPM_SPEED_QUAD;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001540
Takashi Iwai763f3562005-06-03 11:25:34 +02001541 switch (rate) {
1542 case 32000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001543 rate_bits = HDSPM_Frequency32KHz;
1544 break;
1545 case 44100:
Takashi Iwai763f3562005-06-03 11:25:34 +02001546 rate_bits = HDSPM_Frequency44_1KHz;
1547 break;
1548 case 48000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001549 rate_bits = HDSPM_Frequency48KHz;
1550 break;
1551 case 64000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001552 rate_bits = HDSPM_Frequency64KHz;
1553 break;
1554 case 88200:
Takashi Iwai763f3562005-06-03 11:25:34 +02001555 rate_bits = HDSPM_Frequency88_2KHz;
1556 break;
1557 case 96000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001558 rate_bits = HDSPM_Frequency96KHz;
1559 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001560 case 128000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001561 rate_bits = HDSPM_Frequency128KHz;
1562 break;
1563 case 176400:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001564 rate_bits = HDSPM_Frequency176_4KHz;
1565 break;
1566 case 192000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001567 rate_bits = HDSPM_Frequency192KHz;
1568 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001569 default:
1570 return -EINVAL;
1571 }
1572
Remy Bruno65345992007-08-31 12:21:08 +02001573 if (current_speed != target_speed
Takashi Iwai763f3562005-06-03 11:25:34 +02001574 && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
1575 snd_printk
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001576 (KERN_ERR "HDSPM: "
Remy Bruno65345992007-08-31 12:21:08 +02001577 "cannot change from %s speed to %s speed mode "
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001578 "(capture PID = %d, playback PID = %d)\n",
Remy Bruno65345992007-08-31 12:21:08 +02001579 hdspm_speed_names[current_speed],
1580 hdspm_speed_names[target_speed],
Takashi Iwai763f3562005-06-03 11:25:34 +02001581 hdspm->capture_pid, hdspm->playback_pid);
1582 return -EBUSY;
1583 }
1584
1585 hdspm->control_register &= ~HDSPM_FrequencyMask;
1586 hdspm->control_register |= rate_bits;
1587 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1588
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001589 /* For AES32, need to set DDS value in FREQ register
1590 For MADI, also apparently */
1591 hdspm_set_dds_value(hdspm, rate);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001592
1593 if (AES32 == hdspm->io_type && rate != current_rate)
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001594 hdspm_write(hdspm, HDSPM_eeprom_wr, 0);
Takashi Iwai763f3562005-06-03 11:25:34 +02001595
1596 hdspm->system_sample_rate = rate;
1597
Adrian Knoth0dca1792011-01-26 19:32:14 +01001598 if (rate <= 48000) {
1599 hdspm->channel_map_in = hdspm->channel_map_in_ss;
1600 hdspm->channel_map_out = hdspm->channel_map_out_ss;
1601 hdspm->max_channels_in = hdspm->ss_in_channels;
1602 hdspm->max_channels_out = hdspm->ss_out_channels;
1603 hdspm->port_names_in = hdspm->port_names_in_ss;
1604 hdspm->port_names_out = hdspm->port_names_out_ss;
1605 } else if (rate <= 96000) {
1606 hdspm->channel_map_in = hdspm->channel_map_in_ds;
1607 hdspm->channel_map_out = hdspm->channel_map_out_ds;
1608 hdspm->max_channels_in = hdspm->ds_in_channels;
1609 hdspm->max_channels_out = hdspm->ds_out_channels;
1610 hdspm->port_names_in = hdspm->port_names_in_ds;
1611 hdspm->port_names_out = hdspm->port_names_out_ds;
1612 } else {
1613 hdspm->channel_map_in = hdspm->channel_map_in_qs;
1614 hdspm->channel_map_out = hdspm->channel_map_out_qs;
1615 hdspm->max_channels_in = hdspm->qs_in_channels;
1616 hdspm->max_channels_out = hdspm->qs_out_channels;
1617 hdspm->port_names_in = hdspm->port_names_in_qs;
1618 hdspm->port_names_out = hdspm->port_names_out_qs;
1619 }
1620
Takashi Iwai763f3562005-06-03 11:25:34 +02001621 if (not_set != 0)
1622 return -1;
1623
1624 return 0;
1625}
1626
1627/* mainly for init to 0 on load */
Takashi Iwai98274f02005-11-17 14:52:34 +01001628static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
Takashi Iwai763f3562005-06-03 11:25:34 +02001629{
1630 int i, j;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001631 unsigned int gain;
1632
1633 if (sgain > UNITY_GAIN)
1634 gain = UNITY_GAIN;
1635 else if (sgain < 0)
1636 gain = 0;
1637 else
1638 gain = sgain;
Takashi Iwai763f3562005-06-03 11:25:34 +02001639
1640 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
1641 for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
1642 hdspm_write_in_gain(hdspm, i, j, gain);
1643 hdspm_write_pb_gain(hdspm, i, j, gain);
1644 }
1645}
1646
1647/*----------------------------------------------------------------------------
1648 MIDI
1649 ----------------------------------------------------------------------------*/
1650
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001651static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm,
1652 int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001653{
1654 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001655 return hdspm_read(hdspm, hdspm->midi[id].dataIn);
Takashi Iwai763f3562005-06-03 11:25:34 +02001656}
1657
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001658static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
1659 int val)
Takashi Iwai763f3562005-06-03 11:25:34 +02001660{
1661 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001662 return hdspm_write(hdspm, hdspm->midi[id].dataOut, val);
Takashi Iwai763f3562005-06-03 11:25:34 +02001663}
1664
Takashi Iwai98274f02005-11-17 14:52:34 +01001665static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001666{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001667 return hdspm_read(hdspm, hdspm->midi[id].statusIn) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001668}
1669
Takashi Iwai98274f02005-11-17 14:52:34 +01001670static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001671{
1672 int fifo_bytes_used;
1673
Adrian Knoth0dca1792011-01-26 19:32:14 +01001674 fifo_bytes_used = hdspm_read(hdspm, hdspm->midi[id].statusOut) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001675
1676 if (fifo_bytes_used < 128)
1677 return 128 - fifo_bytes_used;
1678 else
1679 return 0;
1680}
1681
Denys Vlasenko62cef822008-04-14 13:04:18 +02001682static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001683{
1684 while (snd_hdspm_midi_input_available (hdspm, id))
1685 snd_hdspm_midi_read_byte (hdspm, id);
1686}
1687
Takashi Iwai98274f02005-11-17 14:52:34 +01001688static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001689{
1690 unsigned long flags;
1691 int n_pending;
1692 int to_write;
1693 int i;
1694 unsigned char buf[128];
1695
1696 /* Output is not interrupt driven */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001697
Takashi Iwai763f3562005-06-03 11:25:34 +02001698 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001699 if (hmidi->output &&
1700 !snd_rawmidi_transmit_empty (hmidi->output)) {
1701 n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm,
1702 hmidi->id);
1703 if (n_pending > 0) {
1704 if (n_pending > (int)sizeof (buf))
1705 n_pending = sizeof (buf);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001706
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001707 to_write = snd_rawmidi_transmit (hmidi->output, buf,
1708 n_pending);
1709 if (to_write > 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001710 for (i = 0; i < to_write; ++i)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001711 snd_hdspm_midi_write_byte (hmidi->hdspm,
1712 hmidi->id,
1713 buf[i]);
Takashi Iwai763f3562005-06-03 11:25:34 +02001714 }
1715 }
1716 }
1717 spin_unlock_irqrestore (&hmidi->lock, flags);
1718 return 0;
1719}
1720
Takashi Iwai98274f02005-11-17 14:52:34 +01001721static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001722{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001723 unsigned char buf[128]; /* this buffer is designed to match the MIDI
1724 * input FIFO size
1725 */
Takashi Iwai763f3562005-06-03 11:25:34 +02001726 unsigned long flags;
1727 int n_pending;
1728 int i;
1729
1730 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001731 n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id);
1732 if (n_pending > 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001733 if (hmidi->input) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001734 if (n_pending > (int)sizeof (buf))
Takashi Iwai763f3562005-06-03 11:25:34 +02001735 n_pending = sizeof (buf);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001736 for (i = 0; i < n_pending; ++i)
1737 buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm,
1738 hmidi->id);
1739 if (n_pending)
1740 snd_rawmidi_receive (hmidi->input, buf,
1741 n_pending);
Takashi Iwai763f3562005-06-03 11:25:34 +02001742 } else {
1743 /* flush the MIDI input FIFO */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001744 while (n_pending--)
1745 snd_hdspm_midi_read_byte (hmidi->hdspm,
1746 hmidi->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02001747 }
1748 }
1749 hmidi->pending = 0;
Adrian Knothc0da0012011-06-12 17:26:17 +02001750 spin_unlock_irqrestore(&hmidi->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001751
Adrian Knothc0da0012011-06-12 17:26:17 +02001752 spin_lock_irqsave(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001753 hmidi->hdspm->control_register |= hmidi->ie;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001754 hdspm_write(hmidi->hdspm, HDSPM_controlRegister,
1755 hmidi->hdspm->control_register);
Adrian Knothc0da0012011-06-12 17:26:17 +02001756 spin_unlock_irqrestore(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001757
Takashi Iwai763f3562005-06-03 11:25:34 +02001758 return snd_hdspm_midi_output_write (hmidi);
1759}
1760
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001761static void
1762snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001763{
Takashi Iwai98274f02005-11-17 14:52:34 +01001764 struct hdspm *hdspm;
1765 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001766 unsigned long flags;
Takashi Iwai763f3562005-06-03 11:25:34 +02001767
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001768 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001769 hdspm = hmidi->hdspm;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001770
Takashi Iwai763f3562005-06-03 11:25:34 +02001771 spin_lock_irqsave (&hdspm->lock, flags);
1772 if (up) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001773 if (!(hdspm->control_register & hmidi->ie)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001774 snd_hdspm_flush_midi_input (hdspm, hmidi->id);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001775 hdspm->control_register |= hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001776 }
1777 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001778 hdspm->control_register &= ~hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001779 }
1780
1781 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1782 spin_unlock_irqrestore (&hdspm->lock, flags);
1783}
1784
1785static void snd_hdspm_midi_output_timer(unsigned long data)
1786{
Takashi Iwai98274f02005-11-17 14:52:34 +01001787 struct hdspm_midi *hmidi = (struct hdspm_midi *) data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001788 unsigned long flags;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001789
Takashi Iwai763f3562005-06-03 11:25:34 +02001790 snd_hdspm_midi_output_write(hmidi);
1791 spin_lock_irqsave (&hmidi->lock, flags);
1792
1793 /* this does not bump hmidi->istimer, because the
1794 kernel automatically removed the timer when it
1795 expired, and we are now adding it back, thus
Adrian Knoth0dca1792011-01-26 19:32:14 +01001796 leaving istimer wherever it was set before.
Takashi Iwai763f3562005-06-03 11:25:34 +02001797 */
1798
1799 if (hmidi->istimer) {
1800 hmidi->timer.expires = 1 + jiffies;
1801 add_timer(&hmidi->timer);
1802 }
1803
1804 spin_unlock_irqrestore (&hmidi->lock, flags);
1805}
1806
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001807static void
1808snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001809{
Takashi Iwai98274f02005-11-17 14:52:34 +01001810 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001811 unsigned long flags;
1812
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001813 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001814 spin_lock_irqsave (&hmidi->lock, flags);
1815 if (up) {
1816 if (!hmidi->istimer) {
1817 init_timer(&hmidi->timer);
1818 hmidi->timer.function = snd_hdspm_midi_output_timer;
1819 hmidi->timer.data = (unsigned long) hmidi;
1820 hmidi->timer.expires = 1 + jiffies;
1821 add_timer(&hmidi->timer);
1822 hmidi->istimer++;
1823 }
1824 } else {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001825 if (hmidi->istimer && --hmidi->istimer <= 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02001826 del_timer (&hmidi->timer);
Takashi Iwai763f3562005-06-03 11:25:34 +02001827 }
1828 spin_unlock_irqrestore (&hmidi->lock, flags);
1829 if (up)
1830 snd_hdspm_midi_output_write(hmidi);
1831}
1832
Takashi Iwai98274f02005-11-17 14:52:34 +01001833static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001834{
Takashi Iwai98274f02005-11-17 14:52:34 +01001835 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001836
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001837 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001838 spin_lock_irq (&hmidi->lock);
1839 snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
1840 hmidi->input = substream;
1841 spin_unlock_irq (&hmidi->lock);
1842
1843 return 0;
1844}
1845
Takashi Iwai98274f02005-11-17 14:52:34 +01001846static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001847{
Takashi Iwai98274f02005-11-17 14:52:34 +01001848 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001849
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001850 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001851 spin_lock_irq (&hmidi->lock);
1852 hmidi->output = substream;
1853 spin_unlock_irq (&hmidi->lock);
1854
1855 return 0;
1856}
1857
Takashi Iwai98274f02005-11-17 14:52:34 +01001858static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001859{
Takashi Iwai98274f02005-11-17 14:52:34 +01001860 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001861
1862 snd_hdspm_midi_input_trigger (substream, 0);
1863
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001864 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001865 spin_lock_irq (&hmidi->lock);
1866 hmidi->input = NULL;
1867 spin_unlock_irq (&hmidi->lock);
1868
1869 return 0;
1870}
1871
Takashi Iwai98274f02005-11-17 14:52:34 +01001872static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001873{
Takashi Iwai98274f02005-11-17 14:52:34 +01001874 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001875
1876 snd_hdspm_midi_output_trigger (substream, 0);
1877
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001878 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001879 spin_lock_irq (&hmidi->lock);
1880 hmidi->output = NULL;
1881 spin_unlock_irq (&hmidi->lock);
1882
1883 return 0;
1884}
1885
Takashi Iwai98274f02005-11-17 14:52:34 +01001886static struct snd_rawmidi_ops snd_hdspm_midi_output =
Takashi Iwai763f3562005-06-03 11:25:34 +02001887{
1888 .open = snd_hdspm_midi_output_open,
1889 .close = snd_hdspm_midi_output_close,
1890 .trigger = snd_hdspm_midi_output_trigger,
1891};
1892
Takashi Iwai98274f02005-11-17 14:52:34 +01001893static struct snd_rawmidi_ops snd_hdspm_midi_input =
Takashi Iwai763f3562005-06-03 11:25:34 +02001894{
1895 .open = snd_hdspm_midi_input_open,
1896 .close = snd_hdspm_midi_input_close,
1897 .trigger = snd_hdspm_midi_input_trigger,
1898};
1899
Bill Pembertone23e7a12012-12-06 12:35:10 -05001900static int snd_hdspm_create_midi(struct snd_card *card,
1901 struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001902{
1903 int err;
1904 char buf[32];
1905
1906 hdspm->midi[id].id = id;
Takashi Iwai763f3562005-06-03 11:25:34 +02001907 hdspm->midi[id].hdspm = hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +02001908 spin_lock_init (&hdspm->midi[id].lock);
1909
Adrian Knoth0dca1792011-01-26 19:32:14 +01001910 if (0 == id) {
1911 if (MADIface == hdspm->io_type) {
1912 /* MIDI-over-MADI on HDSPe MADIface */
1913 hdspm->midi[0].dataIn = HDSPM_midiDataIn2;
1914 hdspm->midi[0].statusIn = HDSPM_midiStatusIn2;
1915 hdspm->midi[0].dataOut = HDSPM_midiDataOut2;
1916 hdspm->midi[0].statusOut = HDSPM_midiStatusOut2;
1917 hdspm->midi[0].ie = HDSPM_Midi2InterruptEnable;
1918 hdspm->midi[0].irq = HDSPM_midi2IRQPending;
1919 } else {
1920 hdspm->midi[0].dataIn = HDSPM_midiDataIn0;
1921 hdspm->midi[0].statusIn = HDSPM_midiStatusIn0;
1922 hdspm->midi[0].dataOut = HDSPM_midiDataOut0;
1923 hdspm->midi[0].statusOut = HDSPM_midiStatusOut0;
1924 hdspm->midi[0].ie = HDSPM_Midi0InterruptEnable;
1925 hdspm->midi[0].irq = HDSPM_midi0IRQPending;
1926 }
1927 } else if (1 == id) {
1928 hdspm->midi[1].dataIn = HDSPM_midiDataIn1;
1929 hdspm->midi[1].statusIn = HDSPM_midiStatusIn1;
1930 hdspm->midi[1].dataOut = HDSPM_midiDataOut1;
1931 hdspm->midi[1].statusOut = HDSPM_midiStatusOut1;
1932 hdspm->midi[1].ie = HDSPM_Midi1InterruptEnable;
1933 hdspm->midi[1].irq = HDSPM_midi1IRQPending;
1934 } else if ((2 == id) && (MADI == hdspm->io_type)) {
1935 /* MIDI-over-MADI on HDSPe MADI */
1936 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1937 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1938 hdspm->midi[2].dataOut = HDSPM_midiDataOut2;
1939 hdspm->midi[2].statusOut = HDSPM_midiStatusOut2;
1940 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1941 hdspm->midi[2].irq = HDSPM_midi2IRQPending;
1942 } else if (2 == id) {
1943 /* TCO MTC, read only */
1944 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1945 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1946 hdspm->midi[2].dataOut = -1;
1947 hdspm->midi[2].statusOut = -1;
1948 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1949 hdspm->midi[2].irq = HDSPM_midi2IRQPendingAES;
1950 } else if (3 == id) {
1951 /* TCO MTC on HDSPe MADI */
1952 hdspm->midi[3].dataIn = HDSPM_midiDataIn3;
1953 hdspm->midi[3].statusIn = HDSPM_midiStatusIn3;
1954 hdspm->midi[3].dataOut = -1;
1955 hdspm->midi[3].statusOut = -1;
1956 hdspm->midi[3].ie = HDSPM_Midi3InterruptEnable;
1957 hdspm->midi[3].irq = HDSPM_midi3IRQPending;
1958 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001959
Adrian Knoth0dca1792011-01-26 19:32:14 +01001960 if ((id < 2) || ((2 == id) && ((MADI == hdspm->io_type) ||
1961 (MADIface == hdspm->io_type)))) {
1962 if ((id == 0) && (MADIface == hdspm->io_type)) {
1963 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1964 } else if ((id == 2) && (MADI == hdspm->io_type)) {
1965 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1966 } else {
1967 sprintf(buf, "%s MIDI %d", card->shortname, id+1);
1968 }
1969 err = snd_rawmidi_new(card, buf, id, 1, 1,
1970 &hdspm->midi[id].rmidi);
1971 if (err < 0)
1972 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02001973
Adrian Knoth0dca1792011-01-26 19:32:14 +01001974 sprintf(hdspm->midi[id].rmidi->name, "%s MIDI %d",
1975 card->id, id+1);
1976 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
Takashi Iwai763f3562005-06-03 11:25:34 +02001977
Adrian Knoth0dca1792011-01-26 19:32:14 +01001978 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1979 SNDRV_RAWMIDI_STREAM_OUTPUT,
1980 &snd_hdspm_midi_output);
1981 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1982 SNDRV_RAWMIDI_STREAM_INPUT,
1983 &snd_hdspm_midi_input);
1984
1985 hdspm->midi[id].rmidi->info_flags |=
1986 SNDRV_RAWMIDI_INFO_OUTPUT |
1987 SNDRV_RAWMIDI_INFO_INPUT |
1988 SNDRV_RAWMIDI_INFO_DUPLEX;
1989 } else {
1990 /* TCO MTC, read only */
1991 sprintf(buf, "%s MTC %d", card->shortname, id+1);
1992 err = snd_rawmidi_new(card, buf, id, 1, 1,
1993 &hdspm->midi[id].rmidi);
1994 if (err < 0)
1995 return err;
1996
1997 sprintf(hdspm->midi[id].rmidi->name,
1998 "%s MTC %d", card->id, id+1);
1999 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
2000
2001 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
2002 SNDRV_RAWMIDI_STREAM_INPUT,
2003 &snd_hdspm_midi_input);
2004
2005 hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
2006 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002007
2008 return 0;
2009}
2010
2011
2012static void hdspm_midi_tasklet(unsigned long arg)
2013{
Takashi Iwai98274f02005-11-17 14:52:34 +01002014 struct hdspm *hdspm = (struct hdspm *)arg;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002015 int i = 0;
2016
2017 while (i < hdspm->midiPorts) {
2018 if (hdspm->midi[i].pending)
2019 snd_hdspm_midi_input_read(&hdspm->midi[i]);
2020
2021 i++;
2022 }
2023}
Takashi Iwai763f3562005-06-03 11:25:34 +02002024
2025
2026/*-----------------------------------------------------------------------------
2027 Status Interface
2028 ----------------------------------------------------------------------------*/
2029
2030/* get the system sample rate which is set */
2031
Adrian Knoth0dca1792011-01-26 19:32:14 +01002032
Adrian Knoth3f7bf912013-03-10 00:37:21 +01002033static inline int hdspm_get_pll_freq(struct hdspm *hdspm)
2034{
2035 unsigned int period, rate;
2036
2037 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
2038 rate = hdspm_calc_dds_value(hdspm, period);
2039
2040 return rate;
2041}
2042
Adrian Knoth0dca1792011-01-26 19:32:14 +01002043/**
2044 * Calculate the real sample rate from the
2045 * current DDS value.
2046 **/
2047static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
2048{
Adrian Knoth3f7bf912013-03-10 00:37:21 +01002049 unsigned int rate;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002050
Adrian Knoth3f7bf912013-03-10 00:37:21 +01002051 rate = hdspm_get_pll_freq(hdspm);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002052
Adrian Knotha97bda72012-05-30 14:23:18 +02002053 if (rate > 207000) {
Adrian Knoth21a164d2012-10-19 17:42:23 +02002054 /* Unreasonable high sample rate as seen on PCI MADI cards. */
2055 if (0 == hdspm_system_clock_mode(hdspm)) {
2056 /* master mode, return internal sample rate */
2057 rate = hdspm->system_sample_rate;
2058 } else {
2059 /* slave mode, return external sample rate */
2060 rate = hdspm_external_sample_rate(hdspm);
2061 }
Adrian Knotha97bda72012-05-30 14:23:18 +02002062 }
2063
Adrian Knoth0dca1792011-01-26 19:32:14 +01002064 return rate;
2065}
2066
2067
Takashi Iwai763f3562005-06-03 11:25:34 +02002068#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02002069{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2070 .name = xname, \
2071 .index = xindex, \
2072 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2073 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2074 .info = snd_hdspm_info_system_sample_rate, \
2075 .put = snd_hdspm_put_system_sample_rate, \
2076 .get = snd_hdspm_get_system_sample_rate \
Takashi Iwai763f3562005-06-03 11:25:34 +02002077}
2078
Takashi Iwai98274f02005-11-17 14:52:34 +01002079static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
2080 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002081{
2082 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2083 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002084 uinfo->value.integer.min = 27000;
2085 uinfo->value.integer.max = 207000;
2086 uinfo->value.integer.step = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002087 return 0;
2088}
2089
Adrian Knoth0dca1792011-01-26 19:32:14 +01002090
Takashi Iwai98274f02005-11-17 14:52:34 +01002091static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
2092 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002093 ucontrol)
2094{
Takashi Iwai98274f02005-11-17 14:52:34 +01002095 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002096
Adrian Knoth0dca1792011-01-26 19:32:14 +01002097 ucontrol->value.integer.value[0] = hdspm_get_system_sample_rate(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002098 return 0;
2099}
2100
Adrian Knoth41285a92012-10-19 17:42:22 +02002101static int snd_hdspm_put_system_sample_rate(struct snd_kcontrol *kcontrol,
2102 struct snd_ctl_elem_value *
2103 ucontrol)
2104{
2105 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2106
2107 hdspm_set_dds_value(hdspm, ucontrol->value.enumerated.item[0]);
2108 return 0;
2109}
2110
Adrian Knoth0dca1792011-01-26 19:32:14 +01002111
2112/**
2113 * Returns the WordClock sample rate class for the given card.
2114 **/
2115static int hdspm_get_wc_sample_rate(struct hdspm *hdspm)
2116{
2117 int status;
2118
2119 switch (hdspm->io_type) {
2120 case RayDAT:
2121 case AIO:
2122 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2123 return (status >> 16) & 0xF;
2124 break;
2125 default:
2126 break;
2127 }
2128
2129
2130 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002131}
2132
Adrian Knoth0dca1792011-01-26 19:32:14 +01002133
2134/**
2135 * Returns the TCO sample rate class for the given card.
2136 **/
2137static int hdspm_get_tco_sample_rate(struct hdspm *hdspm)
2138{
2139 int status;
2140
2141 if (hdspm->tco) {
2142 switch (hdspm->io_type) {
2143 case RayDAT:
2144 case AIO:
2145 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2146 return (status >> 20) & 0xF;
2147 break;
2148 default:
2149 break;
2150 }
2151 }
2152
2153 return 0;
2154}
2155
2156
2157/**
2158 * Returns the SYNC_IN sample rate class for the given card.
2159 **/
2160static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm)
2161{
2162 int status;
2163
2164 if (hdspm->tco) {
2165 switch (hdspm->io_type) {
2166 case RayDAT:
2167 case AIO:
2168 status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2169 return (status >> 12) & 0xF;
2170 break;
2171 default:
2172 break;
2173 }
2174 }
2175
2176 return 0;
2177}
2178
2179
2180/**
2181 * Returns the sample rate class for input source <idx> for
2182 * 'new style' cards like the AIO and RayDAT.
2183 **/
2184static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
2185{
2186 int status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2187
2188 return (status >> (idx*4)) & 0xF;
2189}
2190
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01002191#define ENUMERATED_CTL_INFO(info, texts) \
2192{ \
2193 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; \
2194 uinfo->count = 1; \
2195 uinfo->value.enumerated.items = ARRAY_SIZE(texts); \
2196 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) \
2197 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; \
2198 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); \
2199}
2200
Adrian Knoth0dca1792011-01-26 19:32:14 +01002201
2202
2203#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
2204{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2205 .name = xname, \
2206 .private_value = xindex, \
2207 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2208 .info = snd_hdspm_info_autosync_sample_rate, \
2209 .get = snd_hdspm_get_autosync_sample_rate \
2210}
2211
2212
Takashi Iwai98274f02005-11-17 14:52:34 +01002213static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2214 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002215{
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01002216 ENUMERATED_CTL_INFO(uinfo, texts_freq);
Takashi Iwai763f3562005-06-03 11:25:34 +02002217 return 0;
2218}
2219
Adrian Knoth0dca1792011-01-26 19:32:14 +01002220
Takashi Iwai98274f02005-11-17 14:52:34 +01002221static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2222 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002223 ucontrol)
2224{
Takashi Iwai98274f02005-11-17 14:52:34 +01002225 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002226
Adrian Knoth0dca1792011-01-26 19:32:14 +01002227 switch (hdspm->io_type) {
2228 case RayDAT:
2229 switch (kcontrol->private_value) {
2230 case 0:
2231 ucontrol->value.enumerated.item[0] =
2232 hdspm_get_wc_sample_rate(hdspm);
2233 break;
2234 case 7:
2235 ucontrol->value.enumerated.item[0] =
2236 hdspm_get_tco_sample_rate(hdspm);
2237 break;
2238 case 8:
2239 ucontrol->value.enumerated.item[0] =
2240 hdspm_get_sync_in_sample_rate(hdspm);
2241 break;
2242 default:
2243 ucontrol->value.enumerated.item[0] =
2244 hdspm_get_s1_sample_rate(hdspm,
2245 kcontrol->private_value-1);
2246 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002247 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002248
Adrian Knoth0dca1792011-01-26 19:32:14 +01002249 case AIO:
2250 switch (kcontrol->private_value) {
2251 case 0: /* WC */
2252 ucontrol->value.enumerated.item[0] =
2253 hdspm_get_wc_sample_rate(hdspm);
2254 break;
2255 case 4: /* TCO */
2256 ucontrol->value.enumerated.item[0] =
2257 hdspm_get_tco_sample_rate(hdspm);
2258 break;
2259 case 5: /* SYNC_IN */
2260 ucontrol->value.enumerated.item[0] =
2261 hdspm_get_sync_in_sample_rate(hdspm);
2262 break;
2263 default:
2264 ucontrol->value.enumerated.item[0] =
2265 hdspm_get_s1_sample_rate(hdspm,
2266 ucontrol->id.index-1);
2267 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002268 break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002269
2270 case AES32:
2271
2272 switch (kcontrol->private_value) {
2273 case 0: /* WC */
2274 ucontrol->value.enumerated.item[0] =
2275 hdspm_get_wc_sample_rate(hdspm);
2276 break;
2277 case 9: /* TCO */
2278 ucontrol->value.enumerated.item[0] =
2279 hdspm_get_tco_sample_rate(hdspm);
2280 break;
2281 case 10: /* SYNC_IN */
2282 ucontrol->value.enumerated.item[0] =
2283 hdspm_get_sync_in_sample_rate(hdspm);
2284 break;
2285 default: /* AES1 to AES8 */
2286 ucontrol->value.enumerated.item[0] =
2287 hdspm_get_s1_sample_rate(hdspm,
2288 kcontrol->private_value-1);
2289 break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002290 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002291 break;
Adrian Knothb8812c52012-10-19 17:42:26 +02002292
2293 case MADI:
2294 case MADIface:
2295 {
2296 int rate = hdspm_external_sample_rate(hdspm);
2297 int i, selected_rate = 0;
2298 for (i = 1; i < 10; i++)
2299 if (HDSPM_bit2freq(i) == rate) {
2300 selected_rate = i;
2301 break;
2302 }
2303 ucontrol->value.enumerated.item[0] = selected_rate;
2304 }
2305 break;
2306
Takashi Iwai763f3562005-06-03 11:25:34 +02002307 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002308 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002309 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002310
Takashi Iwai763f3562005-06-03 11:25:34 +02002311 return 0;
2312}
2313
Adrian Knoth0dca1792011-01-26 19:32:14 +01002314
Takashi Iwai763f3562005-06-03 11:25:34 +02002315#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002316{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2317 .name = xname, \
2318 .index = xindex, \
2319 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2320 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2321 .info = snd_hdspm_info_system_clock_mode, \
2322 .get = snd_hdspm_get_system_clock_mode, \
2323 .put = snd_hdspm_put_system_clock_mode, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002324}
2325
2326
Adrian Knoth0dca1792011-01-26 19:32:14 +01002327/**
2328 * Returns the system clock mode for the given card.
2329 * @returns 0 - master, 1 - slave
2330 **/
2331static int hdspm_system_clock_mode(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002332{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002333 switch (hdspm->io_type) {
2334 case AIO:
2335 case RayDAT:
2336 if (hdspm->settings_register & HDSPM_c0Master)
2337 return 0;
2338 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002339
Adrian Knoth0dca1792011-01-26 19:32:14 +01002340 default:
2341 if (hdspm->control_register & HDSPM_ClockModeMaster)
2342 return 0;
2343 }
2344
Takashi Iwai763f3562005-06-03 11:25:34 +02002345 return 1;
2346}
2347
Adrian Knoth0dca1792011-01-26 19:32:14 +01002348
2349/**
2350 * Sets the system clock mode.
2351 * @param mode 0 - master, 1 - slave
2352 **/
2353static void hdspm_set_system_clock_mode(struct hdspm *hdspm, int mode)
2354{
2355 switch (hdspm->io_type) {
2356 case AIO:
2357 case RayDAT:
2358 if (0 == mode)
2359 hdspm->settings_register |= HDSPM_c0Master;
2360 else
2361 hdspm->settings_register &= ~HDSPM_c0Master;
2362
2363 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2364 break;
2365
2366 default:
2367 if (0 == mode)
2368 hdspm->control_register |= HDSPM_ClockModeMaster;
2369 else
2370 hdspm->control_register &= ~HDSPM_ClockModeMaster;
2371
2372 hdspm_write(hdspm, HDSPM_controlRegister,
2373 hdspm->control_register);
2374 }
2375}
2376
2377
Takashi Iwai98274f02005-11-17 14:52:34 +01002378static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
2379 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002380{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002381 static char *texts[] = { "Master", "AutoSync" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01002382 ENUMERATED_CTL_INFO(uinfo, texts);
Takashi Iwai763f3562005-06-03 11:25:34 +02002383 return 0;
2384}
2385
Takashi Iwai98274f02005-11-17 14:52:34 +01002386static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
2387 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002388{
Takashi Iwai98274f02005-11-17 14:52:34 +01002389 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002390
Adrian Knoth0dca1792011-01-26 19:32:14 +01002391 ucontrol->value.enumerated.item[0] = hdspm_system_clock_mode(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002392 return 0;
2393}
2394
Adrian Knoth0dca1792011-01-26 19:32:14 +01002395static int snd_hdspm_put_system_clock_mode(struct snd_kcontrol *kcontrol,
2396 struct snd_ctl_elem_value *ucontrol)
2397{
2398 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2399 int val;
2400
2401 if (!snd_hdspm_use_is_exclusive(hdspm))
2402 return -EBUSY;
2403
2404 val = ucontrol->value.enumerated.item[0];
2405 if (val < 0)
2406 val = 0;
2407 else if (val > 1)
2408 val = 1;
2409
2410 hdspm_set_system_clock_mode(hdspm, val);
2411
2412 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002413}
2414
Adrian Knoth0dca1792011-01-26 19:32:14 +01002415
2416#define HDSPM_INTERNAL_CLOCK(xname, xindex) \
2417{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2418 .name = xname, \
2419 .index = xindex, \
2420 .info = snd_hdspm_info_clock_source, \
2421 .get = snd_hdspm_get_clock_source, \
2422 .put = snd_hdspm_put_clock_source \
2423}
2424
2425
Takashi Iwai98274f02005-11-17 14:52:34 +01002426static int hdspm_clock_source(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002427{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002428 switch (hdspm->system_sample_rate) {
2429 case 32000: return 0;
2430 case 44100: return 1;
2431 case 48000: return 2;
2432 case 64000: return 3;
2433 case 88200: return 4;
2434 case 96000: return 5;
2435 case 128000: return 6;
2436 case 176400: return 7;
2437 case 192000: return 8;
Takashi Iwai763f3562005-06-03 11:25:34 +02002438 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002439
2440 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002441}
2442
Takashi Iwai98274f02005-11-17 14:52:34 +01002443static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
Takashi Iwai763f3562005-06-03 11:25:34 +02002444{
2445 int rate;
2446 switch (mode) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002447 case 0:
2448 rate = 32000; break;
2449 case 1:
2450 rate = 44100; break;
2451 case 2:
2452 rate = 48000; break;
2453 case 3:
2454 rate = 64000; break;
2455 case 4:
2456 rate = 88200; break;
2457 case 5:
2458 rate = 96000; break;
2459 case 6:
2460 rate = 128000; break;
2461 case 7:
2462 rate = 176400; break;
2463 case 8:
2464 rate = 192000; break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002465 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002466 rate = 48000;
Takashi Iwai763f3562005-06-03 11:25:34 +02002467 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002468 hdspm_set_rate(hdspm, rate, 1);
2469 return 0;
2470}
2471
Takashi Iwai98274f02005-11-17 14:52:34 +01002472static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
2473 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002474{
Takashi Iwai763f3562005-06-03 11:25:34 +02002475 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2476 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002477 uinfo->value.enumerated.items = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002478
2479 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2480 uinfo->value.enumerated.item =
2481 uinfo->value.enumerated.items - 1;
2482
2483 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002484 texts_freq[uinfo->value.enumerated.item+1]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002485
2486 return 0;
2487}
2488
Takashi Iwai98274f02005-11-17 14:52:34 +01002489static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
2490 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002491{
Takashi Iwai98274f02005-11-17 14:52:34 +01002492 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002493
2494 ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
2495 return 0;
2496}
2497
Takashi Iwai98274f02005-11-17 14:52:34 +01002498static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
2499 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002500{
Takashi Iwai98274f02005-11-17 14:52:34 +01002501 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002502 int change;
2503 int val;
2504
2505 if (!snd_hdspm_use_is_exclusive(hdspm))
2506 return -EBUSY;
2507 val = ucontrol->value.enumerated.item[0];
2508 if (val < 0)
2509 val = 0;
Remy Bruno65345992007-08-31 12:21:08 +02002510 if (val > 9)
2511 val = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002512 spin_lock_irq(&hdspm->lock);
2513 if (val != hdspm_clock_source(hdspm))
2514 change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
2515 else
2516 change = 0;
2517 spin_unlock_irq(&hdspm->lock);
2518 return change;
2519}
2520
Adrian Knoth0dca1792011-01-26 19:32:14 +01002521
Takashi Iwai763f3562005-06-03 11:25:34 +02002522#define HDSPM_PREF_SYNC_REF(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02002523{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002524 .name = xname, \
2525 .index = xindex, \
2526 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2527 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2528 .info = snd_hdspm_info_pref_sync_ref, \
2529 .get = snd_hdspm_get_pref_sync_ref, \
2530 .put = snd_hdspm_put_pref_sync_ref \
Takashi Iwai763f3562005-06-03 11:25:34 +02002531}
2532
Adrian Knoth0dca1792011-01-26 19:32:14 +01002533
2534/**
2535 * Returns the current preferred sync reference setting.
2536 * The semantics of the return value are depending on the
2537 * card, please see the comments for clarification.
2538 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002539static int hdspm_pref_sync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002540{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002541 switch (hdspm->io_type) {
2542 case AES32:
Remy Bruno3cee5a62006-10-16 12:46:32 +02002543 switch (hdspm->control_register & HDSPM_SyncRefMask) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002544 case 0: return 0; /* WC */
2545 case HDSPM_SyncRef0: return 1; /* AES 1 */
2546 case HDSPM_SyncRef1: return 2; /* AES 2 */
2547 case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; /* AES 3 */
2548 case HDSPM_SyncRef2: return 4; /* AES 4 */
2549 case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; /* AES 5 */
2550 case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; /* AES 6 */
2551 case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0:
2552 return 7; /* AES 7 */
2553 case HDSPM_SyncRef3: return 8; /* AES 8 */
2554 case HDSPM_SyncRef3+HDSPM_SyncRef0: return 9; /* TCO */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002555 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002556 break;
2557
2558 case MADI:
2559 case MADIface:
2560 if (hdspm->tco) {
2561 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2562 case 0: return 0; /* WC */
2563 case HDSPM_SyncRef0: return 1; /* MADI */
2564 case HDSPM_SyncRef1: return 2; /* TCO */
2565 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2566 return 3; /* SYNC_IN */
2567 }
2568 } else {
2569 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2570 case 0: return 0; /* WC */
2571 case HDSPM_SyncRef0: return 1; /* MADI */
2572 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2573 return 2; /* SYNC_IN */
2574 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02002575 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002576 break;
2577
2578 case RayDAT:
2579 if (hdspm->tco) {
2580 switch ((hdspm->settings_register &
2581 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2582 case 0: return 0; /* WC */
2583 case 3: return 1; /* ADAT 1 */
2584 case 4: return 2; /* ADAT 2 */
2585 case 5: return 3; /* ADAT 3 */
2586 case 6: return 4; /* ADAT 4 */
2587 case 1: return 5; /* AES */
2588 case 2: return 6; /* SPDIF */
2589 case 9: return 7; /* TCO */
2590 case 10: return 8; /* SYNC_IN */
2591 }
2592 } else {
2593 switch ((hdspm->settings_register &
2594 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2595 case 0: return 0; /* WC */
2596 case 3: return 1; /* ADAT 1 */
2597 case 4: return 2; /* ADAT 2 */
2598 case 5: return 3; /* ADAT 3 */
2599 case 6: return 4; /* ADAT 4 */
2600 case 1: return 5; /* AES */
2601 case 2: return 6; /* SPDIF */
2602 case 10: return 7; /* SYNC_IN */
2603 }
2604 }
2605
2606 break;
2607
2608 case AIO:
2609 if (hdspm->tco) {
2610 switch ((hdspm->settings_register &
2611 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2612 case 0: return 0; /* WC */
2613 case 3: return 1; /* ADAT */
2614 case 1: return 2; /* AES */
2615 case 2: return 3; /* SPDIF */
2616 case 9: return 4; /* TCO */
2617 case 10: return 5; /* SYNC_IN */
2618 }
2619 } else {
2620 switch ((hdspm->settings_register &
2621 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2622 case 0: return 0; /* WC */
2623 case 3: return 1; /* ADAT */
2624 case 1: return 2; /* AES */
2625 case 2: return 3; /* SPDIF */
2626 case 10: return 4; /* SYNC_IN */
2627 }
2628 }
2629
2630 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002631 }
2632
Adrian Knoth0dca1792011-01-26 19:32:14 +01002633 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002634}
2635
Adrian Knoth0dca1792011-01-26 19:32:14 +01002636
2637/**
2638 * Set the preferred sync reference to <pref>. The semantics
2639 * of <pref> are depending on the card type, see the comments
2640 * for clarification.
2641 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002642static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
Takashi Iwai763f3562005-06-03 11:25:34 +02002643{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002644 int p = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002645
Adrian Knoth0dca1792011-01-26 19:32:14 +01002646 switch (hdspm->io_type) {
2647 case AES32:
2648 hdspm->control_register &= ~HDSPM_SyncRefMask;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002649 switch (pref) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002650 case 0: /* WC */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002651 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002652 case 1: /* AES 1 */
2653 hdspm->control_register |= HDSPM_SyncRef0;
2654 break;
2655 case 2: /* AES 2 */
2656 hdspm->control_register |= HDSPM_SyncRef1;
2657 break;
2658 case 3: /* AES 3 */
2659 hdspm->control_register |=
2660 HDSPM_SyncRef1+HDSPM_SyncRef0;
2661 break;
2662 case 4: /* AES 4 */
2663 hdspm->control_register |= HDSPM_SyncRef2;
2664 break;
2665 case 5: /* AES 5 */
2666 hdspm->control_register |=
2667 HDSPM_SyncRef2+HDSPM_SyncRef0;
2668 break;
2669 case 6: /* AES 6 */
2670 hdspm->control_register |=
2671 HDSPM_SyncRef2+HDSPM_SyncRef1;
2672 break;
2673 case 7: /* AES 7 */
2674 hdspm->control_register |=
2675 HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
2676 break;
2677 case 8: /* AES 8 */
2678 hdspm->control_register |= HDSPM_SyncRef3;
2679 break;
2680 case 9: /* TCO */
2681 hdspm->control_register |=
2682 HDSPM_SyncRef3+HDSPM_SyncRef0;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002683 break;
2684 default:
2685 return -1;
2686 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002687
2688 break;
2689
2690 case MADI:
2691 case MADIface:
2692 hdspm->control_register &= ~HDSPM_SyncRefMask;
2693 if (hdspm->tco) {
2694 switch (pref) {
2695 case 0: /* WC */
2696 break;
2697 case 1: /* MADI */
2698 hdspm->control_register |= HDSPM_SyncRef0;
2699 break;
2700 case 2: /* TCO */
2701 hdspm->control_register |= HDSPM_SyncRef1;
2702 break;
2703 case 3: /* SYNC_IN */
2704 hdspm->control_register |=
2705 HDSPM_SyncRef0+HDSPM_SyncRef1;
2706 break;
2707 default:
2708 return -1;
2709 }
2710 } else {
2711 switch (pref) {
2712 case 0: /* WC */
2713 break;
2714 case 1: /* MADI */
2715 hdspm->control_register |= HDSPM_SyncRef0;
2716 break;
2717 case 2: /* SYNC_IN */
2718 hdspm->control_register |=
2719 HDSPM_SyncRef0+HDSPM_SyncRef1;
2720 break;
2721 default:
2722 return -1;
2723 }
2724 }
2725
2726 break;
2727
2728 case RayDAT:
2729 if (hdspm->tco) {
2730 switch (pref) {
2731 case 0: p = 0; break; /* WC */
2732 case 1: p = 3; break; /* ADAT 1 */
2733 case 2: p = 4; break; /* ADAT 2 */
2734 case 3: p = 5; break; /* ADAT 3 */
2735 case 4: p = 6; break; /* ADAT 4 */
2736 case 5: p = 1; break; /* AES */
2737 case 6: p = 2; break; /* SPDIF */
2738 case 7: p = 9; break; /* TCO */
2739 case 8: p = 10; break; /* SYNC_IN */
2740 default: return -1;
2741 }
2742 } else {
2743 switch (pref) {
2744 case 0: p = 0; break; /* WC */
2745 case 1: p = 3; break; /* ADAT 1 */
2746 case 2: p = 4; break; /* ADAT 2 */
2747 case 3: p = 5; break; /* ADAT 3 */
2748 case 4: p = 6; break; /* ADAT 4 */
2749 case 5: p = 1; break; /* AES */
2750 case 6: p = 2; break; /* SPDIF */
2751 case 7: p = 10; break; /* SYNC_IN */
2752 default: return -1;
2753 }
2754 }
2755 break;
2756
2757 case AIO:
2758 if (hdspm->tco) {
2759 switch (pref) {
2760 case 0: p = 0; break; /* WC */
2761 case 1: p = 3; break; /* ADAT */
2762 case 2: p = 1; break; /* AES */
2763 case 3: p = 2; break; /* SPDIF */
2764 case 4: p = 9; break; /* TCO */
2765 case 5: p = 10; break; /* SYNC_IN */
2766 default: return -1;
2767 }
2768 } else {
2769 switch (pref) {
2770 case 0: p = 0; break; /* WC */
2771 case 1: p = 3; break; /* ADAT */
2772 case 2: p = 1; break; /* AES */
2773 case 3: p = 2; break; /* SPDIF */
2774 case 4: p = 10; break; /* SYNC_IN */
2775 default: return -1;
2776 }
2777 }
2778 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002779 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002780
2781 switch (hdspm->io_type) {
2782 case RayDAT:
2783 case AIO:
2784 hdspm->settings_register &= ~HDSPM_c0_SyncRefMask;
2785 hdspm->settings_register |= HDSPM_c0_SyncRef0 * p;
2786 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2787 break;
2788
2789 case MADI:
2790 case MADIface:
2791 case AES32:
2792 hdspm_write(hdspm, HDSPM_controlRegister,
2793 hdspm->control_register);
2794 }
2795
Takashi Iwai763f3562005-06-03 11:25:34 +02002796 return 0;
2797}
2798
Adrian Knoth0dca1792011-01-26 19:32:14 +01002799
Takashi Iwai98274f02005-11-17 14:52:34 +01002800static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
2801 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002802{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002803 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002804
Adrian Knoth0dca1792011-01-26 19:32:14 +01002805 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2806 uinfo->count = 1;
2807 uinfo->value.enumerated.items = hdspm->texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +02002808
Adrian Knoth0dca1792011-01-26 19:32:14 +01002809 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2810 uinfo->value.enumerated.item =
2811 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002812
Adrian Knoth0dca1792011-01-26 19:32:14 +01002813 strcpy(uinfo->value.enumerated.name,
2814 hdspm->texts_autosync[uinfo->value.enumerated.item]);
Remy Bruno3cee5a62006-10-16 12:46:32 +02002815
Takashi Iwai763f3562005-06-03 11:25:34 +02002816 return 0;
2817}
2818
Takashi Iwai98274f02005-11-17 14:52:34 +01002819static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
2820 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002821{
Takashi Iwai98274f02005-11-17 14:52:34 +01002822 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002823 int psf = hdspm_pref_sync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002824
Adrian Knoth0dca1792011-01-26 19:32:14 +01002825 if (psf >= 0) {
2826 ucontrol->value.enumerated.item[0] = psf;
2827 return 0;
2828 }
2829
2830 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002831}
2832
Takashi Iwai98274f02005-11-17 14:52:34 +01002833static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
2834 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002835{
Takashi Iwai98274f02005-11-17 14:52:34 +01002836 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002837 int val, change = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002838
2839 if (!snd_hdspm_use_is_exclusive(hdspm))
2840 return -EBUSY;
2841
Adrian Knoth0dca1792011-01-26 19:32:14 +01002842 val = ucontrol->value.enumerated.item[0];
2843
2844 if (val < 0)
2845 val = 0;
2846 else if (val >= hdspm->texts_autosync_items)
2847 val = hdspm->texts_autosync_items-1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002848
2849 spin_lock_irq(&hdspm->lock);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002850 if (val != hdspm_pref_sync_ref(hdspm))
2851 change = (0 == hdspm_set_pref_sync_ref(hdspm, val)) ? 1 : 0;
2852
Takashi Iwai763f3562005-06-03 11:25:34 +02002853 spin_unlock_irq(&hdspm->lock);
2854 return change;
2855}
2856
Adrian Knoth0dca1792011-01-26 19:32:14 +01002857
Takashi Iwai763f3562005-06-03 11:25:34 +02002858#define HDSPM_AUTOSYNC_REF(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02002859{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2860 .name = xname, \
2861 .index = xindex, \
2862 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2863 .info = snd_hdspm_info_autosync_ref, \
2864 .get = snd_hdspm_get_autosync_ref, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002865}
2866
Adrian Knoth0dca1792011-01-26 19:32:14 +01002867static int hdspm_autosync_ref(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002868{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002869 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002870 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002871 unsigned int syncref =
2872 (status >> HDSPM_AES32_syncref_bit) & 0xF;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002873 if (syncref == 0)
2874 return HDSPM_AES32_AUTOSYNC_FROM_WORD;
2875 if (syncref <= 8)
2876 return syncref;
2877 return HDSPM_AES32_AUTOSYNC_FROM_NONE;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002878 } else if (MADI == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002879 /* This looks at the autosync selected sync reference */
2880 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Takashi Iwai763f3562005-06-03 11:25:34 +02002881
Remy Bruno3cee5a62006-10-16 12:46:32 +02002882 switch (status2 & HDSPM_SelSyncRefMask) {
2883 case HDSPM_SelSyncRef_WORD:
2884 return HDSPM_AUTOSYNC_FROM_WORD;
2885 case HDSPM_SelSyncRef_MADI:
2886 return HDSPM_AUTOSYNC_FROM_MADI;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002887 case HDSPM_SelSyncRef_TCO:
2888 return HDSPM_AUTOSYNC_FROM_TCO;
2889 case HDSPM_SelSyncRef_SyncIn:
2890 return HDSPM_AUTOSYNC_FROM_SYNC_IN;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002891 case HDSPM_SelSyncRef_NVALID:
2892 return HDSPM_AUTOSYNC_FROM_NONE;
2893 default:
2894 return 0;
2895 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002896
Takashi Iwai763f3562005-06-03 11:25:34 +02002897 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002898 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002899}
2900
Adrian Knoth0dca1792011-01-26 19:32:14 +01002901
Takashi Iwai98274f02005-11-17 14:52:34 +01002902static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
2903 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002904{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002905 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002906
Adrian Knoth0dca1792011-01-26 19:32:14 +01002907 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002908 static char *texts[] = { "WordClock", "AES1", "AES2", "AES3",
2909 "AES4", "AES5", "AES6", "AES7", "AES8", "None"};
2910
2911 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2912 uinfo->count = 1;
2913 uinfo->value.enumerated.items = 10;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002914 if (uinfo->value.enumerated.item >=
2915 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002916 uinfo->value.enumerated.item =
2917 uinfo->value.enumerated.items - 1;
2918 strcpy(uinfo->value.enumerated.name,
2919 texts[uinfo->value.enumerated.item]);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002920 } else if (MADI == hdspm->io_type) {
2921 static char *texts[] = {"Word Clock", "MADI", "TCO",
2922 "Sync In", "None" };
Remy Bruno3cee5a62006-10-16 12:46:32 +02002923
2924 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2925 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002926 uinfo->value.enumerated.items = 5;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002927 if (uinfo->value.enumerated.item >=
Adrian Knoth0dca1792011-01-26 19:32:14 +01002928 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002929 uinfo->value.enumerated.item =
2930 uinfo->value.enumerated.items - 1;
2931 strcpy(uinfo->value.enumerated.name,
2932 texts[uinfo->value.enumerated.item]);
2933 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002934 return 0;
2935}
2936
Takashi Iwai98274f02005-11-17 14:52:34 +01002937static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
2938 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002939{
Takashi Iwai98274f02005-11-17 14:52:34 +01002940 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002941
Remy Bruno65345992007-08-31 12:21:08 +02002942 ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002943 return 0;
2944}
2945
Adrian Knothf99c7882013-03-10 00:37:26 +01002946
2947
2948#define HDSPM_TCO_VIDEO_INPUT_FORMAT(xname, xindex) \
2949{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2950 .name = xname, \
2951 .access = SNDRV_CTL_ELEM_ACCESS_READ |\
2952 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2953 .info = snd_hdspm_info_tco_video_input_format, \
2954 .get = snd_hdspm_get_tco_video_input_format, \
2955}
2956
2957static int snd_hdspm_info_tco_video_input_format(struct snd_kcontrol *kcontrol,
2958 struct snd_ctl_elem_info *uinfo)
2959{
2960 static char *texts[] = {"No video", "NTSC", "PAL"};
2961 ENUMERATED_CTL_INFO(uinfo, texts);
2962 return 0;
2963}
2964
2965static int snd_hdspm_get_tco_video_input_format(struct snd_kcontrol *kcontrol,
2966 struct snd_ctl_elem_value *ucontrol)
2967{
2968 u32 status;
2969 int ret = 0;
2970
2971 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2972 status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
2973 switch (status & (HDSPM_TCO1_Video_Input_Format_NTSC |
2974 HDSPM_TCO1_Video_Input_Format_PAL)) {
2975 case HDSPM_TCO1_Video_Input_Format_NTSC:
2976 /* ntsc */
2977 ret = 1;
2978 break;
2979 case HDSPM_TCO1_Video_Input_Format_PAL:
2980 /* pal */
2981 ret = 2;
2982 break;
2983 default:
2984 /* no video */
2985 ret = 0;
2986 break;
2987 }
2988 ucontrol->value.enumerated.item[0] = ret;
2989 return 0;
2990}
2991
2992
2993
2994#define HDSPM_TCO_LTC_FRAMES(xname, xindex) \
2995{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2996 .name = xname, \
2997 .access = SNDRV_CTL_ELEM_ACCESS_READ |\
2998 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2999 .info = snd_hdspm_info_tco_ltc_frames, \
3000 .get = snd_hdspm_get_tco_ltc_frames, \
3001}
3002
3003static int snd_hdspm_info_tco_ltc_frames(struct snd_kcontrol *kcontrol,
3004 struct snd_ctl_elem_info *uinfo)
3005{
3006 static char *texts[] = {"No lock", "24 fps", "25 fps", "29.97 fps",
3007 "30 fps"};
3008 ENUMERATED_CTL_INFO(uinfo, texts);
3009 return 0;
3010}
3011
3012static int hdspm_tco_ltc_frames(struct hdspm *hdspm)
3013{
3014 u32 status;
3015 int ret = 0;
3016
3017 status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
3018 if (status & HDSPM_TCO1_LTC_Input_valid) {
3019 switch (status & (HDSPM_TCO1_LTC_Format_LSB |
3020 HDSPM_TCO1_LTC_Format_MSB)) {
3021 case 0:
3022 /* 24 fps */
3023 ret = 1;
3024 break;
3025 case HDSPM_TCO1_LTC_Format_LSB:
3026 /* 25 fps */
3027 ret = 2;
3028 break;
3029 case HDSPM_TCO1_LTC_Format_MSB:
3030 /* 25 fps */
3031 ret = 3;
3032 break;
3033 default:
3034 /* 30 fps */
3035 ret = 4;
3036 break;
3037 }
3038 }
3039
3040 return ret;
3041}
3042
3043static int snd_hdspm_get_tco_ltc_frames(struct snd_kcontrol *kcontrol,
3044 struct snd_ctl_elem_value *ucontrol)
3045{
3046 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3047
3048 ucontrol->value.enumerated.item[0] = hdspm_tco_ltc_frames(hdspm);
3049 return 0;
3050}
3051
Adrian Knothbf0ff872012-12-03 14:55:49 +01003052#define HDSPM_TOGGLE_SETTING(xname, xindex) \
3053{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3054 .name = xname, \
3055 .private_value = xindex, \
3056 .info = snd_hdspm_info_toggle_setting, \
3057 .get = snd_hdspm_get_toggle_setting, \
3058 .put = snd_hdspm_put_toggle_setting \
3059}
3060
3061static int hdspm_toggle_setting(struct hdspm *hdspm, u32 regmask)
3062{
3063 return (hdspm->control_register & regmask) ? 1 : 0;
3064}
3065
3066static int hdspm_set_toggle_setting(struct hdspm *hdspm, u32 regmask, int out)
3067{
3068 if (out)
3069 hdspm->control_register |= regmask;
3070 else
3071 hdspm->control_register &= ~regmask;
3072 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3073
3074 return 0;
3075}
3076
3077#define snd_hdspm_info_toggle_setting snd_ctl_boolean_mono_info
3078
3079static int snd_hdspm_get_toggle_setting(struct snd_kcontrol *kcontrol,
3080 struct snd_ctl_elem_value *ucontrol)
3081{
3082 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3083 u32 regmask = kcontrol->private_value;
3084
3085 spin_lock_irq(&hdspm->lock);
3086 ucontrol->value.integer.value[0] = hdspm_toggle_setting(hdspm, regmask);
3087 spin_unlock_irq(&hdspm->lock);
3088 return 0;
3089}
3090
3091static int snd_hdspm_put_toggle_setting(struct snd_kcontrol *kcontrol,
3092 struct snd_ctl_elem_value *ucontrol)
3093{
3094 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3095 u32 regmask = kcontrol->private_value;
3096 int change;
3097 unsigned int val;
3098
3099 if (!snd_hdspm_use_is_exclusive(hdspm))
3100 return -EBUSY;
3101 val = ucontrol->value.integer.value[0] & 1;
3102 spin_lock_irq(&hdspm->lock);
3103 change = (int) val != hdspm_toggle_setting(hdspm, regmask);
3104 hdspm_set_toggle_setting(hdspm, regmask, val);
3105 spin_unlock_irq(&hdspm->lock);
3106 return change;
3107}
3108
Takashi Iwai763f3562005-06-03 11:25:34 +02003109#define HDSPM_INPUT_SELECT(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003110{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3111 .name = xname, \
3112 .index = xindex, \
3113 .info = snd_hdspm_info_input_select, \
3114 .get = snd_hdspm_get_input_select, \
3115 .put = snd_hdspm_put_input_select \
Takashi Iwai763f3562005-06-03 11:25:34 +02003116}
3117
Takashi Iwai98274f02005-11-17 14:52:34 +01003118static int hdspm_input_select(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003119{
3120 return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
3121}
3122
Takashi Iwai98274f02005-11-17 14:52:34 +01003123static int hdspm_set_input_select(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02003124{
3125 if (out)
3126 hdspm->control_register |= HDSPM_InputSelect0;
3127 else
3128 hdspm->control_register &= ~HDSPM_InputSelect0;
3129 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3130
3131 return 0;
3132}
3133
Takashi Iwai98274f02005-11-17 14:52:34 +01003134static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
3135 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003136{
3137 static char *texts[] = { "optical", "coaxial" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003138 ENUMERATED_CTL_INFO(uinfo, texts);
Takashi Iwai763f3562005-06-03 11:25:34 +02003139 return 0;
3140}
3141
Takashi Iwai98274f02005-11-17 14:52:34 +01003142static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
3143 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003144{
Takashi Iwai98274f02005-11-17 14:52:34 +01003145 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003146
3147 spin_lock_irq(&hdspm->lock);
3148 ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
3149 spin_unlock_irq(&hdspm->lock);
3150 return 0;
3151}
3152
Takashi Iwai98274f02005-11-17 14:52:34 +01003153static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
3154 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003155{
Takashi Iwai98274f02005-11-17 14:52:34 +01003156 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003157 int change;
3158 unsigned int val;
3159
3160 if (!snd_hdspm_use_is_exclusive(hdspm))
3161 return -EBUSY;
3162 val = ucontrol->value.integer.value[0] & 1;
3163 spin_lock_irq(&hdspm->lock);
3164 change = (int) val != hdspm_input_select(hdspm);
3165 hdspm_set_input_select(hdspm, val);
3166 spin_unlock_irq(&hdspm->lock);
3167 return change;
3168}
3169
Adrian Knoth0dca1792011-01-26 19:32:14 +01003170
Remy Bruno3cee5a62006-10-16 12:46:32 +02003171#define HDSPM_DS_WIRE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003172{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3173 .name = xname, \
3174 .index = xindex, \
3175 .info = snd_hdspm_info_ds_wire, \
3176 .get = snd_hdspm_get_ds_wire, \
3177 .put = snd_hdspm_put_ds_wire \
Remy Bruno3cee5a62006-10-16 12:46:32 +02003178}
3179
3180static int hdspm_ds_wire(struct hdspm * hdspm)
3181{
3182 return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
3183}
3184
3185static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
3186{
3187 if (ds)
3188 hdspm->control_register |= HDSPM_DS_DoubleWire;
3189 else
3190 hdspm->control_register &= ~HDSPM_DS_DoubleWire;
3191 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3192
3193 return 0;
3194}
3195
3196static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
3197 struct snd_ctl_elem_info *uinfo)
3198{
3199 static char *texts[] = { "Single", "Double" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003200 ENUMERATED_CTL_INFO(uinfo, texts);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003201 return 0;
3202}
3203
3204static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
3205 struct snd_ctl_elem_value *ucontrol)
3206{
3207 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3208
3209 spin_lock_irq(&hdspm->lock);
3210 ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
3211 spin_unlock_irq(&hdspm->lock);
3212 return 0;
3213}
3214
3215static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
3216 struct snd_ctl_elem_value *ucontrol)
3217{
3218 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3219 int change;
3220 unsigned int val;
3221
3222 if (!snd_hdspm_use_is_exclusive(hdspm))
3223 return -EBUSY;
3224 val = ucontrol->value.integer.value[0] & 1;
3225 spin_lock_irq(&hdspm->lock);
3226 change = (int) val != hdspm_ds_wire(hdspm);
3227 hdspm_set_ds_wire(hdspm, val);
3228 spin_unlock_irq(&hdspm->lock);
3229 return change;
3230}
3231
Adrian Knoth0dca1792011-01-26 19:32:14 +01003232
Remy Bruno3cee5a62006-10-16 12:46:32 +02003233#define HDSPM_QS_WIRE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003234{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3235 .name = xname, \
3236 .index = xindex, \
3237 .info = snd_hdspm_info_qs_wire, \
3238 .get = snd_hdspm_get_qs_wire, \
3239 .put = snd_hdspm_put_qs_wire \
Remy Bruno3cee5a62006-10-16 12:46:32 +02003240}
3241
3242static int hdspm_qs_wire(struct hdspm * hdspm)
3243{
3244 if (hdspm->control_register & HDSPM_QS_DoubleWire)
3245 return 1;
3246 if (hdspm->control_register & HDSPM_QS_QuadWire)
3247 return 2;
3248 return 0;
3249}
3250
3251static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
3252{
3253 hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
3254 switch (mode) {
3255 case 0:
3256 break;
3257 case 1:
3258 hdspm->control_register |= HDSPM_QS_DoubleWire;
3259 break;
3260 case 2:
3261 hdspm->control_register |= HDSPM_QS_QuadWire;
3262 break;
3263 }
3264 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3265
3266 return 0;
3267}
3268
3269static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
3270 struct snd_ctl_elem_info *uinfo)
3271{
3272 static char *texts[] = { "Single", "Double", "Quad" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003273 ENUMERATED_CTL_INFO(uinfo, texts);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003274 return 0;
3275}
3276
3277static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
3278 struct snd_ctl_elem_value *ucontrol)
3279{
3280 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3281
3282 spin_lock_irq(&hdspm->lock);
3283 ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
3284 spin_unlock_irq(&hdspm->lock);
3285 return 0;
3286}
3287
3288static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
3289 struct snd_ctl_elem_value *ucontrol)
3290{
3291 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3292 int change;
3293 int val;
3294
3295 if (!snd_hdspm_use_is_exclusive(hdspm))
3296 return -EBUSY;
3297 val = ucontrol->value.integer.value[0];
3298 if (val < 0)
3299 val = 0;
3300 if (val > 2)
3301 val = 2;
3302 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003303 change = val != hdspm_qs_wire(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003304 hdspm_set_qs_wire(hdspm, val);
3305 spin_unlock_irq(&hdspm->lock);
3306 return change;
3307}
3308
Adrian Knoth700d1ef2011-07-29 03:11:02 +02003309#define HDSPM_MADI_SPEEDMODE(xname, xindex) \
3310{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3311 .name = xname, \
3312 .index = xindex, \
3313 .info = snd_hdspm_info_madi_speedmode, \
3314 .get = snd_hdspm_get_madi_speedmode, \
3315 .put = snd_hdspm_put_madi_speedmode \
3316}
3317
3318static int hdspm_madi_speedmode(struct hdspm *hdspm)
3319{
3320 if (hdspm->control_register & HDSPM_QuadSpeed)
3321 return 2;
3322 if (hdspm->control_register & HDSPM_DoubleSpeed)
3323 return 1;
3324 return 0;
3325}
3326
3327static int hdspm_set_madi_speedmode(struct hdspm *hdspm, int mode)
3328{
3329 hdspm->control_register &= ~(HDSPM_DoubleSpeed | HDSPM_QuadSpeed);
3330 switch (mode) {
3331 case 0:
3332 break;
3333 case 1:
3334 hdspm->control_register |= HDSPM_DoubleSpeed;
3335 break;
3336 case 2:
3337 hdspm->control_register |= HDSPM_QuadSpeed;
3338 break;
3339 }
3340 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3341
3342 return 0;
3343}
3344
3345static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol,
3346 struct snd_ctl_elem_info *uinfo)
3347{
3348 static char *texts[] = { "Single", "Double", "Quad" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003349 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth700d1ef2011-07-29 03:11:02 +02003350 return 0;
3351}
3352
3353static int snd_hdspm_get_madi_speedmode(struct snd_kcontrol *kcontrol,
3354 struct snd_ctl_elem_value *ucontrol)
3355{
3356 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3357
3358 spin_lock_irq(&hdspm->lock);
3359 ucontrol->value.enumerated.item[0] = hdspm_madi_speedmode(hdspm);
3360 spin_unlock_irq(&hdspm->lock);
3361 return 0;
3362}
3363
3364static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol,
3365 struct snd_ctl_elem_value *ucontrol)
3366{
3367 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3368 int change;
3369 int val;
3370
3371 if (!snd_hdspm_use_is_exclusive(hdspm))
3372 return -EBUSY;
3373 val = ucontrol->value.integer.value[0];
3374 if (val < 0)
3375 val = 0;
3376 if (val > 2)
3377 val = 2;
3378 spin_lock_irq(&hdspm->lock);
3379 change = val != hdspm_madi_speedmode(hdspm);
3380 hdspm_set_madi_speedmode(hdspm, val);
3381 spin_unlock_irq(&hdspm->lock);
3382 return change;
3383}
Takashi Iwai763f3562005-06-03 11:25:34 +02003384
3385#define HDSPM_MIXER(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003386{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
3387 .name = xname, \
3388 .index = xindex, \
3389 .device = 0, \
3390 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
3391 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3392 .info = snd_hdspm_info_mixer, \
3393 .get = snd_hdspm_get_mixer, \
3394 .put = snd_hdspm_put_mixer \
Takashi Iwai763f3562005-06-03 11:25:34 +02003395}
3396
Takashi Iwai98274f02005-11-17 14:52:34 +01003397static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
3398 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003399{
3400 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3401 uinfo->count = 3;
3402 uinfo->value.integer.min = 0;
3403 uinfo->value.integer.max = 65535;
3404 uinfo->value.integer.step = 1;
3405 return 0;
3406}
3407
Takashi Iwai98274f02005-11-17 14:52:34 +01003408static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
3409 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003410{
Takashi Iwai98274f02005-11-17 14:52:34 +01003411 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003412 int source;
3413 int destination;
3414
3415 source = ucontrol->value.integer.value[0];
3416 if (source < 0)
3417 source = 0;
3418 else if (source >= 2 * HDSPM_MAX_CHANNELS)
3419 source = 2 * HDSPM_MAX_CHANNELS - 1;
3420
3421 destination = ucontrol->value.integer.value[1];
3422 if (destination < 0)
3423 destination = 0;
3424 else if (destination >= HDSPM_MAX_CHANNELS)
3425 destination = HDSPM_MAX_CHANNELS - 1;
3426
3427 spin_lock_irq(&hdspm->lock);
3428 if (source >= HDSPM_MAX_CHANNELS)
3429 ucontrol->value.integer.value[2] =
3430 hdspm_read_pb_gain(hdspm, destination,
3431 source - HDSPM_MAX_CHANNELS);
3432 else
3433 ucontrol->value.integer.value[2] =
3434 hdspm_read_in_gain(hdspm, destination, source);
3435
3436 spin_unlock_irq(&hdspm->lock);
3437
3438 return 0;
3439}
3440
Takashi Iwai98274f02005-11-17 14:52:34 +01003441static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
3442 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003443{
Takashi Iwai98274f02005-11-17 14:52:34 +01003444 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003445 int change;
3446 int source;
3447 int destination;
3448 int gain;
3449
3450 if (!snd_hdspm_use_is_exclusive(hdspm))
3451 return -EBUSY;
3452
3453 source = ucontrol->value.integer.value[0];
3454 destination = ucontrol->value.integer.value[1];
3455
3456 if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
3457 return -1;
3458 if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
3459 return -1;
3460
3461 gain = ucontrol->value.integer.value[2];
3462
3463 spin_lock_irq(&hdspm->lock);
3464
3465 if (source >= HDSPM_MAX_CHANNELS)
3466 change = gain != hdspm_read_pb_gain(hdspm, destination,
3467 source -
3468 HDSPM_MAX_CHANNELS);
3469 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003470 change = gain != hdspm_read_in_gain(hdspm, destination,
3471 source);
Takashi Iwai763f3562005-06-03 11:25:34 +02003472
3473 if (change) {
3474 if (source >= HDSPM_MAX_CHANNELS)
3475 hdspm_write_pb_gain(hdspm, destination,
3476 source - HDSPM_MAX_CHANNELS,
3477 gain);
3478 else
3479 hdspm_write_in_gain(hdspm, destination, source,
3480 gain);
3481 }
3482 spin_unlock_irq(&hdspm->lock);
3483
3484 return change;
3485}
3486
3487/* The simple mixer control(s) provide gain control for the
3488 basic 1:1 mappings of playback streams to output
Adrian Knoth0dca1792011-01-26 19:32:14 +01003489 streams.
Takashi Iwai763f3562005-06-03 11:25:34 +02003490*/
3491
3492#define HDSPM_PLAYBACK_MIXER \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003493{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3494 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
3495 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3496 .info = snd_hdspm_info_playback_mixer, \
3497 .get = snd_hdspm_get_playback_mixer, \
3498 .put = snd_hdspm_put_playback_mixer \
Takashi Iwai763f3562005-06-03 11:25:34 +02003499}
3500
Takashi Iwai98274f02005-11-17 14:52:34 +01003501static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
3502 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003503{
3504 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3505 uinfo->count = 1;
3506 uinfo->value.integer.min = 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003507 uinfo->value.integer.max = 64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003508 uinfo->value.integer.step = 1;
3509 return 0;
3510}
3511
Takashi Iwai98274f02005-11-17 14:52:34 +01003512static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
3513 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003514{
Takashi Iwai98274f02005-11-17 14:52:34 +01003515 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003516 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003517
3518 channel = ucontrol->id.index - 1;
3519
Takashi Iwaida3cec32008-08-08 17:12:14 +02003520 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3521 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003522
Takashi Iwai763f3562005-06-03 11:25:34 +02003523 spin_lock_irq(&hdspm->lock);
3524 ucontrol->value.integer.value[0] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003525 (hdspm_read_pb_gain(hdspm, channel, channel)*64)/UNITY_GAIN;
Takashi Iwai763f3562005-06-03 11:25:34 +02003526 spin_unlock_irq(&hdspm->lock);
3527
Takashi Iwai763f3562005-06-03 11:25:34 +02003528 return 0;
3529}
3530
Takashi Iwai98274f02005-11-17 14:52:34 +01003531static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
3532 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003533{
Takashi Iwai98274f02005-11-17 14:52:34 +01003534 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003535 int change;
3536 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003537 int gain;
3538
3539 if (!snd_hdspm_use_is_exclusive(hdspm))
3540 return -EBUSY;
3541
3542 channel = ucontrol->id.index - 1;
3543
Takashi Iwaida3cec32008-08-08 17:12:14 +02003544 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3545 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003546
Adrian Knoth0dca1792011-01-26 19:32:14 +01003547 gain = ucontrol->value.integer.value[0]*UNITY_GAIN/64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003548
3549 spin_lock_irq(&hdspm->lock);
3550 change =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003551 gain != hdspm_read_pb_gain(hdspm, channel,
3552 channel);
Takashi Iwai763f3562005-06-03 11:25:34 +02003553 if (change)
Adrian Knoth0dca1792011-01-26 19:32:14 +01003554 hdspm_write_pb_gain(hdspm, channel, channel,
Takashi Iwai763f3562005-06-03 11:25:34 +02003555 gain);
3556 spin_unlock_irq(&hdspm->lock);
3557 return change;
3558}
3559
Adrian Knoth0dca1792011-01-26 19:32:14 +01003560#define HDSPM_SYNC_CHECK(xname, xindex) \
3561{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3562 .name = xname, \
3563 .private_value = xindex, \
3564 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3565 .info = snd_hdspm_info_sync_check, \
3566 .get = snd_hdspm_get_sync_check \
Takashi Iwai763f3562005-06-03 11:25:34 +02003567}
3568
Adrian Knoth34542212013-03-10 00:37:25 +01003569#define HDSPM_TCO_LOCK_CHECK(xname, xindex) \
3570{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3571 .name = xname, \
3572 .private_value = xindex, \
3573 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3574 .info = snd_hdspm_tco_info_lock_check, \
3575 .get = snd_hdspm_get_sync_check \
3576}
3577
3578
Adrian Knoth0dca1792011-01-26 19:32:14 +01003579
Takashi Iwai98274f02005-11-17 14:52:34 +01003580static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
3581 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003582{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003583 static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003584 ENUMERATED_CTL_INFO(uinfo, texts);
Takashi Iwai763f3562005-06-03 11:25:34 +02003585 return 0;
3586}
3587
Adrian Knoth34542212013-03-10 00:37:25 +01003588static int snd_hdspm_tco_info_lock_check(struct snd_kcontrol *kcontrol,
3589 struct snd_ctl_elem_info *uinfo)
3590{
3591 static char *texts[] = { "No Lock", "Lock" };
3592 ENUMERATED_CTL_INFO(uinfo, texts);
3593 return 0;
3594}
3595
Adrian Knoth0dca1792011-01-26 19:32:14 +01003596static int hdspm_wc_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003597{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003598 int status, status2;
3599
3600 switch (hdspm->io_type) {
3601 case AES32:
3602 status = hdspm_read(hdspm, HDSPM_statusRegister);
Andre Schramm56bde0f2013-01-09 14:40:18 +01003603 if (status & HDSPM_AES32_wcLock) {
3604 if (status & HDSPM_AES32_wcSync)
3605 return 2;
3606 else
3607 return 1;
3608 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02003609 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003610 break;
3611
3612 case MADI:
3613 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003614 if (status2 & HDSPM_wcLock) {
3615 if (status2 & HDSPM_wcSync)
3616 return 2;
3617 else
3618 return 1;
3619 }
3620 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003621 break;
3622
3623 case RayDAT:
3624 case AIO:
3625 status = hdspm_read(hdspm, HDSPM_statusRegister);
3626
3627 if (status & 0x2000000)
3628 return 2;
3629 else if (status & 0x1000000)
3630 return 1;
3631 return 0;
3632
3633 break;
3634
3635 case MADIface:
3636 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02003637 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003638
Takashi Iwai763f3562005-06-03 11:25:34 +02003639
Adrian Knoth0dca1792011-01-26 19:32:14 +01003640 return 3;
Takashi Iwai763f3562005-06-03 11:25:34 +02003641}
3642
3643
Adrian Knoth0dca1792011-01-26 19:32:14 +01003644static int hdspm_madi_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003645{
3646 int status = hdspm_read(hdspm, HDSPM_statusRegister);
3647 if (status & HDSPM_madiLock) {
3648 if (status & HDSPM_madiSync)
3649 return 2;
3650 else
3651 return 1;
3652 }
3653 return 0;
3654}
3655
Adrian Knoth0dca1792011-01-26 19:32:14 +01003656
3657static int hdspm_s1_sync_check(struct hdspm *hdspm, int idx)
3658{
3659 int status, lock, sync;
3660
3661 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3662
3663 lock = (status & (0x1<<idx)) ? 1 : 0;
3664 sync = (status & (0x100<<idx)) ? 1 : 0;
3665
3666 if (lock && sync)
3667 return 2;
3668 else if (lock)
3669 return 1;
3670 return 0;
3671}
3672
3673
3674static int hdspm_sync_in_sync_check(struct hdspm *hdspm)
3675{
3676 int status, lock = 0, sync = 0;
3677
3678 switch (hdspm->io_type) {
3679 case RayDAT:
3680 case AIO:
3681 status = hdspm_read(hdspm, HDSPM_RD_STATUS_3);
3682 lock = (status & 0x400) ? 1 : 0;
3683 sync = (status & 0x800) ? 1 : 0;
3684 break;
3685
3686 case MADI:
Adrian Knoth2e0452f2012-10-19 17:42:27 +02003687 status = hdspm_read(hdspm, HDSPM_statusRegister);
3688 lock = (status & HDSPM_syncInLock) ? 1 : 0;
3689 sync = (status & HDSPM_syncInSync) ? 1 : 0;
3690 break;
3691
Adrian Knoth0dca1792011-01-26 19:32:14 +01003692 case AES32:
3693 status = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth9a215f42012-10-19 17:42:28 +02003694 lock = (status & 0x100000) ? 1 : 0;
3695 sync = (status & 0x200000) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003696 break;
3697
3698 case MADIface:
3699 break;
3700 }
3701
3702 if (lock && sync)
3703 return 2;
3704 else if (lock)
3705 return 1;
3706
3707 return 0;
3708}
3709
3710static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx)
3711{
3712 int status2, lock, sync;
3713 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
3714
3715 lock = (status2 & (0x0080 >> idx)) ? 1 : 0;
3716 sync = (status2 & (0x8000 >> idx)) ? 1 : 0;
3717
3718 if (sync)
3719 return 2;
3720 else if (lock)
3721 return 1;
3722 return 0;
3723}
3724
Adrian Knoth34542212013-03-10 00:37:25 +01003725static int hdspm_tco_input_check(struct hdspm *hdspm, u32 mask)
3726{
3727 u32 status;
3728 status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
3729
3730 return (status & mask) ? 1 : 0;
3731}
3732
Adrian Knoth0dca1792011-01-26 19:32:14 +01003733
3734static int hdspm_tco_sync_check(struct hdspm *hdspm)
3735{
3736 int status;
3737
3738 if (hdspm->tco) {
3739 switch (hdspm->io_type) {
3740 case MADI:
3741 case AES32:
3742 status = hdspm_read(hdspm, HDSPM_statusRegister);
3743 if (status & HDSPM_tcoLock) {
3744 if (status & HDSPM_tcoSync)
3745 return 2;
3746 else
3747 return 1;
3748 }
3749 return 0;
3750
3751 break;
3752
3753 case RayDAT:
3754 case AIO:
3755 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3756
3757 if (status & 0x8000000)
3758 return 2; /* Sync */
3759 if (status & 0x4000000)
3760 return 1; /* Lock */
3761 return 0; /* No signal */
3762 break;
3763
3764 default:
3765 break;
3766 }
3767 }
3768
3769 return 3; /* N/A */
3770}
3771
3772
3773static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
3774 struct snd_ctl_elem_value *ucontrol)
3775{
3776 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3777 int val = -1;
3778
3779 switch (hdspm->io_type) {
3780 case RayDAT:
3781 switch (kcontrol->private_value) {
3782 case 0: /* WC */
3783 val = hdspm_wc_sync_check(hdspm); break;
3784 case 7: /* TCO */
3785 val = hdspm_tco_sync_check(hdspm); break;
3786 case 8: /* SYNC IN */
3787 val = hdspm_sync_in_sync_check(hdspm); break;
3788 default:
Adrian Knothd1a3c982012-11-07 18:00:09 +01003789 val = hdspm_s1_sync_check(hdspm,
3790 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003791 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02003792 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003793
3794 case AIO:
3795 switch (kcontrol->private_value) {
3796 case 0: /* WC */
3797 val = hdspm_wc_sync_check(hdspm); break;
3798 case 4: /* TCO */
3799 val = hdspm_tco_sync_check(hdspm); break;
3800 case 5: /* SYNC IN */
3801 val = hdspm_sync_in_sync_check(hdspm); break;
3802 default:
3803 val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
3804 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02003805 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003806
3807 case MADI:
3808 switch (kcontrol->private_value) {
3809 case 0: /* WC */
3810 val = hdspm_wc_sync_check(hdspm); break;
3811 case 1: /* MADI */
3812 val = hdspm_madi_sync_check(hdspm); break;
3813 case 2: /* TCO */
3814 val = hdspm_tco_sync_check(hdspm); break;
3815 case 3: /* SYNC_IN */
3816 val = hdspm_sync_in_sync_check(hdspm); break;
3817 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02003818 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003819
3820 case MADIface:
3821 val = hdspm_madi_sync_check(hdspm); /* MADI */
3822 break;
3823
3824 case AES32:
3825 switch (kcontrol->private_value) {
3826 case 0: /* WC */
3827 val = hdspm_wc_sync_check(hdspm); break;
3828 case 9: /* TCO */
3829 val = hdspm_tco_sync_check(hdspm); break;
3830 case 10 /* SYNC IN */:
3831 val = hdspm_sync_in_sync_check(hdspm); break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01003832 default: /* AES1 to AES8 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01003833 val = hdspm_aes_sync_check(hdspm,
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01003834 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003835 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02003836 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003837
3838 }
3839
Adrian Knoth34542212013-03-10 00:37:25 +01003840 if (hdspm->tco) {
3841 switch (kcontrol->private_value) {
3842 case 11:
3843 /* Check TCO for lock state of its current input */
3844 val = hdspm_tco_input_check(hdspm, HDSPM_TCO1_TCO_lock);
3845 break;
3846 case 12:
3847 /* Check TCO for valid time code on LTC input. */
3848 val = hdspm_tco_input_check(hdspm,
3849 HDSPM_TCO1_LTC_Input_valid);
3850 break;
3851 default:
3852 break;
3853 }
3854 }
3855
Adrian Knoth0dca1792011-01-26 19:32:14 +01003856 if (-1 == val)
3857 val = 3;
3858
3859 ucontrol->value.enumerated.item[0] = val;
3860 return 0;
3861}
3862
3863
3864
3865/**
3866 * TCO controls
3867 **/
3868static void hdspm_tco_write(struct hdspm *hdspm)
3869{
3870 unsigned int tc[4] = { 0, 0, 0, 0};
3871
3872 switch (hdspm->tco->input) {
3873 case 0:
3874 tc[2] |= HDSPM_TCO2_set_input_MSB;
3875 break;
3876 case 1:
3877 tc[2] |= HDSPM_TCO2_set_input_LSB;
3878 break;
3879 default:
3880 break;
3881 }
3882
3883 switch (hdspm->tco->framerate) {
3884 case 1:
3885 tc[1] |= HDSPM_TCO1_LTC_Format_LSB;
3886 break;
3887 case 2:
3888 tc[1] |= HDSPM_TCO1_LTC_Format_MSB;
3889 break;
3890 case 3:
3891 tc[1] |= HDSPM_TCO1_LTC_Format_MSB +
3892 HDSPM_TCO1_set_drop_frame_flag;
3893 break;
3894 case 4:
3895 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
3896 HDSPM_TCO1_LTC_Format_MSB;
3897 break;
3898 case 5:
3899 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
3900 HDSPM_TCO1_LTC_Format_MSB +
3901 HDSPM_TCO1_set_drop_frame_flag;
3902 break;
3903 default:
3904 break;
3905 }
3906
3907 switch (hdspm->tco->wordclock) {
3908 case 1:
3909 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_LSB;
3910 break;
3911 case 2:
3912 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_MSB;
3913 break;
3914 default:
3915 break;
3916 }
3917
3918 switch (hdspm->tco->samplerate) {
3919 case 1:
3920 tc[2] |= HDSPM_TCO2_set_freq;
3921 break;
3922 case 2:
3923 tc[2] |= HDSPM_TCO2_set_freq_from_app;
3924 break;
3925 default:
3926 break;
3927 }
3928
3929 switch (hdspm->tco->pull) {
3930 case 1:
3931 tc[2] |= HDSPM_TCO2_set_pull_up;
3932 break;
3933 case 2:
3934 tc[2] |= HDSPM_TCO2_set_pull_down;
3935 break;
3936 case 3:
3937 tc[2] |= HDSPM_TCO2_set_pull_up + HDSPM_TCO2_set_01_4;
3938 break;
3939 case 4:
3940 tc[2] |= HDSPM_TCO2_set_pull_down + HDSPM_TCO2_set_01_4;
3941 break;
3942 default:
3943 break;
3944 }
3945
3946 if (1 == hdspm->tco->term) {
3947 tc[2] |= HDSPM_TCO2_set_term_75R;
3948 }
3949
3950 hdspm_write(hdspm, HDSPM_WR_TCO, tc[0]);
3951 hdspm_write(hdspm, HDSPM_WR_TCO+4, tc[1]);
3952 hdspm_write(hdspm, HDSPM_WR_TCO+8, tc[2]);
3953 hdspm_write(hdspm, HDSPM_WR_TCO+12, tc[3]);
3954}
3955
3956
3957#define HDSPM_TCO_SAMPLE_RATE(xname, xindex) \
3958{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3959 .name = xname, \
3960 .index = xindex, \
3961 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
3962 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3963 .info = snd_hdspm_info_tco_sample_rate, \
3964 .get = snd_hdspm_get_tco_sample_rate, \
3965 .put = snd_hdspm_put_tco_sample_rate \
3966}
3967
3968static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol,
3969 struct snd_ctl_elem_info *uinfo)
3970{
3971 static char *texts[] = { "44.1 kHz", "48 kHz" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003972 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003973 return 0;
3974}
3975
3976static int snd_hdspm_get_tco_sample_rate(struct snd_kcontrol *kcontrol,
3977 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003978{
Takashi Iwai98274f02005-11-17 14:52:34 +01003979 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003980
Adrian Knoth0dca1792011-01-26 19:32:14 +01003981 ucontrol->value.enumerated.item[0] = hdspm->tco->samplerate;
3982
Takashi Iwai763f3562005-06-03 11:25:34 +02003983 return 0;
3984}
3985
Adrian Knoth0dca1792011-01-26 19:32:14 +01003986static int snd_hdspm_put_tco_sample_rate(struct snd_kcontrol *kcontrol,
3987 struct snd_ctl_elem_value *ucontrol)
Remy Bruno3cee5a62006-10-16 12:46:32 +02003988{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003989 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3990
3991 if (hdspm->tco->samplerate != ucontrol->value.enumerated.item[0]) {
3992 hdspm->tco->samplerate = ucontrol->value.enumerated.item[0];
3993
3994 hdspm_tco_write(hdspm);
3995
3996 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003997 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01003998
Remy Bruno3cee5a62006-10-16 12:46:32 +02003999 return 0;
4000}
4001
Adrian Knoth0dca1792011-01-26 19:32:14 +01004002
4003#define HDSPM_TCO_PULL(xname, xindex) \
4004{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4005 .name = xname, \
4006 .index = xindex, \
4007 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4008 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4009 .info = snd_hdspm_info_tco_pull, \
4010 .get = snd_hdspm_get_tco_pull, \
4011 .put = snd_hdspm_put_tco_pull \
4012}
4013
4014static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol,
4015 struct snd_ctl_elem_info *uinfo)
4016{
4017 static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004018 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004019 return 0;
4020}
4021
4022static int snd_hdspm_get_tco_pull(struct snd_kcontrol *kcontrol,
4023 struct snd_ctl_elem_value *ucontrol)
4024{
4025 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4026
4027 ucontrol->value.enumerated.item[0] = hdspm->tco->pull;
4028
4029 return 0;
4030}
4031
4032static int snd_hdspm_put_tco_pull(struct snd_kcontrol *kcontrol,
4033 struct snd_ctl_elem_value *ucontrol)
4034{
4035 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4036
4037 if (hdspm->tco->pull != ucontrol->value.enumerated.item[0]) {
4038 hdspm->tco->pull = ucontrol->value.enumerated.item[0];
4039
4040 hdspm_tco_write(hdspm);
4041
4042 return 1;
4043 }
4044
4045 return 0;
4046}
4047
4048#define HDSPM_TCO_WCK_CONVERSION(xname, xindex) \
4049{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4050 .name = xname, \
4051 .index = xindex, \
4052 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4053 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4054 .info = snd_hdspm_info_tco_wck_conversion, \
4055 .get = snd_hdspm_get_tco_wck_conversion, \
4056 .put = snd_hdspm_put_tco_wck_conversion \
4057}
4058
4059static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4060 struct snd_ctl_elem_info *uinfo)
4061{
4062 static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004063 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004064 return 0;
4065}
4066
4067static int snd_hdspm_get_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4068 struct snd_ctl_elem_value *ucontrol)
4069{
4070 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4071
4072 ucontrol->value.enumerated.item[0] = hdspm->tco->wordclock;
4073
4074 return 0;
4075}
4076
4077static int snd_hdspm_put_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4078 struct snd_ctl_elem_value *ucontrol)
4079{
4080 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4081
4082 if (hdspm->tco->wordclock != ucontrol->value.enumerated.item[0]) {
4083 hdspm->tco->wordclock = ucontrol->value.enumerated.item[0];
4084
4085 hdspm_tco_write(hdspm);
4086
4087 return 1;
4088 }
4089
4090 return 0;
4091}
4092
4093
4094#define HDSPM_TCO_FRAME_RATE(xname, xindex) \
4095{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4096 .name = xname, \
4097 .index = xindex, \
4098 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4099 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4100 .info = snd_hdspm_info_tco_frame_rate, \
4101 .get = snd_hdspm_get_tco_frame_rate, \
4102 .put = snd_hdspm_put_tco_frame_rate \
4103}
4104
4105static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol,
4106 struct snd_ctl_elem_info *uinfo)
4107{
4108 static char *texts[] = { "24 fps", "25 fps", "29.97fps",
4109 "29.97 dfps", "30 fps", "30 dfps" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004110 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004111 return 0;
4112}
4113
4114static int snd_hdspm_get_tco_frame_rate(struct snd_kcontrol *kcontrol,
Remy Bruno3cee5a62006-10-16 12:46:32 +02004115 struct snd_ctl_elem_value *ucontrol)
4116{
Remy Bruno3cee5a62006-10-16 12:46:32 +02004117 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4118
Adrian Knoth0dca1792011-01-26 19:32:14 +01004119 ucontrol->value.enumerated.item[0] = hdspm->tco->framerate;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004120
Remy Bruno3cee5a62006-10-16 12:46:32 +02004121 return 0;
4122}
Takashi Iwai763f3562005-06-03 11:25:34 +02004123
Adrian Knoth0dca1792011-01-26 19:32:14 +01004124static int snd_hdspm_put_tco_frame_rate(struct snd_kcontrol *kcontrol,
4125 struct snd_ctl_elem_value *ucontrol)
4126{
4127 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4128
4129 if (hdspm->tco->framerate != ucontrol->value.enumerated.item[0]) {
4130 hdspm->tco->framerate = ucontrol->value.enumerated.item[0];
4131
4132 hdspm_tco_write(hdspm);
4133
4134 return 1;
4135 }
4136
4137 return 0;
4138}
4139
4140
4141#define HDSPM_TCO_SYNC_SOURCE(xname, xindex) \
4142{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4143 .name = xname, \
4144 .index = xindex, \
4145 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4146 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4147 .info = snd_hdspm_info_tco_sync_source, \
4148 .get = snd_hdspm_get_tco_sync_source, \
4149 .put = snd_hdspm_put_tco_sync_source \
4150}
4151
4152static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol,
4153 struct snd_ctl_elem_info *uinfo)
4154{
4155 static char *texts[] = { "LTC", "Video", "WCK" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004156 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004157 return 0;
4158}
4159
4160static int snd_hdspm_get_tco_sync_source(struct snd_kcontrol *kcontrol,
4161 struct snd_ctl_elem_value *ucontrol)
4162{
4163 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4164
4165 ucontrol->value.enumerated.item[0] = hdspm->tco->input;
4166
4167 return 0;
4168}
4169
4170static int snd_hdspm_put_tco_sync_source(struct snd_kcontrol *kcontrol,
4171 struct snd_ctl_elem_value *ucontrol)
4172{
4173 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4174
4175 if (hdspm->tco->input != ucontrol->value.enumerated.item[0]) {
4176 hdspm->tco->input = ucontrol->value.enumerated.item[0];
4177
4178 hdspm_tco_write(hdspm);
4179
4180 return 1;
4181 }
4182
4183 return 0;
4184}
4185
4186
4187#define HDSPM_TCO_WORD_TERM(xname, xindex) \
4188{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4189 .name = xname, \
4190 .index = xindex, \
4191 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4192 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4193 .info = snd_hdspm_info_tco_word_term, \
4194 .get = snd_hdspm_get_tco_word_term, \
4195 .put = snd_hdspm_put_tco_word_term \
4196}
4197
4198static int snd_hdspm_info_tco_word_term(struct snd_kcontrol *kcontrol,
4199 struct snd_ctl_elem_info *uinfo)
4200{
4201 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
4202 uinfo->count = 1;
4203 uinfo->value.integer.min = 0;
4204 uinfo->value.integer.max = 1;
4205
4206 return 0;
4207}
4208
4209
4210static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol,
4211 struct snd_ctl_elem_value *ucontrol)
4212{
4213 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4214
4215 ucontrol->value.enumerated.item[0] = hdspm->tco->term;
4216
4217 return 0;
4218}
4219
4220
4221static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol,
4222 struct snd_ctl_elem_value *ucontrol)
4223{
4224 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4225
4226 if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) {
4227 hdspm->tco->term = ucontrol->value.enumerated.item[0];
4228
4229 hdspm_tco_write(hdspm);
4230
4231 return 1;
4232 }
4233
4234 return 0;
4235}
4236
4237
4238
Takashi Iwai763f3562005-06-03 11:25:34 +02004239
Remy Bruno3cee5a62006-10-16 12:46:32 +02004240static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004241 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004242 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Takashi Iwai763f3562005-06-03 11:25:34 +02004243 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4244 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4245 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4246 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Adrian Knothb8812c52012-10-19 17:42:26 +02004247 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004248 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4249 HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
Adrian Knoth930f4ff2012-10-19 17:42:29 +02004250 HDSPM_SYNC_CHECK("TCO SyncCheck", 2),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004251 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
Adrian Knothc9e16682012-12-03 14:55:50 +01004252 HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
4253 HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
Adrian Knoth696be0f2013-03-10 00:37:23 +01004254 HDSPM_TOGGLE_SETTING("Disable 96K frames", HDSPM_SMUX),
Adrian Knothc9e16682012-12-03 14:55:50 +01004255 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
4256 HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
Adrian Knoth700d1ef2011-07-29 03:11:02 +02004257 HDSPM_INPUT_SELECT("Input Select", 0),
4258 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004259};
4260
4261
4262static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
4263 HDSPM_MIXER("Mixer", 0),
4264 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4265 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4266 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4267 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4268 HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
Adrian Knothc9e16682012-12-03 14:55:50 +01004269 HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
4270 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
4271 HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
Adrian Knoth700d1ef2011-07-29 03:11:02 +02004272 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004273};
4274
Adrian Knoth0dca1792011-01-26 19:32:14 +01004275static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004276 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004277 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004278 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4279 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4280 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4281 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004282 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004283 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4284 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4285 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4286 HDSPM_SYNC_CHECK("ADAT SyncCheck", 3),
4287 HDSPM_SYNC_CHECK("TCO SyncCheck", 4),
4288 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 5),
4289 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4290 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4291 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4292 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT Frequency", 3),
4293 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 4),
4294 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5)
4295
4296 /*
4297 HDSPM_INPUT_SELECT("Input Select", 0),
4298 HDSPM_SPDIF_OPTICAL("SPDIF Out Optical", 0),
4299 HDSPM_PROFESSIONAL("SPDIF Out Professional", 0);
4300 HDSPM_SPDIF_IN("SPDIF In", 0);
4301 HDSPM_BREAKOUT_CABLE("Breakout Cable", 0);
4302 HDSPM_INPUT_LEVEL("Input Level", 0);
4303 HDSPM_OUTPUT_LEVEL("Output Level", 0);
4304 HDSPM_PHONES("Phones", 0);
4305 */
4306};
4307
4308static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = {
4309 HDSPM_MIXER("Mixer", 0),
4310 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4311 HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0),
4312 HDSPM_PREF_SYNC_REF("Pref Sync Ref", 0),
4313 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4314 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4315 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4316 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4317 HDSPM_SYNC_CHECK("ADAT1 SyncCheck", 3),
4318 HDSPM_SYNC_CHECK("ADAT2 SyncCheck", 4),
4319 HDSPM_SYNC_CHECK("ADAT3 SyncCheck", 5),
4320 HDSPM_SYNC_CHECK("ADAT4 SyncCheck", 6),
4321 HDSPM_SYNC_CHECK("TCO SyncCheck", 7),
4322 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 8),
4323 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4324 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4325 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4326 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT1 Frequency", 3),
4327 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT2 Frequency", 4),
4328 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT3 Frequency", 5),
4329 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT4 Frequency", 6),
4330 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 7),
4331 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8)
4332};
4333
4334static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
4335 HDSPM_MIXER("Mixer", 0),
4336 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4337 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4338 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4339 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4340 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4341 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4342 HDSPM_SYNC_CHECK("WC Sync Check", 0),
4343 HDSPM_SYNC_CHECK("AES1 Sync Check", 1),
4344 HDSPM_SYNC_CHECK("AES2 Sync Check", 2),
4345 HDSPM_SYNC_CHECK("AES3 Sync Check", 3),
4346 HDSPM_SYNC_CHECK("AES4 Sync Check", 4),
4347 HDSPM_SYNC_CHECK("AES5 Sync Check", 5),
4348 HDSPM_SYNC_CHECK("AES6 Sync Check", 6),
4349 HDSPM_SYNC_CHECK("AES7 Sync Check", 7),
4350 HDSPM_SYNC_CHECK("AES8 Sync Check", 8),
4351 HDSPM_SYNC_CHECK("TCO Sync Check", 9),
4352 HDSPM_SYNC_CHECK("SYNC IN Sync Check", 10),
4353 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4354 HDSPM_AUTOSYNC_SAMPLE_RATE("AES1 Frequency", 1),
4355 HDSPM_AUTOSYNC_SAMPLE_RATE("AES2 Frequency", 2),
4356 HDSPM_AUTOSYNC_SAMPLE_RATE("AES3 Frequency", 3),
4357 HDSPM_AUTOSYNC_SAMPLE_RATE("AES4 Frequency", 4),
4358 HDSPM_AUTOSYNC_SAMPLE_RATE("AES5 Frequency", 5),
4359 HDSPM_AUTOSYNC_SAMPLE_RATE("AES6 Frequency", 6),
4360 HDSPM_AUTOSYNC_SAMPLE_RATE("AES7 Frequency", 7),
4361 HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8),
4362 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9),
4363 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10),
Adrian Knothc9e16682012-12-03 14:55:50 +01004364 HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
4365 HDSPM_TOGGLE_SETTING("Emphasis", HDSPM_Emphasis),
4366 HDSPM_TOGGLE_SETTING("Non Audio", HDSPM_Dolby),
4367 HDSPM_TOGGLE_SETTING("Professional", HDSPM_Professional),
4368 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004369 HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
4370 HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
4371};
4372
Adrian Knoth0dca1792011-01-26 19:32:14 +01004373
4374
4375/* Control elements for the optional TCO module */
4376static struct snd_kcontrol_new snd_hdspm_controls_tco[] = {
4377 HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0),
4378 HDSPM_TCO_PULL("TCO Pull", 0),
4379 HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0),
4380 HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0),
4381 HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0),
Adrian Knotha8176502013-03-10 00:37:27 +01004382 HDSPM_TCO_WORD_TERM("TCO Word Term", 0),
4383 HDSPM_TCO_LOCK_CHECK("TCO Input Check", 11),
4384 HDSPM_TCO_LOCK_CHECK("TCO LTC Valid", 12),
4385 HDSPM_TCO_LTC_FRAMES("TCO Detected Frame Rate", 0),
4386 HDSPM_TCO_VIDEO_INPUT_FORMAT("Video Input Format", 0)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004387};
4388
4389
Takashi Iwai98274f02005-11-17 14:52:34 +01004390static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
Takashi Iwai763f3562005-06-03 11:25:34 +02004391
4392
Takashi Iwai98274f02005-11-17 14:52:34 +01004393static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004394{
4395 int i;
4396
Adrian Knoth0dca1792011-01-26 19:32:14 +01004397 for (i = hdspm->ds_out_channels; i < hdspm->ss_out_channels; ++i) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004398 if (hdspm->system_sample_rate > 48000) {
4399 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004400 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
4401 SNDRV_CTL_ELEM_ACCESS_READ |
4402 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004403 } else {
4404 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004405 SNDRV_CTL_ELEM_ACCESS_READWRITE |
4406 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004407 }
4408 snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
Adrian Knoth0dca1792011-01-26 19:32:14 +01004409 SNDRV_CTL_EVENT_MASK_INFO,
4410 &hdspm->playback_mixer_ctls[i]->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02004411 }
4412
4413 return 0;
4414}
4415
4416
Adrian Knoth0dca1792011-01-26 19:32:14 +01004417static int snd_hdspm_create_controls(struct snd_card *card,
4418 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004419{
4420 unsigned int idx, limit;
4421 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01004422 struct snd_kcontrol *kctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004423 struct snd_kcontrol_new *list = NULL;
Takashi Iwai763f3562005-06-03 11:25:34 +02004424
Adrian Knoth0dca1792011-01-26 19:32:14 +01004425 switch (hdspm->io_type) {
4426 case MADI:
4427 list = snd_hdspm_controls_madi;
4428 limit = ARRAY_SIZE(snd_hdspm_controls_madi);
4429 break;
4430 case MADIface:
4431 list = snd_hdspm_controls_madiface;
4432 limit = ARRAY_SIZE(snd_hdspm_controls_madiface);
4433 break;
4434 case AIO:
4435 list = snd_hdspm_controls_aio;
4436 limit = ARRAY_SIZE(snd_hdspm_controls_aio);
4437 break;
4438 case RayDAT:
4439 list = snd_hdspm_controls_raydat;
4440 limit = ARRAY_SIZE(snd_hdspm_controls_raydat);
4441 break;
4442 case AES32:
4443 list = snd_hdspm_controls_aes32;
4444 limit = ARRAY_SIZE(snd_hdspm_controls_aes32);
4445 break;
4446 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004447
Adrian Knoth0dca1792011-01-26 19:32:14 +01004448 if (NULL != list) {
4449 for (idx = 0; idx < limit; idx++) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004450 err = snd_ctl_add(card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004451 snd_ctl_new1(&list[idx], hdspm));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004452 if (err < 0)
4453 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004454 }
4455 }
4456
Takashi Iwai763f3562005-06-03 11:25:34 +02004457
Adrian Knoth0dca1792011-01-26 19:32:14 +01004458 /* create simple 1:1 playback mixer controls */
Takashi Iwai763f3562005-06-03 11:25:34 +02004459 snd_hdspm_playback_mixer.name = "Chn";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004460 if (hdspm->system_sample_rate >= 128000) {
4461 limit = hdspm->qs_out_channels;
4462 } else if (hdspm->system_sample_rate >= 64000) {
4463 limit = hdspm->ds_out_channels;
4464 } else {
4465 limit = hdspm->ss_out_channels;
4466 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004467 for (idx = 0; idx < limit; ++idx) {
4468 snd_hdspm_playback_mixer.index = idx + 1;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004469 kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm);
4470 err = snd_ctl_add(card, kctl);
4471 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004472 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004473 hdspm->playback_mixer_ctls[idx] = kctl;
4474 }
4475
Adrian Knoth0dca1792011-01-26 19:32:14 +01004476
4477 if (hdspm->tco) {
4478 /* add tco control elements */
4479 list = snd_hdspm_controls_tco;
4480 limit = ARRAY_SIZE(snd_hdspm_controls_tco);
4481 for (idx = 0; idx < limit; idx++) {
4482 err = snd_ctl_add(card,
4483 snd_ctl_new1(&list[idx], hdspm));
4484 if (err < 0)
4485 return err;
4486 }
4487 }
4488
Takashi Iwai763f3562005-06-03 11:25:34 +02004489 return 0;
4490}
4491
4492/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01004493 /proc interface
Takashi Iwai763f3562005-06-03 11:25:34 +02004494 ------------------------------------------------------------*/
4495
4496static void
Remy Bruno3cee5a62006-10-16 12:46:32 +02004497snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
4498 struct snd_info_buffer *buffer)
Takashi Iwai763f3562005-06-03 11:25:34 +02004499{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004500 struct hdspm *hdspm = entry->private_data;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004501 unsigned int status, status2, control, freq;
4502
Takashi Iwai763f3562005-06-03 11:25:34 +02004503 char *pref_sync_ref;
4504 char *autosync_ref;
4505 char *system_clock_mode;
Takashi Iwai763f3562005-06-03 11:25:34 +02004506 char *insel;
Takashi Iwai763f3562005-06-03 11:25:34 +02004507 int x, x2;
4508
Adrian Knoth0dca1792011-01-26 19:32:14 +01004509 /* TCO stuff */
4510 int a, ltc, frames, seconds, minutes, hours;
4511 unsigned int period;
4512 u64 freq_const = 0;
4513 u32 rate;
4514
Takashi Iwai763f3562005-06-03 11:25:34 +02004515 status = hdspm_read(hdspm, HDSPM_statusRegister);
4516 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004517 control = hdspm->control_register;
4518 freq = hdspm_read(hdspm, HDSPM_timecodeRegister);
Takashi Iwai763f3562005-06-03 11:25:34 +02004519
4520 snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004521 hdspm->card_name, hdspm->card->number + 1,
4522 hdspm->firmware_rev,
4523 (status2 & HDSPM_version0) |
4524 (status2 & HDSPM_version1) | (status2 &
4525 HDSPM_version2));
4526
4527 snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n",
4528 (hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF,
Adrian Knoth7d53a632012-01-04 14:31:16 +01004529 hdspm->serial);
Takashi Iwai763f3562005-06-03 11:25:34 +02004530
4531 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004532 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
Takashi Iwai763f3562005-06-03 11:25:34 +02004533
4534 snd_iprintf(buffer, "--- System ---\n");
4535
4536 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004537 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4538 status & HDSPM_audioIRQPending,
4539 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4540 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4541 hdspm->irq_count);
Takashi Iwai763f3562005-06-03 11:25:34 +02004542 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004543 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4544 "estimated= %ld (bytes)\n",
4545 ((status & HDSPM_BufferID) ? 1 : 0),
4546 (status & HDSPM_BufferPositionMask),
4547 (status & HDSPM_BufferPositionMask) %
4548 (2 * (int)hdspm->period_bytes),
4549 ((status & HDSPM_BufferPositionMask) - 64) %
4550 (2 * (int)hdspm->period_bytes),
4551 (long) hdspm_hw_pointer(hdspm) * 4);
Takashi Iwai763f3562005-06-03 11:25:34 +02004552
4553 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004554 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4555 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4556 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4557 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4558 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
Takashi Iwai763f3562005-06-03 11:25:34 +02004559 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004560 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4561 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4562 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4563 snd_iprintf(buffer,
4564 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4565 "status2=0x%x\n",
4566 hdspm->control_register, hdspm->control2_register,
4567 status, status2);
4568 if (status & HDSPM_tco_detect) {
4569 snd_iprintf(buffer, "TCO module detected.\n");
4570 a = hdspm_read(hdspm, HDSPM_RD_TCO+4);
4571 if (a & HDSPM_TCO1_LTC_Input_valid) {
4572 snd_iprintf(buffer, " LTC valid, ");
4573 switch (a & (HDSPM_TCO1_LTC_Format_LSB |
4574 HDSPM_TCO1_LTC_Format_MSB)) {
4575 case 0:
4576 snd_iprintf(buffer, "24 fps, ");
4577 break;
4578 case HDSPM_TCO1_LTC_Format_LSB:
4579 snd_iprintf(buffer, "25 fps, ");
4580 break;
4581 case HDSPM_TCO1_LTC_Format_MSB:
4582 snd_iprintf(buffer, "29.97 fps, ");
4583 break;
4584 default:
4585 snd_iprintf(buffer, "30 fps, ");
4586 break;
4587 }
4588 if (a & HDSPM_TCO1_set_drop_frame_flag) {
4589 snd_iprintf(buffer, "drop frame\n");
4590 } else {
4591 snd_iprintf(buffer, "full frame\n");
4592 }
4593 } else {
4594 snd_iprintf(buffer, " no LTC\n");
4595 }
4596 if (a & HDSPM_TCO1_Video_Input_Format_NTSC) {
4597 snd_iprintf(buffer, " Video: NTSC\n");
4598 } else if (a & HDSPM_TCO1_Video_Input_Format_PAL) {
4599 snd_iprintf(buffer, " Video: PAL\n");
4600 } else {
4601 snd_iprintf(buffer, " No video\n");
4602 }
4603 if (a & HDSPM_TCO1_TCO_lock) {
4604 snd_iprintf(buffer, " Sync: lock\n");
4605 } else {
4606 snd_iprintf(buffer, " Sync: no lock\n");
4607 }
4608
4609 switch (hdspm->io_type) {
4610 case MADI:
4611 case AES32:
4612 freq_const = 110069313433624ULL;
4613 break;
4614 case RayDAT:
4615 case AIO:
4616 freq_const = 104857600000000ULL;
4617 break;
4618 case MADIface:
4619 break; /* no TCO possible */
4620 }
4621
4622 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
4623 snd_iprintf(buffer, " period: %u\n", period);
4624
4625
4626 /* rate = freq_const/period; */
4627 rate = div_u64(freq_const, period);
4628
4629 if (control & HDSPM_QuadSpeed) {
4630 rate *= 4;
4631 } else if (control & HDSPM_DoubleSpeed) {
4632 rate *= 2;
4633 }
4634
4635 snd_iprintf(buffer, " Frequency: %u Hz\n",
4636 (unsigned int) rate);
4637
4638 ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
4639 frames = ltc & 0xF;
4640 ltc >>= 4;
4641 frames += (ltc & 0x3) * 10;
4642 ltc >>= 4;
4643 seconds = ltc & 0xF;
4644 ltc >>= 4;
4645 seconds += (ltc & 0x7) * 10;
4646 ltc >>= 4;
4647 minutes = ltc & 0xF;
4648 ltc >>= 4;
4649 minutes += (ltc & 0x7) * 10;
4650 ltc >>= 4;
4651 hours = ltc & 0xF;
4652 ltc >>= 4;
4653 hours += (ltc & 0x3) * 10;
4654 snd_iprintf(buffer,
4655 " LTC In: %02d:%02d:%02d:%02d\n",
4656 hours, minutes, seconds, frames);
4657
4658 } else {
4659 snd_iprintf(buffer, "No TCO module detected.\n");
4660 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004661
4662 snd_iprintf(buffer, "--- Settings ---\n");
4663
Adrian Knoth7cb155f2011-08-15 00:22:53 +02004664 x = hdspm_get_latency(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02004665
4666 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004667 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4668 x, (unsigned long) hdspm->period_bytes);
Takashi Iwai763f3562005-06-03 11:25:34 +02004669
Adrian Knoth0dca1792011-01-26 19:32:14 +01004670 snd_iprintf(buffer, "Line out: %s\n",
4671 (hdspm->control_register & HDSPM_LineOut) ? "on " : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004672
4673 switch (hdspm->control_register & HDSPM_InputMask) {
4674 case HDSPM_InputOptical:
4675 insel = "Optical";
4676 break;
4677 case HDSPM_InputCoaxial:
4678 insel = "Coaxial";
4679 break;
4680 default:
Masanari Iidaec8f53f2012-11-02 00:28:50 +09004681 insel = "Unknown";
Takashi Iwai763f3562005-06-03 11:25:34 +02004682 }
4683
Takashi Iwai763f3562005-06-03 11:25:34 +02004684 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004685 "ClearTrackMarker = %s, Transmit in %s Channel Mode, "
4686 "Auto Input %s\n",
4687 (hdspm->control_register & HDSPM_clr_tms) ? "on" : "off",
4688 (hdspm->control_register & HDSPM_TX_64ch) ? "64" : "56",
4689 (hdspm->control_register & HDSPM_AutoInp) ? "on" : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004690
Adrian Knoth0dca1792011-01-26 19:32:14 +01004691
Remy Bruno3cee5a62006-10-16 12:46:32 +02004692 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
Adrian Knoth0dca1792011-01-26 19:32:14 +01004693 system_clock_mode = "AutoSync";
Remy Bruno3cee5a62006-10-16 12:46:32 +02004694 else
Takashi Iwai763f3562005-06-03 11:25:34 +02004695 system_clock_mode = "Master";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004696 snd_iprintf(buffer, "AutoSync Reference: %s\n", system_clock_mode);
Takashi Iwai763f3562005-06-03 11:25:34 +02004697
4698 switch (hdspm_pref_sync_ref(hdspm)) {
4699 case HDSPM_SYNC_FROM_WORD:
4700 pref_sync_ref = "Word Clock";
4701 break;
4702 case HDSPM_SYNC_FROM_MADI:
4703 pref_sync_ref = "MADI Sync";
4704 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004705 case HDSPM_SYNC_FROM_TCO:
4706 pref_sync_ref = "TCO";
4707 break;
4708 case HDSPM_SYNC_FROM_SYNC_IN:
4709 pref_sync_ref = "Sync In";
4710 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004711 default:
4712 pref_sync_ref = "XXXX Clock";
4713 break;
4714 }
4715 snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004716 pref_sync_ref);
Takashi Iwai763f3562005-06-03 11:25:34 +02004717
4718 snd_iprintf(buffer, "System Clock Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004719 hdspm->system_sample_rate);
Takashi Iwai763f3562005-06-03 11:25:34 +02004720
4721
4722 snd_iprintf(buffer, "--- Status:\n");
4723
4724 x = status & HDSPM_madiSync;
4725 x2 = status2 & HDSPM_wcSync;
4726
4727 snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004728 (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
4729 "NoLock",
4730 (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
4731 "NoLock");
Takashi Iwai763f3562005-06-03 11:25:34 +02004732
4733 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004734 case HDSPM_AUTOSYNC_FROM_SYNC_IN:
4735 autosync_ref = "Sync In";
4736 break;
4737 case HDSPM_AUTOSYNC_FROM_TCO:
4738 autosync_ref = "TCO";
4739 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004740 case HDSPM_AUTOSYNC_FROM_WORD:
4741 autosync_ref = "Word Clock";
4742 break;
4743 case HDSPM_AUTOSYNC_FROM_MADI:
4744 autosync_ref = "MADI Sync";
4745 break;
4746 case HDSPM_AUTOSYNC_FROM_NONE:
4747 autosync_ref = "Input not valid";
4748 break;
4749 default:
4750 autosync_ref = "---";
4751 break;
4752 }
4753 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004754 "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
4755 autosync_ref, hdspm_external_sample_rate(hdspm),
4756 (status & HDSPM_madiFreqMask) >> 22,
4757 (status2 & HDSPM_wcFreqMask) >> 5);
Takashi Iwai763f3562005-06-03 11:25:34 +02004758
4759 snd_iprintf(buffer, "Input: %s, Mode=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004760 (status & HDSPM_AB_int) ? "Coax" : "Optical",
4761 (status & HDSPM_RX_64ch) ? "64 channels" :
4762 "56 channels");
Takashi Iwai763f3562005-06-03 11:25:34 +02004763
4764 snd_iprintf(buffer, "\n");
4765}
4766
Remy Bruno3cee5a62006-10-16 12:46:32 +02004767static void
4768snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
4769 struct snd_info_buffer *buffer)
4770{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004771 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004772 unsigned int status;
4773 unsigned int status2;
4774 unsigned int timecode;
Andre Schramm56bde0f2013-01-09 14:40:18 +01004775 unsigned int wcLock, wcSync;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004776 int pref_syncref;
4777 char *autosync_ref;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004778 int x;
4779
4780 status = hdspm_read(hdspm, HDSPM_statusRegister);
4781 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
4782 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
4783
4784 snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
4785 hdspm->card_name, hdspm->card->number + 1,
4786 hdspm->firmware_rev);
4787
4788 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
4789 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
4790
4791 snd_iprintf(buffer, "--- System ---\n");
4792
4793 snd_iprintf(buffer,
4794 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4795 status & HDSPM_audioIRQPending,
4796 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4797 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4798 hdspm->irq_count);
4799 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004800 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4801 "estimated= %ld (bytes)\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004802 ((status & HDSPM_BufferID) ? 1 : 0),
4803 (status & HDSPM_BufferPositionMask),
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004804 (status & HDSPM_BufferPositionMask) %
4805 (2 * (int)hdspm->period_bytes),
4806 ((status & HDSPM_BufferPositionMask) - 64) %
4807 (2 * (int)hdspm->period_bytes),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004808 (long) hdspm_hw_pointer(hdspm) * 4);
4809
4810 snd_iprintf(buffer,
4811 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4812 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4813 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4814 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4815 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
4816 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004817 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4818 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4819 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4820 snd_iprintf(buffer,
4821 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4822 "status2=0x%x\n",
4823 hdspm->control_register, hdspm->control2_register,
4824 status, status2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02004825
4826 snd_iprintf(buffer, "--- Settings ---\n");
4827
Adrian Knoth7cb155f2011-08-15 00:22:53 +02004828 x = hdspm_get_latency(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02004829
4830 snd_iprintf(buffer,
4831 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4832 x, (unsigned long) hdspm->period_bytes);
4833
Adrian Knoth0dca1792011-01-26 19:32:14 +01004834 snd_iprintf(buffer, "Line out: %s\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004835 (hdspm->
Adrian Knoth0dca1792011-01-26 19:32:14 +01004836 control_register & HDSPM_LineOut) ? "on " : "off");
Remy Bruno3cee5a62006-10-16 12:46:32 +02004837
4838 snd_iprintf(buffer,
4839 "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
4840 (hdspm->
4841 control_register & HDSPM_clr_tms) ? "on" : "off",
4842 (hdspm->
4843 control_register & HDSPM_Emphasis) ? "on" : "off",
4844 (hdspm->
4845 control_register & HDSPM_Dolby) ? "on" : "off");
4846
Remy Bruno3cee5a62006-10-16 12:46:32 +02004847
4848 pref_syncref = hdspm_pref_sync_ref(hdspm);
4849 if (pref_syncref == 0)
4850 snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
4851 else
4852 snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
4853 pref_syncref);
4854
4855 snd_iprintf(buffer, "System Clock Frequency: %d\n",
4856 hdspm->system_sample_rate);
4857
4858 snd_iprintf(buffer, "Double speed: %s\n",
4859 hdspm->control_register & HDSPM_DS_DoubleWire?
4860 "Double wire" : "Single wire");
4861 snd_iprintf(buffer, "Quad speed: %s\n",
4862 hdspm->control_register & HDSPM_QS_DoubleWire?
4863 "Double wire" :
4864 hdspm->control_register & HDSPM_QS_QuadWire?
4865 "Quad wire" : "Single wire");
4866
4867 snd_iprintf(buffer, "--- Status:\n");
4868
Andre Schramm56bde0f2013-01-09 14:40:18 +01004869 wcLock = status & HDSPM_AES32_wcLock;
4870 wcSync = wcLock && (status & HDSPM_AES32_wcSync);
4871
Remy Bruno3cee5a62006-10-16 12:46:32 +02004872 snd_iprintf(buffer, "Word: %s Frequency: %d\n",
Andre Schramm56bde0f2013-01-09 14:40:18 +01004873 (wcLock) ? (wcSync ? "Sync " : "Lock ") : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004874 HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004875
4876 for (x = 0; x < 8; x++) {
4877 snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004878 x+1,
4879 (status2 & (HDSPM_LockAES >> x)) ?
Adrian Knoth0dca1792011-01-26 19:32:14 +01004880 "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004881 HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004882 }
4883
4884 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004885 case HDSPM_AES32_AUTOSYNC_FROM_NONE:
4886 autosync_ref = "None"; break;
4887 case HDSPM_AES32_AUTOSYNC_FROM_WORD:
4888 autosync_ref = "Word Clock"; break;
4889 case HDSPM_AES32_AUTOSYNC_FROM_AES1:
4890 autosync_ref = "AES1"; break;
4891 case HDSPM_AES32_AUTOSYNC_FROM_AES2:
4892 autosync_ref = "AES2"; break;
4893 case HDSPM_AES32_AUTOSYNC_FROM_AES3:
4894 autosync_ref = "AES3"; break;
4895 case HDSPM_AES32_AUTOSYNC_FROM_AES4:
4896 autosync_ref = "AES4"; break;
4897 case HDSPM_AES32_AUTOSYNC_FROM_AES5:
4898 autosync_ref = "AES5"; break;
4899 case HDSPM_AES32_AUTOSYNC_FROM_AES6:
4900 autosync_ref = "AES6"; break;
4901 case HDSPM_AES32_AUTOSYNC_FROM_AES7:
4902 autosync_ref = "AES7"; break;
4903 case HDSPM_AES32_AUTOSYNC_FROM_AES8:
4904 autosync_ref = "AES8"; break;
4905 default:
4906 autosync_ref = "---"; break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004907 }
4908 snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
4909
4910 snd_iprintf(buffer, "\n");
4911}
4912
Adrian Knoth0dca1792011-01-26 19:32:14 +01004913static void
4914snd_hdspm_proc_read_raydat(struct snd_info_entry *entry,
4915 struct snd_info_buffer *buffer)
4916{
4917 struct hdspm *hdspm = entry->private_data;
4918 unsigned int status1, status2, status3, control, i;
4919 unsigned int lock, sync;
4920
4921 status1 = hdspm_read(hdspm, HDSPM_RD_STATUS_1); /* s1 */
4922 status2 = hdspm_read(hdspm, HDSPM_RD_STATUS_2); /* freq */
4923 status3 = hdspm_read(hdspm, HDSPM_RD_STATUS_3); /* s2 */
4924
4925 control = hdspm->control_register;
4926
4927 snd_iprintf(buffer, "STATUS1: 0x%08x\n", status1);
4928 snd_iprintf(buffer, "STATUS2: 0x%08x\n", status2);
4929 snd_iprintf(buffer, "STATUS3: 0x%08x\n", status3);
4930
4931
4932 snd_iprintf(buffer, "\n*** CLOCK MODE\n\n");
4933
4934 snd_iprintf(buffer, "Clock mode : %s\n",
4935 (hdspm_system_clock_mode(hdspm) == 0) ? "master" : "slave");
4936 snd_iprintf(buffer, "System frequency: %d Hz\n",
4937 hdspm_get_system_sample_rate(hdspm));
4938
4939 snd_iprintf(buffer, "\n*** INPUT STATUS\n\n");
4940
4941 lock = 0x1;
4942 sync = 0x100;
4943
4944 for (i = 0; i < 8; i++) {
4945 snd_iprintf(buffer, "s1_input %d: Lock %d, Sync %d, Freq %s\n",
4946 i,
4947 (status1 & lock) ? 1 : 0,
4948 (status1 & sync) ? 1 : 0,
4949 texts_freq[(status2 >> (i * 4)) & 0xF]);
4950
4951 lock = lock<<1;
4952 sync = sync<<1;
4953 }
4954
4955 snd_iprintf(buffer, "WC input: Lock %d, Sync %d, Freq %s\n",
4956 (status1 & 0x1000000) ? 1 : 0,
4957 (status1 & 0x2000000) ? 1 : 0,
4958 texts_freq[(status1 >> 16) & 0xF]);
4959
4960 snd_iprintf(buffer, "TCO input: Lock %d, Sync %d, Freq %s\n",
4961 (status1 & 0x4000000) ? 1 : 0,
4962 (status1 & 0x8000000) ? 1 : 0,
4963 texts_freq[(status1 >> 20) & 0xF]);
4964
4965 snd_iprintf(buffer, "SYNC IN: Lock %d, Sync %d, Freq %s\n",
4966 (status3 & 0x400) ? 1 : 0,
4967 (status3 & 0x800) ? 1 : 0,
4968 texts_freq[(status2 >> 12) & 0xF]);
4969
4970}
4971
Remy Bruno3cee5a62006-10-16 12:46:32 +02004972#ifdef CONFIG_SND_DEBUG
4973static void
Adrian Knoth0dca1792011-01-26 19:32:14 +01004974snd_hdspm_proc_read_debug(struct snd_info_entry *entry,
Remy Bruno3cee5a62006-10-16 12:46:32 +02004975 struct snd_info_buffer *buffer)
4976{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004977 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004978
4979 int j,i;
4980
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004981 for (i = 0; i < 256 /* 1024*64 */; i += j) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004982 snd_iprintf(buffer, "0x%08X: ", i);
4983 for (j = 0; j < 16; j += 4)
4984 snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
4985 snd_iprintf(buffer, "\n");
4986 }
4987}
4988#endif
4989
4990
Adrian Knoth0dca1792011-01-26 19:32:14 +01004991static void snd_hdspm_proc_ports_in(struct snd_info_entry *entry,
4992 struct snd_info_buffer *buffer)
4993{
4994 struct hdspm *hdspm = entry->private_data;
4995 int i;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004996
Adrian Knoth0dca1792011-01-26 19:32:14 +01004997 snd_iprintf(buffer, "# generated by hdspm\n");
4998
4999 for (i = 0; i < hdspm->max_channels_in; i++) {
5000 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_in[i]);
5001 }
5002}
5003
5004static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry,
5005 struct snd_info_buffer *buffer)
5006{
5007 struct hdspm *hdspm = entry->private_data;
5008 int i;
5009
5010 snd_iprintf(buffer, "# generated by hdspm\n");
5011
5012 for (i = 0; i < hdspm->max_channels_out; i++) {
5013 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_out[i]);
5014 }
5015}
5016
5017
Bill Pembertone23e7a12012-12-06 12:35:10 -05005018static void snd_hdspm_proc_init(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005019{
Takashi Iwai98274f02005-11-17 14:52:34 +01005020 struct snd_info_entry *entry;
Takashi Iwai763f3562005-06-03 11:25:34 +02005021
Adrian Knoth0dca1792011-01-26 19:32:14 +01005022 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) {
5023 switch (hdspm->io_type) {
5024 case AES32:
5025 snd_info_set_text_ops(entry, hdspm,
5026 snd_hdspm_proc_read_aes32);
5027 break;
5028 case MADI:
5029 snd_info_set_text_ops(entry, hdspm,
5030 snd_hdspm_proc_read_madi);
5031 break;
5032 case MADIface:
5033 /* snd_info_set_text_ops(entry, hdspm,
5034 snd_hdspm_proc_read_madiface); */
5035 break;
5036 case RayDAT:
5037 snd_info_set_text_ops(entry, hdspm,
5038 snd_hdspm_proc_read_raydat);
5039 break;
5040 case AIO:
5041 break;
5042 }
5043 }
5044
5045 if (!snd_card_proc_new(hdspm->card, "ports.in", &entry)) {
5046 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_in);
5047 }
5048
5049 if (!snd_card_proc_new(hdspm->card, "ports.out", &entry)) {
5050 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_out);
5051 }
5052
Remy Bruno3cee5a62006-10-16 12:46:32 +02005053#ifdef CONFIG_SND_DEBUG
5054 /* debug file to read all hdspm registers */
5055 if (!snd_card_proc_new(hdspm->card, "debug", &entry))
5056 snd_info_set_text_ops(entry, hdspm,
5057 snd_hdspm_proc_read_debug);
5058#endif
Takashi Iwai763f3562005-06-03 11:25:34 +02005059}
5060
5061/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005062 hdspm intitialize
Takashi Iwai763f3562005-06-03 11:25:34 +02005063 ------------------------------------------------------------*/
5064
Takashi Iwai98274f02005-11-17 14:52:34 +01005065static int snd_hdspm_set_defaults(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005066{
Takashi Iwai763f3562005-06-03 11:25:34 +02005067 /* ASSUMPTION: hdspm->lock is either held, or there is no need to
Joe Perches561de312007-12-18 13:13:47 +01005068 hold it (e.g. during module initialization).
Adrian Knoth0dca1792011-01-26 19:32:14 +01005069 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005070
5071 /* set defaults: */
5072
Adrian Knoth0dca1792011-01-26 19:32:14 +01005073 hdspm->settings_register = 0;
5074
5075 switch (hdspm->io_type) {
5076 case MADI:
5077 case MADIface:
5078 hdspm->control_register =
5079 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5080 break;
5081
5082 case RayDAT:
5083 case AIO:
5084 hdspm->settings_register = 0x1 + 0x1000;
5085 /* Magic values are: LAT_0, LAT_2, Master, freq1, tx64ch, inp_0,
5086 * line_out */
5087 hdspm->control_register =
5088 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5089 break;
5090
5091 case AES32:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005092 hdspm->control_register =
5093 HDSPM_ClockModeMaster | /* Master Cloack Mode on */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005094 hdspm_encode_latency(7) | /* latency max=8192samples */
Remy Bruno3cee5a62006-10-16 12:46:32 +02005095 HDSPM_SyncRef0 | /* AES1 is syncclock */
5096 HDSPM_LineOut | /* Analog output in */
5097 HDSPM_Professional; /* Professional mode */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005098 break;
5099 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005100
5101 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5102
Adrian Knoth0dca1792011-01-26 19:32:14 +01005103 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005104 /* No control2 register for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005105#ifdef SNDRV_BIG_ENDIAN
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005106 hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
Takashi Iwai763f3562005-06-03 11:25:34 +02005107#else
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005108 hdspm->control2_register = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005109#endif
5110
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005111 hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
5112 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005113 hdspm_compute_period_size(hdspm);
5114
5115 /* silence everything */
5116
5117 all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
5118
Adrian Knoth0dca1792011-01-26 19:32:14 +01005119 if (hdspm->io_type == AIO || hdspm->io_type == RayDAT) {
5120 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
Takashi Iwai763f3562005-06-03 11:25:34 +02005121 }
5122
5123 /* set a default rate so that the channel map is set up. */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005124 hdspm_set_rate(hdspm, 48000, 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02005125
5126 return 0;
5127}
5128
5129
5130/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005131 interrupt
Takashi Iwai763f3562005-06-03 11:25:34 +02005132 ------------------------------------------------------------*/
5133
David Howells7d12e782006-10-05 14:55:46 +01005134static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02005135{
Takashi Iwai98274f02005-11-17 14:52:34 +01005136 struct hdspm *hdspm = (struct hdspm *) dev_id;
Takashi Iwai763f3562005-06-03 11:25:34 +02005137 unsigned int status;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005138 int i, audio, midi, schedule = 0;
5139 /* cycles_t now; */
Takashi Iwai763f3562005-06-03 11:25:34 +02005140
5141 status = hdspm_read(hdspm, HDSPM_statusRegister);
5142
5143 audio = status & HDSPM_audioIRQPending;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005144 midi = status & (HDSPM_midi0IRQPending | HDSPM_midi1IRQPending |
5145 HDSPM_midi2IRQPending | HDSPM_midi3IRQPending);
Takashi Iwai763f3562005-06-03 11:25:34 +02005146
Adrian Knoth0dca1792011-01-26 19:32:14 +01005147 /* now = get_cycles(); */
5148 /**
5149 * LAT_2..LAT_0 period counter (win) counter (mac)
5150 * 6 4096 ~256053425 ~514672358
5151 * 5 2048 ~128024983 ~257373821
5152 * 4 1024 ~64023706 ~128718089
5153 * 3 512 ~32005945 ~64385999
5154 * 2 256 ~16003039 ~32260176
5155 * 1 128 ~7998738 ~16194507
5156 * 0 64 ~3998231 ~8191558
5157 **/
5158 /*
5159 snd_printk(KERN_INFO "snd_hdspm_interrupt %llu @ %llx\n",
5160 now-hdspm->last_interrupt, status & 0xFFC0);
5161 hdspm->last_interrupt = now;
5162 */
5163
5164 if (!audio && !midi)
Takashi Iwai763f3562005-06-03 11:25:34 +02005165 return IRQ_NONE;
5166
5167 hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
5168 hdspm->irq_count++;
5169
Takashi Iwai763f3562005-06-03 11:25:34 +02005170
5171 if (audio) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005172 if (hdspm->capture_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005173 snd_pcm_period_elapsed(hdspm->capture_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005174
5175 if (hdspm->playback_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005176 snd_pcm_period_elapsed(hdspm->playback_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005177 }
5178
Adrian Knoth0dca1792011-01-26 19:32:14 +01005179 if (midi) {
5180 i = 0;
5181 while (i < hdspm->midiPorts) {
5182 if ((hdspm_read(hdspm,
5183 hdspm->midi[i].statusIn) & 0xff) &&
5184 (status & hdspm->midi[i].irq)) {
5185 /* we disable interrupts for this input until
5186 * processing is done
5187 */
5188 hdspm->control_register &= ~hdspm->midi[i].ie;
5189 hdspm_write(hdspm, HDSPM_controlRegister,
5190 hdspm->control_register);
5191 hdspm->midi[i].pending = 1;
5192 schedule = 1;
5193 }
5194
5195 i++;
5196 }
5197
5198 if (schedule)
5199 tasklet_hi_schedule(&hdspm->midi_tasklet);
Takashi Iwai763f3562005-06-03 11:25:34 +02005200 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005201
Takashi Iwai763f3562005-06-03 11:25:34 +02005202 return IRQ_HANDLED;
5203}
5204
5205/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005206 pcm interface
Takashi Iwai763f3562005-06-03 11:25:34 +02005207 ------------------------------------------------------------*/
5208
5209
Adrian Knoth0dca1792011-01-26 19:32:14 +01005210static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream
5211 *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005212{
Takashi Iwai98274f02005-11-17 14:52:34 +01005213 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005214 return hdspm_hw_pointer(hdspm);
5215}
5216
Takashi Iwai763f3562005-06-03 11:25:34 +02005217
Takashi Iwai98274f02005-11-17 14:52:34 +01005218static int snd_hdspm_reset(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005219{
Takashi Iwai98274f02005-11-17 14:52:34 +01005220 struct snd_pcm_runtime *runtime = substream->runtime;
5221 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5222 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005223
5224 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5225 other = hdspm->capture_substream;
5226 else
5227 other = hdspm->playback_substream;
5228
5229 if (hdspm->running)
5230 runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
5231 else
5232 runtime->status->hw_ptr = 0;
5233 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005234 struct snd_pcm_substream *s;
5235 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01005236 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005237 if (s == other) {
5238 oruntime->status->hw_ptr =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005239 runtime->status->hw_ptr;
Takashi Iwai763f3562005-06-03 11:25:34 +02005240 break;
5241 }
5242 }
5243 }
5244 return 0;
5245}
5246
Takashi Iwai98274f02005-11-17 14:52:34 +01005247static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
5248 struct snd_pcm_hw_params *params)
Takashi Iwai763f3562005-06-03 11:25:34 +02005249{
Takashi Iwai98274f02005-11-17 14:52:34 +01005250 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005251 int err;
5252 int i;
5253 pid_t this_pid;
5254 pid_t other_pid;
Takashi Iwai763f3562005-06-03 11:25:34 +02005255
5256 spin_lock_irq(&hdspm->lock);
5257
5258 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5259 this_pid = hdspm->playback_pid;
5260 other_pid = hdspm->capture_pid;
5261 } else {
5262 this_pid = hdspm->capture_pid;
5263 other_pid = hdspm->playback_pid;
5264 }
5265
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005266 if (other_pid > 0 && this_pid != other_pid) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005267
5268 /* The other stream is open, and not by the same
5269 task as this one. Make sure that the parameters
5270 that matter are the same.
Adrian Knoth0dca1792011-01-26 19:32:14 +01005271 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005272
5273 if (params_rate(params) != hdspm->system_sample_rate) {
5274 spin_unlock_irq(&hdspm->lock);
5275 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005276 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005277 return -EBUSY;
5278 }
5279
5280 if (params_period_size(params) != hdspm->period_bytes / 4) {
5281 spin_unlock_irq(&hdspm->lock);
5282 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005283 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005284 return -EBUSY;
5285 }
5286
5287 }
5288 /* We're fine. */
5289 spin_unlock_irq(&hdspm->lock);
5290
5291 /* how to make sure that the rate matches an externally-set one ? */
5292
5293 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005294 err = hdspm_set_rate(hdspm, params_rate(params), 0);
5295 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005296 snd_printk(KERN_INFO "err on hdspm_set_rate: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005297 spin_unlock_irq(&hdspm->lock);
5298 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005299 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005300 return err;
5301 }
5302 spin_unlock_irq(&hdspm->lock);
5303
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005304 err = hdspm_set_interrupt_interval(hdspm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005305 params_period_size(params));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005306 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005307 snd_printk(KERN_INFO "err on hdspm_set_interrupt_interval: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005308 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005309 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005310 return err;
5311 }
5312
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005313 /* Memory allocation, takashi's method, dont know if we should
5314 * spinlock
5315 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005316 /* malloc all buffer even if not enabled to get sure */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005317 /* Update for MADI rev 204: we need to allocate for all channels,
5318 * otherwise it doesn't work at 96kHz */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005319
Takashi Iwai763f3562005-06-03 11:25:34 +02005320 err =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005321 snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
5322 if (err < 0) {
5323 snd_printk(KERN_INFO "err on snd_pcm_lib_malloc_pages: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005324 return err;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005325 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005326
Takashi Iwai763f3562005-06-03 11:25:34 +02005327 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5328
Takashi Iwai77a23f22008-08-21 13:00:13 +02005329 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferOut,
Takashi Iwai763f3562005-06-03 11:25:34 +02005330 params_channels(params));
5331
5332 for (i = 0; i < params_channels(params); ++i)
5333 snd_hdspm_enable_out(hdspm, i, 1);
5334
5335 hdspm->playback_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005336 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005337 snd_printdd("Allocated sample buffer for playback at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005338 hdspm->playback_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005339 } else {
Takashi Iwai77a23f22008-08-21 13:00:13 +02005340 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn,
Takashi Iwai763f3562005-06-03 11:25:34 +02005341 params_channels(params));
5342
5343 for (i = 0; i < params_channels(params); ++i)
5344 snd_hdspm_enable_in(hdspm, i, 1);
5345
5346 hdspm->capture_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005347 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005348 snd_printdd("Allocated sample buffer for capture at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005349 hdspm->capture_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005350 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005351
Remy Bruno3cee5a62006-10-16 12:46:32 +02005352 /*
5353 snd_printdd("Allocated sample buffer for %s at 0x%08X\n",
5354 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5355 "playback" : "capture",
Takashi Iwai77a23f22008-08-21 13:00:13 +02005356 snd_pcm_sgbuf_get_addr(substream, 0));
Adrian Knoth0dca1792011-01-26 19:32:14 +01005357 */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005358 /*
Adrian Knoth0dca1792011-01-26 19:32:14 +01005359 snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n",
5360 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5361 "playback" : "capture",
5362 params_rate(params), params_channels(params),
5363 params_buffer_size(params));
5364 */
5365
5366
5367 /* Switch to native float format if requested */
5368 if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) {
5369 if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT))
5370 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE float format.\n");
5371
5372 hdspm->control_register |= HDSPe_FLOAT_FORMAT;
5373 } else if (SNDRV_PCM_FORMAT_S32_LE == params_format(params)) {
5374 if (hdspm->control_register & HDSPe_FLOAT_FORMAT)
5375 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE integer format.\n");
5376
5377 hdspm->control_register &= ~HDSPe_FLOAT_FORMAT;
5378 }
5379 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5380
Takashi Iwai763f3562005-06-03 11:25:34 +02005381 return 0;
5382}
5383
Takashi Iwai98274f02005-11-17 14:52:34 +01005384static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005385{
5386 int i;
Takashi Iwai98274f02005-11-17 14:52:34 +01005387 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005388
5389 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5390
Adrian Knoth0dca1792011-01-26 19:32:14 +01005391 /* params_channels(params) should be enough,
Takashi Iwai763f3562005-06-03 11:25:34 +02005392 but to get sure in case of error */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005393 for (i = 0; i < hdspm->max_channels_out; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005394 snd_hdspm_enable_out(hdspm, i, 0);
5395
5396 hdspm->playback_buffer = NULL;
5397 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005398 for (i = 0; i < hdspm->max_channels_in; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005399 snd_hdspm_enable_in(hdspm, i, 0);
5400
5401 hdspm->capture_buffer = NULL;
5402
5403 }
5404
5405 snd_pcm_lib_free_pages(substream);
5406
5407 return 0;
5408}
5409
Adrian Knoth0dca1792011-01-26 19:32:14 +01005410
Takashi Iwai98274f02005-11-17 14:52:34 +01005411static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005412 struct snd_pcm_channel_info *info)
Takashi Iwai763f3562005-06-03 11:25:34 +02005413{
Takashi Iwai98274f02005-11-17 14:52:34 +01005414 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005415
Adrian Knoth0dca1792011-01-26 19:32:14 +01005416 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5417 if (snd_BUG_ON(info->channel >= hdspm->max_channels_out)) {
5418 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel out of range (%d)\n", info->channel);
5419 return -EINVAL;
5420 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005421
Adrian Knoth0dca1792011-01-26 19:32:14 +01005422 if (hdspm->channel_map_out[info->channel] < 0) {
5423 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel %d mapped out\n", info->channel);
5424 return -EINVAL;
5425 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005426
Adrian Knoth0dca1792011-01-26 19:32:14 +01005427 info->offset = hdspm->channel_map_out[info->channel] *
5428 HDSPM_CHANNEL_BUFFER_BYTES;
5429 } else {
5430 if (snd_BUG_ON(info->channel >= hdspm->max_channels_in)) {
5431 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel out of range (%d)\n", info->channel);
5432 return -EINVAL;
5433 }
5434
5435 if (hdspm->channel_map_in[info->channel] < 0) {
5436 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel %d mapped out\n", info->channel);
5437 return -EINVAL;
5438 }
5439
5440 info->offset = hdspm->channel_map_in[info->channel] *
5441 HDSPM_CHANNEL_BUFFER_BYTES;
5442 }
5443
Takashi Iwai763f3562005-06-03 11:25:34 +02005444 info->first = 0;
5445 info->step = 32;
5446 return 0;
5447}
5448
Adrian Knoth0dca1792011-01-26 19:32:14 +01005449
Takashi Iwai98274f02005-11-17 14:52:34 +01005450static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005451 unsigned int cmd, void *arg)
Takashi Iwai763f3562005-06-03 11:25:34 +02005452{
5453 switch (cmd) {
5454 case SNDRV_PCM_IOCTL1_RESET:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005455 return snd_hdspm_reset(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005456
5457 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Adrian Knoth0dca1792011-01-26 19:32:14 +01005458 {
5459 struct snd_pcm_channel_info *info = arg;
5460 return snd_hdspm_channel_info(substream, info);
5461 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005462 default:
5463 break;
5464 }
5465
5466 return snd_pcm_lib_ioctl(substream, cmd, arg);
5467}
5468
Takashi Iwai98274f02005-11-17 14:52:34 +01005469static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
Takashi Iwai763f3562005-06-03 11:25:34 +02005470{
Takashi Iwai98274f02005-11-17 14:52:34 +01005471 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5472 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005473 int running;
5474
5475 spin_lock(&hdspm->lock);
5476 running = hdspm->running;
5477 switch (cmd) {
5478 case SNDRV_PCM_TRIGGER_START:
5479 running |= 1 << substream->stream;
5480 break;
5481 case SNDRV_PCM_TRIGGER_STOP:
5482 running &= ~(1 << substream->stream);
5483 break;
5484 default:
5485 snd_BUG();
5486 spin_unlock(&hdspm->lock);
5487 return -EINVAL;
5488 }
5489 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5490 other = hdspm->capture_substream;
5491 else
5492 other = hdspm->playback_substream;
5493
5494 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005495 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01005496 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005497 if (s == other) {
5498 snd_pcm_trigger_done(s, substream);
5499 if (cmd == SNDRV_PCM_TRIGGER_START)
5500 running |= 1 << s->stream;
5501 else
5502 running &= ~(1 << s->stream);
5503 goto _ok;
5504 }
5505 }
5506 if (cmd == SNDRV_PCM_TRIGGER_START) {
5507 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005508 && substream->stream ==
5509 SNDRV_PCM_STREAM_CAPTURE)
Takashi Iwai763f3562005-06-03 11:25:34 +02005510 hdspm_silence_playback(hdspm);
5511 } else {
5512 if (running &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01005513 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Takashi Iwai763f3562005-06-03 11:25:34 +02005514 hdspm_silence_playback(hdspm);
5515 }
5516 } else {
5517 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
5518 hdspm_silence_playback(hdspm);
5519 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005520_ok:
Takashi Iwai763f3562005-06-03 11:25:34 +02005521 snd_pcm_trigger_done(substream, substream);
5522 if (!hdspm->running && running)
5523 hdspm_start_audio(hdspm);
5524 else if (hdspm->running && !running)
5525 hdspm_stop_audio(hdspm);
5526 hdspm->running = running;
5527 spin_unlock(&hdspm->lock);
5528
5529 return 0;
5530}
5531
Takashi Iwai98274f02005-11-17 14:52:34 +01005532static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005533{
5534 return 0;
5535}
5536
Takashi Iwai98274f02005-11-17 14:52:34 +01005537static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005538 .info = (SNDRV_PCM_INFO_MMAP |
5539 SNDRV_PCM_INFO_MMAP_VALID |
5540 SNDRV_PCM_INFO_NONINTERLEAVED |
5541 SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
5542 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5543 .rates = (SNDRV_PCM_RATE_32000 |
5544 SNDRV_PCM_RATE_44100 |
5545 SNDRV_PCM_RATE_48000 |
5546 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005547 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5548 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ),
Takashi Iwai763f3562005-06-03 11:25:34 +02005549 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005550 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005551 .channels_min = 1,
5552 .channels_max = HDSPM_MAX_CHANNELS,
5553 .buffer_bytes_max =
5554 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
Adrian Knoth1b6fa102011-08-15 00:22:51 +02005555 .period_bytes_min = (32 * 4),
Takashi Iwai52e6fb42011-08-15 10:40:59 +02005556 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005557 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005558 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005559 .fifo_size = 0
5560};
5561
Takashi Iwai98274f02005-11-17 14:52:34 +01005562static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005563 .info = (SNDRV_PCM_INFO_MMAP |
5564 SNDRV_PCM_INFO_MMAP_VALID |
5565 SNDRV_PCM_INFO_NONINTERLEAVED |
5566 SNDRV_PCM_INFO_SYNC_START),
5567 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5568 .rates = (SNDRV_PCM_RATE_32000 |
5569 SNDRV_PCM_RATE_44100 |
5570 SNDRV_PCM_RATE_48000 |
5571 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005572 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5573 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
Takashi Iwai763f3562005-06-03 11:25:34 +02005574 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005575 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005576 .channels_min = 1,
5577 .channels_max = HDSPM_MAX_CHANNELS,
5578 .buffer_bytes_max =
5579 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
Adrian Knoth1b6fa102011-08-15 00:22:51 +02005580 .period_bytes_min = (32 * 4),
Takashi Iwai52e6fb42011-08-15 10:40:59 +02005581 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005582 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005583 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005584 .fifo_size = 0
5585};
5586
Adrian Knoth0dca1792011-01-26 19:32:14 +01005587static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
5588 struct snd_pcm_hw_rule *rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005589{
Takashi Iwai98274f02005-11-17 14:52:34 +01005590 struct hdspm *hdspm = rule->private;
5591 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005592 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005593 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005594 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5595
Adrian Knoth0dca1792011-01-26 19:32:14 +01005596 if (r->min > 96000 && r->max <= 192000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005597 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005598 .min = hdspm->qs_in_channels,
5599 .max = hdspm->qs_in_channels,
5600 .integer = 1,
5601 };
5602 return snd_interval_refine(c, &t);
5603 } else if (r->min > 48000 && r->max <= 96000) {
5604 struct snd_interval t = {
5605 .min = hdspm->ds_in_channels,
5606 .max = hdspm->ds_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005607 .integer = 1,
5608 };
5609 return snd_interval_refine(c, &t);
5610 } else if (r->max < 64000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005611 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005612 .min = hdspm->ss_in_channels,
5613 .max = hdspm->ss_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005614 .integer = 1,
5615 };
5616 return snd_interval_refine(c, &t);
5617 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005618
Takashi Iwai763f3562005-06-03 11:25:34 +02005619 return 0;
5620}
5621
Adrian Knoth0dca1792011-01-26 19:32:14 +01005622static int snd_hdspm_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
Takashi Iwai98274f02005-11-17 14:52:34 +01005623 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005624{
Takashi Iwai98274f02005-11-17 14:52:34 +01005625 struct hdspm *hdspm = rule->private;
5626 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005627 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005628 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005629 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5630
Adrian Knoth0dca1792011-01-26 19:32:14 +01005631 if (r->min > 96000 && r->max <= 192000) {
5632 struct snd_interval t = {
5633 .min = hdspm->qs_out_channels,
5634 .max = hdspm->qs_out_channels,
5635 .integer = 1,
5636 };
5637 return snd_interval_refine(c, &t);
5638 } else if (r->min > 48000 && r->max <= 96000) {
5639 struct snd_interval t = {
5640 .min = hdspm->ds_out_channels,
5641 .max = hdspm->ds_out_channels,
5642 .integer = 1,
5643 };
5644 return snd_interval_refine(c, &t);
5645 } else if (r->max < 64000) {
5646 struct snd_interval t = {
5647 .min = hdspm->ss_out_channels,
5648 .max = hdspm->ss_out_channels,
5649 .integer = 1,
5650 };
5651 return snd_interval_refine(c, &t);
5652 } else {
5653 }
5654 return 0;
5655}
5656
5657static int snd_hdspm_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
5658 struct snd_pcm_hw_rule * rule)
5659{
5660 struct hdspm *hdspm = rule->private;
5661 struct snd_interval *c =
5662 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5663 struct snd_interval *r =
5664 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5665
5666 if (c->min >= hdspm->ss_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005667 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005668 .min = 32000,
5669 .max = 48000,
5670 .integer = 1,
5671 };
5672 return snd_interval_refine(r, &t);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005673 } else if (c->max <= hdspm->qs_in_channels) {
5674 struct snd_interval t = {
5675 .min = 128000,
5676 .max = 192000,
5677 .integer = 1,
5678 };
5679 return snd_interval_refine(r, &t);
5680 } else if (c->max <= hdspm->ds_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005681 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005682 .min = 64000,
5683 .max = 96000,
5684 .integer = 1,
5685 };
Takashi Iwai763f3562005-06-03 11:25:34 +02005686 return snd_interval_refine(r, &t);
5687 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005688
5689 return 0;
5690}
5691static int snd_hdspm_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
5692 struct snd_pcm_hw_rule *rule)
5693{
5694 struct hdspm *hdspm = rule->private;
5695 struct snd_interval *c =
5696 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5697 struct snd_interval *r =
5698 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5699
5700 if (c->min >= hdspm->ss_out_channels) {
5701 struct snd_interval t = {
5702 .min = 32000,
5703 .max = 48000,
5704 .integer = 1,
5705 };
5706 return snd_interval_refine(r, &t);
5707 } else if (c->max <= hdspm->qs_out_channels) {
5708 struct snd_interval t = {
5709 .min = 128000,
5710 .max = 192000,
5711 .integer = 1,
5712 };
5713 return snd_interval_refine(r, &t);
5714 } else if (c->max <= hdspm->ds_out_channels) {
5715 struct snd_interval t = {
5716 .min = 64000,
5717 .max = 96000,
5718 .integer = 1,
5719 };
5720 return snd_interval_refine(r, &t);
5721 }
5722
Takashi Iwai763f3562005-06-03 11:25:34 +02005723 return 0;
5724}
5725
Adrian Knoth0dca1792011-01-26 19:32:14 +01005726static int snd_hdspm_hw_rule_in_channels(struct snd_pcm_hw_params *params,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005727 struct snd_pcm_hw_rule *rule)
5728{
5729 unsigned int list[3];
5730 struct hdspm *hdspm = rule->private;
5731 struct snd_interval *c = hw_param_interval(params,
5732 SNDRV_PCM_HW_PARAM_CHANNELS);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005733
5734 list[0] = hdspm->qs_in_channels;
5735 list[1] = hdspm->ds_in_channels;
5736 list[2] = hdspm->ss_in_channels;
5737 return snd_interval_list(c, 3, list, 0);
5738}
5739
5740static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params,
5741 struct snd_pcm_hw_rule *rule)
5742{
5743 unsigned int list[3];
5744 struct hdspm *hdspm = rule->private;
5745 struct snd_interval *c = hw_param_interval(params,
5746 SNDRV_PCM_HW_PARAM_CHANNELS);
5747
5748 list[0] = hdspm->qs_out_channels;
5749 list[1] = hdspm->ds_out_channels;
5750 list[2] = hdspm->ss_out_channels;
5751 return snd_interval_list(c, 3, list, 0);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005752}
5753
5754
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005755static unsigned int hdspm_aes32_sample_rates[] = {
5756 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000
5757};
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005758
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005759static struct snd_pcm_hw_constraint_list
5760hdspm_hw_constraints_aes32_sample_rates = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005761 .count = ARRAY_SIZE(hdspm_aes32_sample_rates),
5762 .list = hdspm_aes32_sample_rates,
5763 .mask = 0
5764};
5765
Takashi Iwai98274f02005-11-17 14:52:34 +01005766static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005767{
Takashi Iwai98274f02005-11-17 14:52:34 +01005768 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5769 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02005770
Takashi Iwai763f3562005-06-03 11:25:34 +02005771 spin_lock_irq(&hdspm->lock);
5772
5773 snd_pcm_set_sync(substream);
5774
Adrian Knoth0dca1792011-01-26 19:32:14 +01005775
Takashi Iwai763f3562005-06-03 11:25:34 +02005776 runtime->hw = snd_hdspm_playback_subinfo;
5777
5778 if (hdspm->capture_substream == NULL)
5779 hdspm_stop_audio(hdspm);
5780
5781 hdspm->playback_pid = current->pid;
5782 hdspm->playback_substream = substream;
5783
5784 spin_unlock_irq(&hdspm->lock);
5785
5786 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Takashi Iwaid8776812011-08-15 10:45:42 +02005787 snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005788
Adrian Knoth0dca1792011-01-26 19:32:14 +01005789 switch (hdspm->io_type) {
5790 case AIO:
5791 case RayDAT:
Takashi Iwaid8776812011-08-15 10:45:42 +02005792 snd_pcm_hw_constraint_minmax(runtime,
5793 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5794 32, 4096);
5795 /* RayDAT & AIO have a fixed buffer of 16384 samples per channel */
5796 snd_pcm_hw_constraint_minmax(runtime,
5797 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
5798 16384, 16384);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005799 break;
5800
5801 default:
Takashi Iwaid8776812011-08-15 10:45:42 +02005802 snd_pcm_hw_constraint_minmax(runtime,
5803 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5804 64, 8192);
5805 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005806 }
5807
5808 if (AES32 == hdspm->io_type) {
Takashi Iwai3fa9e3d2011-08-15 10:42:23 +02005809 runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005810 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
5811 &hdspm_hw_constraints_aes32_sample_rates);
5812 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005813 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005814 snd_hdspm_hw_rule_rate_out_channels, hdspm,
5815 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005816 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01005817
5818 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5819 snd_hdspm_hw_rule_out_channels, hdspm,
5820 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
5821
5822 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5823 snd_hdspm_hw_rule_out_channels_rate, hdspm,
5824 SNDRV_PCM_HW_PARAM_RATE, -1);
5825
Takashi Iwai763f3562005-06-03 11:25:34 +02005826 return 0;
5827}
5828
Takashi Iwai98274f02005-11-17 14:52:34 +01005829static int snd_hdspm_playback_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005830{
Takashi Iwai98274f02005-11-17 14:52:34 +01005831 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005832
5833 spin_lock_irq(&hdspm->lock);
5834
5835 hdspm->playback_pid = -1;
5836 hdspm->playback_substream = NULL;
5837
5838 spin_unlock_irq(&hdspm->lock);
5839
5840 return 0;
5841}
5842
5843
Takashi Iwai98274f02005-11-17 14:52:34 +01005844static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005845{
Takashi Iwai98274f02005-11-17 14:52:34 +01005846 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5847 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02005848
5849 spin_lock_irq(&hdspm->lock);
5850 snd_pcm_set_sync(substream);
5851 runtime->hw = snd_hdspm_capture_subinfo;
5852
5853 if (hdspm->playback_substream == NULL)
5854 hdspm_stop_audio(hdspm);
5855
5856 hdspm->capture_pid = current->pid;
5857 hdspm->capture_substream = substream;
5858
5859 spin_unlock_irq(&hdspm->lock);
5860
5861 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Takashi Iwaid8776812011-08-15 10:45:42 +02005862 snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
5863
Adrian Knoth0dca1792011-01-26 19:32:14 +01005864 switch (hdspm->io_type) {
5865 case AIO:
5866 case RayDAT:
Takashi Iwaid8776812011-08-15 10:45:42 +02005867 snd_pcm_hw_constraint_minmax(runtime,
5868 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5869 32, 4096);
5870 snd_pcm_hw_constraint_minmax(runtime,
5871 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
5872 16384, 16384);
5873 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005874
5875 default:
Takashi Iwaid8776812011-08-15 10:45:42 +02005876 snd_pcm_hw_constraint_minmax(runtime,
5877 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5878 64, 8192);
5879 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005880 }
5881
5882 if (AES32 == hdspm->io_type) {
Takashi Iwai3fa9e3d2011-08-15 10:42:23 +02005883 runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005884 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
5885 &hdspm_hw_constraints_aes32_sample_rates);
5886 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005887 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth88fabbf2011-02-23 11:43:10 +01005888 snd_hdspm_hw_rule_rate_in_channels, hdspm,
5889 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005890 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01005891
5892 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5893 snd_hdspm_hw_rule_in_channels, hdspm,
5894 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
5895
5896 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5897 snd_hdspm_hw_rule_in_channels_rate, hdspm,
5898 SNDRV_PCM_HW_PARAM_RATE, -1);
5899
Takashi Iwai763f3562005-06-03 11:25:34 +02005900 return 0;
5901}
5902
Takashi Iwai98274f02005-11-17 14:52:34 +01005903static int snd_hdspm_capture_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005904{
Takashi Iwai98274f02005-11-17 14:52:34 +01005905 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005906
5907 spin_lock_irq(&hdspm->lock);
5908
5909 hdspm->capture_pid = -1;
5910 hdspm->capture_substream = NULL;
5911
5912 spin_unlock_irq(&hdspm->lock);
5913 return 0;
5914}
5915
Adrian Knoth0dca1792011-01-26 19:32:14 +01005916static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
Takashi Iwai763f3562005-06-03 11:25:34 +02005917{
Adrian Knoth0dca1792011-01-26 19:32:14 +01005918 /* we have nothing to initialize but the call is required */
5919 return 0;
5920}
5921
5922static inline int copy_u32_le(void __user *dest, void __iomem *src)
5923{
5924 u32 val = readl(src);
5925 return copy_to_user(dest, &val, 4);
5926}
5927
5928static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
Dan Carpenter2ca595a2011-09-23 09:25:05 +03005929 unsigned int cmd, unsigned long arg)
Adrian Knoth0dca1792011-01-26 19:32:14 +01005930{
5931 void __user *argp = (void __user *)arg;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005932 struct hdspm *hdspm = hw->private_data;
Takashi Iwai98274f02005-11-17 14:52:34 +01005933 struct hdspm_mixer_ioctl mixer;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005934 struct hdspm_config info;
5935 struct hdspm_status status;
Takashi Iwai98274f02005-11-17 14:52:34 +01005936 struct hdspm_version hdspm_version;
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005937 struct hdspm_peak_rms *levels;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005938 struct hdspm_ltc ltc;
5939 unsigned int statusregister;
5940 long unsigned int s;
5941 int i = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005942
5943 switch (cmd) {
5944
Takashi Iwai763f3562005-06-03 11:25:34 +02005945 case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005946 levels = &hdspm->peak_rms;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005947 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005948 levels->input_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005949 readl(hdspm->iobase +
5950 HDSPM_MADI_INPUT_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005951 levels->playback_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005952 readl(hdspm->iobase +
5953 HDSPM_MADI_PLAYBACK_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005954 levels->output_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005955 readl(hdspm->iobase +
5956 HDSPM_MADI_OUTPUT_PEAK + i*4);
5957
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005958 levels->input_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005959 ((uint64_t) readl(hdspm->iobase +
5960 HDSPM_MADI_INPUT_RMS_H + i*4) << 32) |
5961 (uint64_t) readl(hdspm->iobase +
5962 HDSPM_MADI_INPUT_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005963 levels->playback_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005964 ((uint64_t)readl(hdspm->iobase +
5965 HDSPM_MADI_PLAYBACK_RMS_H+i*4) << 32) |
5966 (uint64_t)readl(hdspm->iobase +
5967 HDSPM_MADI_PLAYBACK_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005968 levels->output_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005969 ((uint64_t)readl(hdspm->iobase +
5970 HDSPM_MADI_OUTPUT_RMS_H + i*4) << 32) |
5971 (uint64_t)readl(hdspm->iobase +
5972 HDSPM_MADI_OUTPUT_RMS_L + i*4);
5973 }
5974
5975 if (hdspm->system_sample_rate > 96000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005976 levels->speed = qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005977 } else if (hdspm->system_sample_rate > 48000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005978 levels->speed = ds;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005979 } else {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005980 levels->speed = ss;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005981 }
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005982 levels->status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005983
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005984 s = copy_to_user(argp, levels, sizeof(struct hdspm_peak_rms));
Adrian Knoth0dca1792011-01-26 19:32:14 +01005985 if (0 != s) {
5986 /* snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu
5987 [Levels]\n", sizeof(struct hdspm_peak_rms), s);
5988 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005989 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005990 }
5991 break;
5992
5993 case SNDRV_HDSPM_IOCTL_GET_LTC:
5994 ltc.ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
5995 i = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
5996 if (i & HDSPM_TCO1_LTC_Input_valid) {
5997 switch (i & (HDSPM_TCO1_LTC_Format_LSB |
5998 HDSPM_TCO1_LTC_Format_MSB)) {
5999 case 0:
6000 ltc.format = fps_24;
6001 break;
6002 case HDSPM_TCO1_LTC_Format_LSB:
6003 ltc.format = fps_25;
6004 break;
6005 case HDSPM_TCO1_LTC_Format_MSB:
6006 ltc.format = fps_2997;
6007 break;
6008 default:
6009 ltc.format = 30;
6010 break;
6011 }
6012 if (i & HDSPM_TCO1_set_drop_frame_flag) {
6013 ltc.frame = drop_frame;
6014 } else {
6015 ltc.frame = full_frame;
6016 }
6017 } else {
6018 ltc.format = format_invalid;
6019 ltc.frame = frame_invalid;
6020 }
6021 if (i & HDSPM_TCO1_Video_Input_Format_NTSC) {
6022 ltc.input_format = ntsc;
6023 } else if (i & HDSPM_TCO1_Video_Input_Format_PAL) {
6024 ltc.input_format = pal;
6025 } else {
6026 ltc.input_format = no_video;
6027 }
6028
6029 s = copy_to_user(argp, &ltc, sizeof(struct hdspm_ltc));
6030 if (0 != s) {
6031 /*
6032 snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */
Takashi Iwai763f3562005-06-03 11:25:34 +02006033 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006034 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006035
6036 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02006037
Adrian Knoth0dca1792011-01-26 19:32:14 +01006038 case SNDRV_HDSPM_IOCTL_GET_CONFIG:
Takashi Iwai763f3562005-06-03 11:25:34 +02006039
Adrian Knoth4ab69a22011-02-23 11:43:14 +01006040 memset(&info, 0, sizeof(info));
Takashi Iwai763f3562005-06-03 11:25:34 +02006041 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006042 info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
6043 info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006044
6045 info.system_sample_rate = hdspm->system_sample_rate;
6046 info.autosync_sample_rate =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006047 hdspm_external_sample_rate(hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006048 info.system_clock_mode = hdspm_system_clock_mode(hdspm);
6049 info.clock_source = hdspm_clock_source(hdspm);
6050 info.autosync_ref = hdspm_autosync_ref(hdspm);
Adrian Knothc9e16682012-12-03 14:55:50 +01006051 info.line_out = hdspm_toggle_setting(hdspm, HDSPM_LineOut);
Takashi Iwai763f3562005-06-03 11:25:34 +02006052 info.passthru = 0;
6053 spin_unlock_irq(&hdspm->lock);
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006054 if (copy_to_user(argp, &info, sizeof(info)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006055 return -EFAULT;
6056 break;
6057
Adrian Knoth0dca1792011-01-26 19:32:14 +01006058 case SNDRV_HDSPM_IOCTL_GET_STATUS:
Dan Carpenter643d6bb2011-09-23 09:24:21 +03006059 memset(&status, 0, sizeof(status));
6060
Adrian Knoth0dca1792011-01-26 19:32:14 +01006061 status.card_type = hdspm->io_type;
6062
6063 status.autosync_source = hdspm_autosync_ref(hdspm);
6064
6065 status.card_clock = 110069313433624ULL;
6066 status.master_period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
6067
6068 switch (hdspm->io_type) {
6069 case MADI:
6070 case MADIface:
6071 status.card_specific.madi.sync_wc =
6072 hdspm_wc_sync_check(hdspm);
6073 status.card_specific.madi.sync_madi =
6074 hdspm_madi_sync_check(hdspm);
6075 status.card_specific.madi.sync_tco =
6076 hdspm_tco_sync_check(hdspm);
6077 status.card_specific.madi.sync_in =
6078 hdspm_sync_in_sync_check(hdspm);
6079
6080 statusregister =
6081 hdspm_read(hdspm, HDSPM_statusRegister);
6082 status.card_specific.madi.madi_input =
6083 (statusregister & HDSPM_AB_int) ? 1 : 0;
6084 status.card_specific.madi.channel_format =
Adrian Knoth9e6ff522011-10-27 21:57:52 +02006085 (statusregister & HDSPM_RX_64ch) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006086 /* TODO: Mac driver sets it when f_s>48kHz */
6087 status.card_specific.madi.frame_format = 0;
6088
6089 default:
6090 break;
6091 }
6092
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006093 if (copy_to_user(argp, &status, sizeof(status)))
Adrian Knoth0dca1792011-01-26 19:32:14 +01006094 return -EFAULT;
6095
6096
6097 break;
6098
Takashi Iwai763f3562005-06-03 11:25:34 +02006099 case SNDRV_HDSPM_IOCTL_GET_VERSION:
Dan Carpenter643d6bb2011-09-23 09:24:21 +03006100 memset(&hdspm_version, 0, sizeof(hdspm_version));
6101
Adrian Knoth0dca1792011-01-26 19:32:14 +01006102 hdspm_version.card_type = hdspm->io_type;
6103 strncpy(hdspm_version.cardname, hdspm->card_name,
6104 sizeof(hdspm_version.cardname));
Adrian Knoth7d53a632012-01-04 14:31:16 +01006105 hdspm_version.serial = hdspm->serial;
Takashi Iwai763f3562005-06-03 11:25:34 +02006106 hdspm_version.firmware_rev = hdspm->firmware_rev;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006107 hdspm_version.addons = 0;
6108 if (hdspm->tco)
6109 hdspm_version.addons |= HDSPM_ADDON_TCO;
6110
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006111 if (copy_to_user(argp, &hdspm_version,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006112 sizeof(hdspm_version)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006113 return -EFAULT;
6114 break;
6115
6116 case SNDRV_HDSPM_IOCTL_GET_MIXER:
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006117 if (copy_from_user(&mixer, argp, sizeof(mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006118 return -EFAULT;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006119 if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006120 sizeof(struct hdspm_mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006121 return -EFAULT;
6122 break;
6123
6124 default:
6125 return -EINVAL;
6126 }
6127 return 0;
6128}
6129
Takashi Iwai98274f02005-11-17 14:52:34 +01006130static struct snd_pcm_ops snd_hdspm_playback_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006131 .open = snd_hdspm_playback_open,
6132 .close = snd_hdspm_playback_release,
6133 .ioctl = snd_hdspm_ioctl,
6134 .hw_params = snd_hdspm_hw_params,
6135 .hw_free = snd_hdspm_hw_free,
6136 .prepare = snd_hdspm_prepare,
6137 .trigger = snd_hdspm_trigger,
6138 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006139 .page = snd_pcm_sgbuf_ops_page,
6140};
6141
Takashi Iwai98274f02005-11-17 14:52:34 +01006142static struct snd_pcm_ops snd_hdspm_capture_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006143 .open = snd_hdspm_capture_open,
6144 .close = snd_hdspm_capture_release,
6145 .ioctl = snd_hdspm_ioctl,
6146 .hw_params = snd_hdspm_hw_params,
6147 .hw_free = snd_hdspm_hw_free,
6148 .prepare = snd_hdspm_prepare,
6149 .trigger = snd_hdspm_trigger,
6150 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006151 .page = snd_pcm_sgbuf_ops_page,
6152};
6153
Bill Pembertone23e7a12012-12-06 12:35:10 -05006154static int snd_hdspm_create_hwdep(struct snd_card *card,
6155 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006156{
Takashi Iwai98274f02005-11-17 14:52:34 +01006157 struct snd_hwdep *hw;
Takashi Iwai763f3562005-06-03 11:25:34 +02006158 int err;
6159
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006160 err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw);
6161 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006162 return err;
6163
6164 hdspm->hwdep = hw;
6165 hw->private_data = hdspm;
6166 strcpy(hw->name, "HDSPM hwdep interface");
6167
Adrian Knoth0dca1792011-01-26 19:32:14 +01006168 hw->ops.open = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006169 hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
Adrian Knoth8de5d6f2012-03-08 15:38:04 +01006170 hw->ops.ioctl_compat = snd_hdspm_hwdep_ioctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006171 hw->ops.release = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006172
6173 return 0;
6174}
6175
6176
6177/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01006178 memory interface
Takashi Iwai763f3562005-06-03 11:25:34 +02006179 ------------------------------------------------------------*/
Bill Pembertone23e7a12012-12-06 12:35:10 -05006180static int snd_hdspm_preallocate_memory(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006181{
6182 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01006183 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006184 size_t wanted;
6185
6186 pcm = hdspm->pcm;
6187
Remy Bruno3cee5a62006-10-16 12:46:32 +02006188 wanted = HDSPM_DMA_AREA_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02006189
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006190 err =
Takashi Iwai763f3562005-06-03 11:25:34 +02006191 snd_pcm_lib_preallocate_pages_for_all(pcm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006192 SNDRV_DMA_TYPE_DEV_SG,
Takashi Iwai763f3562005-06-03 11:25:34 +02006193 snd_dma_pci_data(hdspm->pci),
6194 wanted,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006195 wanted);
6196 if (err < 0) {
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006197 snd_printdd("Could not preallocate %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006198
6199 return err;
6200 } else
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006201 snd_printdd(" Preallocated %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006202
6203 return 0;
6204}
6205
Adrian Knoth0dca1792011-01-26 19:32:14 +01006206
6207static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +02006208 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02006209 unsigned int reg, int channels)
6210{
6211 int i;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006212
6213 /* continuous memory segment */
Takashi Iwai763f3562005-06-03 11:25:34 +02006214 for (i = 0; i < (channels * 16); i++)
6215 hdspm_write(hdspm, reg + 4 * i,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006216 snd_pcm_sgbuf_get_addr(substream, 4096 * i));
Takashi Iwai763f3562005-06-03 11:25:34 +02006217}
6218
Adrian Knoth0dca1792011-01-26 19:32:14 +01006219
Takashi Iwai763f3562005-06-03 11:25:34 +02006220/* ------------- ALSA Devices ---------------------------- */
Bill Pembertone23e7a12012-12-06 12:35:10 -05006221static int snd_hdspm_create_pcm(struct snd_card *card,
6222 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006223{
Takashi Iwai98274f02005-11-17 14:52:34 +01006224 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006225 int err;
6226
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006227 err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm);
6228 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006229 return err;
6230
6231 hdspm->pcm = pcm;
6232 pcm->private_data = hdspm;
6233 strcpy(pcm->name, hdspm->card_name);
6234
6235 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
6236 &snd_hdspm_playback_ops);
6237 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
6238 &snd_hdspm_capture_ops);
6239
6240 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
6241
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006242 err = snd_hdspm_preallocate_memory(hdspm);
6243 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006244 return err;
6245
6246 return 0;
6247}
6248
Takashi Iwai98274f02005-11-17 14:52:34 +01006249static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006250{
Adrian Knoth7c7102b2011-02-28 15:14:50 +01006251 int i;
6252
6253 for (i = 0; i < hdspm->midiPorts; i++)
6254 snd_hdspm_flush_midi_input(hdspm, i);
Takashi Iwai763f3562005-06-03 11:25:34 +02006255}
6256
Bill Pembertone23e7a12012-12-06 12:35:10 -05006257static int snd_hdspm_create_alsa_devices(struct snd_card *card,
6258 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006259{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006260 int err, i;
Takashi Iwai763f3562005-06-03 11:25:34 +02006261
6262 snd_printdd("Create card...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006263 err = snd_hdspm_create_pcm(card, hdspm);
6264 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006265 return err;
6266
Adrian Knoth0dca1792011-01-26 19:32:14 +01006267 i = 0;
6268 while (i < hdspm->midiPorts) {
6269 err = snd_hdspm_create_midi(card, hdspm, i);
6270 if (err < 0) {
6271 return err;
6272 }
6273 i++;
6274 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006275
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006276 err = snd_hdspm_create_controls(card, hdspm);
6277 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006278 return err;
6279
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006280 err = snd_hdspm_create_hwdep(card, hdspm);
6281 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006282 return err;
6283
6284 snd_printdd("proc init...\n");
6285 snd_hdspm_proc_init(hdspm);
6286
6287 hdspm->system_sample_rate = -1;
6288 hdspm->last_external_sample_rate = -1;
6289 hdspm->last_internal_sample_rate = -1;
6290 hdspm->playback_pid = -1;
6291 hdspm->capture_pid = -1;
6292 hdspm->capture_substream = NULL;
6293 hdspm->playback_substream = NULL;
6294
6295 snd_printdd("Set defaults...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006296 err = snd_hdspm_set_defaults(hdspm);
6297 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006298 return err;
6299
6300 snd_printdd("Update mixer controls...\n");
6301 hdspm_update_simple_mixer_controls(hdspm);
6302
6303 snd_printdd("Initializeing complete ???\n");
6304
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006305 err = snd_card_register(card);
6306 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006307 snd_printk(KERN_ERR "HDSPM: error registering card\n");
6308 return err;
6309 }
6310
6311 snd_printdd("... yes now\n");
6312
6313 return 0;
6314}
6315
Bill Pembertone23e7a12012-12-06 12:35:10 -05006316static int snd_hdspm_create(struct snd_card *card,
6317 struct hdspm *hdspm)
6318{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006319
Takashi Iwai763f3562005-06-03 11:25:34 +02006320 struct pci_dev *pci = hdspm->pci;
6321 int err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006322 unsigned long io_extent;
6323
6324 hdspm->irq = -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02006325 hdspm->card = card;
6326
6327 spin_lock_init(&hdspm->lock);
6328
Takashi Iwai763f3562005-06-03 11:25:34 +02006329 pci_read_config_word(hdspm->pci,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006330 PCI_CLASS_REVISION, &hdspm->firmware_rev);
Remy Bruno3cee5a62006-10-16 12:46:32 +02006331
Takashi Iwai763f3562005-06-03 11:25:34 +02006332 strcpy(card->mixername, "Xilinx FPGA");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006333 strcpy(card->driver, "HDSPM");
6334
6335 switch (hdspm->firmware_rev) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01006336 case HDSPM_RAYDAT_REV:
6337 hdspm->io_type = RayDAT;
6338 hdspm->card_name = "RME RayDAT";
6339 hdspm->midiPorts = 2;
6340 break;
6341 case HDSPM_AIO_REV:
6342 hdspm->io_type = AIO;
6343 hdspm->card_name = "RME AIO";
6344 hdspm->midiPorts = 1;
6345 break;
6346 case HDSPM_MADIFACE_REV:
6347 hdspm->io_type = MADIface;
6348 hdspm->card_name = "RME MADIface";
6349 hdspm->midiPorts = 1;
6350 break;
Adrian Knoth5027f342011-02-28 15:14:49 +01006351 default:
Adrian Knothc09403d2011-10-27 21:57:54 +02006352 if ((hdspm->firmware_rev == 0xf0) ||
6353 ((hdspm->firmware_rev >= 0xe6) &&
6354 (hdspm->firmware_rev <= 0xea))) {
6355 hdspm->io_type = AES32;
6356 hdspm->card_name = "RME AES32";
6357 hdspm->midiPorts = 2;
Adrian Knoth05c7cc92011-11-21 16:15:36 +01006358 } else if ((hdspm->firmware_rev == 0xd2) ||
Adrian Knothc09403d2011-10-27 21:57:54 +02006359 ((hdspm->firmware_rev >= 0xc8) &&
6360 (hdspm->firmware_rev <= 0xcf))) {
6361 hdspm->io_type = MADI;
6362 hdspm->card_name = "RME MADI";
6363 hdspm->midiPorts = 3;
6364 } else {
6365 snd_printk(KERN_ERR
6366 "HDSPM: unknown firmware revision %x\n",
Adrian Knoth5027f342011-02-28 15:14:49 +01006367 hdspm->firmware_rev);
Adrian Knothc09403d2011-10-27 21:57:54 +02006368 return -ENODEV;
6369 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02006370 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006371
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006372 err = pci_enable_device(pci);
6373 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006374 return err;
6375
6376 pci_set_master(hdspm->pci);
6377
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006378 err = pci_request_regions(pci, "hdspm");
6379 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006380 return err;
6381
6382 hdspm->port = pci_resource_start(pci, 0);
6383 io_extent = pci_resource_len(pci, 0);
6384
6385 snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006386 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006387
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006388 hdspm->iobase = ioremap_nocache(hdspm->port, io_extent);
6389 if (!hdspm->iobase) {
6390 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006391 "unable to remap region 0x%lx-0x%lx\n",
6392 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006393 return -EBUSY;
6394 }
6395 snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006396 (unsigned long)hdspm->iobase, hdspm->port,
6397 hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006398
6399 if (request_irq(pci->irq, snd_hdspm_interrupt,
Takashi Iwai934c2b62011-06-10 16:36:37 +02006400 IRQF_SHARED, KBUILD_MODNAME, hdspm)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006401 snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
6402 return -EBUSY;
6403 }
6404
6405 snd_printdd("use IRQ %d\n", pci->irq);
6406
6407 hdspm->irq = pci->irq;
Takashi Iwai763f3562005-06-03 11:25:34 +02006408
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006409 snd_printdd("kmalloc Mixer memory of %zd Bytes\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006410 sizeof(struct hdspm_mixer));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006411 hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL);
6412 if (!hdspm->mixer) {
6413 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006414 "unable to kmalloc Mixer memory of %d Bytes\n",
6415 (int)sizeof(struct hdspm_mixer));
Julia Lawallb17cbdd2012-08-19 09:02:54 +02006416 return -ENOMEM;
Takashi Iwai763f3562005-06-03 11:25:34 +02006417 }
6418
Adrian Knoth0dca1792011-01-26 19:32:14 +01006419 hdspm->port_names_in = NULL;
6420 hdspm->port_names_out = NULL;
6421
6422 switch (hdspm->io_type) {
6423 case AES32:
Adrian Knothd2d10a22011-02-28 15:14:47 +01006424 hdspm->ss_in_channels = hdspm->ss_out_channels = AES32_CHANNELS;
6425 hdspm->ds_in_channels = hdspm->ds_out_channels = AES32_CHANNELS;
6426 hdspm->qs_in_channels = hdspm->qs_out_channels = AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006427
6428 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6429 channel_map_aes32;
6430 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6431 channel_map_aes32;
6432 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6433 channel_map_aes32;
6434 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6435 texts_ports_aes32;
6436 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6437 texts_ports_aes32;
6438 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6439 texts_ports_aes32;
6440
Adrian Knothd2d10a22011-02-28 15:14:47 +01006441 hdspm->max_channels_out = hdspm->max_channels_in =
6442 AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006443 hdspm->port_names_in = hdspm->port_names_out =
6444 texts_ports_aes32;
6445 hdspm->channel_map_in = hdspm->channel_map_out =
6446 channel_map_aes32;
6447
Adrian Knoth0dca1792011-01-26 19:32:14 +01006448 break;
6449
6450 case MADI:
6451 case MADIface:
6452 hdspm->ss_in_channels = hdspm->ss_out_channels =
6453 MADI_SS_CHANNELS;
6454 hdspm->ds_in_channels = hdspm->ds_out_channels =
6455 MADI_DS_CHANNELS;
6456 hdspm->qs_in_channels = hdspm->qs_out_channels =
6457 MADI_QS_CHANNELS;
6458
6459 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6460 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006461 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006462 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006463 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006464 channel_map_unity_ss;
6465
6466 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6467 texts_ports_madi;
6468 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6469 texts_ports_madi;
6470 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6471 texts_ports_madi;
6472 break;
6473
6474 case AIO:
6475 if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) {
6476 snd_printk(KERN_INFO "HDSPM: AEB input board found, but not supported\n");
6477 }
6478
6479 hdspm->ss_in_channels = AIO_IN_SS_CHANNELS;
6480 hdspm->ds_in_channels = AIO_IN_DS_CHANNELS;
6481 hdspm->qs_in_channels = AIO_IN_QS_CHANNELS;
6482 hdspm->ss_out_channels = AIO_OUT_SS_CHANNELS;
6483 hdspm->ds_out_channels = AIO_OUT_DS_CHANNELS;
6484 hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS;
6485
6486 hdspm->channel_map_out_ss = channel_map_aio_out_ss;
6487 hdspm->channel_map_out_ds = channel_map_aio_out_ds;
6488 hdspm->channel_map_out_qs = channel_map_aio_out_qs;
6489
6490 hdspm->channel_map_in_ss = channel_map_aio_in_ss;
6491 hdspm->channel_map_in_ds = channel_map_aio_in_ds;
6492 hdspm->channel_map_in_qs = channel_map_aio_in_qs;
6493
6494 hdspm->port_names_in_ss = texts_ports_aio_in_ss;
6495 hdspm->port_names_out_ss = texts_ports_aio_out_ss;
6496 hdspm->port_names_in_ds = texts_ports_aio_in_ds;
6497 hdspm->port_names_out_ds = texts_ports_aio_out_ds;
6498 hdspm->port_names_in_qs = texts_ports_aio_in_qs;
6499 hdspm->port_names_out_qs = texts_ports_aio_out_qs;
6500
6501 break;
6502
6503 case RayDAT:
6504 hdspm->ss_in_channels = hdspm->ss_out_channels =
6505 RAYDAT_SS_CHANNELS;
6506 hdspm->ds_in_channels = hdspm->ds_out_channels =
6507 RAYDAT_DS_CHANNELS;
6508 hdspm->qs_in_channels = hdspm->qs_out_channels =
6509 RAYDAT_QS_CHANNELS;
6510
6511 hdspm->max_channels_in = RAYDAT_SS_CHANNELS;
6512 hdspm->max_channels_out = RAYDAT_SS_CHANNELS;
6513
6514 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6515 channel_map_raydat_ss;
6516 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6517 channel_map_raydat_ds;
6518 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6519 channel_map_raydat_qs;
6520 hdspm->channel_map_in = hdspm->channel_map_out =
6521 channel_map_raydat_ss;
6522
6523 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6524 texts_ports_raydat_ss;
6525 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6526 texts_ports_raydat_ds;
6527 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6528 texts_ports_raydat_qs;
6529
6530
6531 break;
6532
6533 }
6534
6535 /* TCO detection */
6536 switch (hdspm->io_type) {
6537 case AIO:
6538 case RayDAT:
6539 if (hdspm_read(hdspm, HDSPM_statusRegister2) &
6540 HDSPM_s2_tco_detect) {
6541 hdspm->midiPorts++;
6542 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6543 GFP_KERNEL);
6544 if (NULL != hdspm->tco) {
6545 hdspm_tco_write(hdspm);
6546 }
6547 snd_printk(KERN_INFO "HDSPM: AIO/RayDAT TCO module found\n");
6548 } else {
6549 hdspm->tco = NULL;
6550 }
6551 break;
6552
6553 case MADI:
6554 if (hdspm_read(hdspm, HDSPM_statusRegister) & HDSPM_tco_detect) {
6555 hdspm->midiPorts++;
6556 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6557 GFP_KERNEL);
6558 if (NULL != hdspm->tco) {
6559 hdspm_tco_write(hdspm);
6560 }
6561 snd_printk(KERN_INFO "HDSPM: MADI TCO module found\n");
6562 } else {
6563 hdspm->tco = NULL;
6564 }
6565 break;
6566
6567 default:
6568 hdspm->tco = NULL;
6569 }
6570
6571 /* texts */
6572 switch (hdspm->io_type) {
6573 case AES32:
6574 if (hdspm->tco) {
6575 hdspm->texts_autosync = texts_autosync_aes_tco;
6576 hdspm->texts_autosync_items = 10;
6577 } else {
6578 hdspm->texts_autosync = texts_autosync_aes;
6579 hdspm->texts_autosync_items = 9;
6580 }
6581 break;
6582
6583 case MADI:
6584 if (hdspm->tco) {
6585 hdspm->texts_autosync = texts_autosync_madi_tco;
6586 hdspm->texts_autosync_items = 4;
6587 } else {
6588 hdspm->texts_autosync = texts_autosync_madi;
6589 hdspm->texts_autosync_items = 3;
6590 }
6591 break;
6592
6593 case MADIface:
6594
6595 break;
6596
6597 case RayDAT:
6598 if (hdspm->tco) {
6599 hdspm->texts_autosync = texts_autosync_raydat_tco;
6600 hdspm->texts_autosync_items = 9;
6601 } else {
6602 hdspm->texts_autosync = texts_autosync_raydat;
6603 hdspm->texts_autosync_items = 8;
6604 }
6605 break;
6606
6607 case AIO:
6608 if (hdspm->tco) {
6609 hdspm->texts_autosync = texts_autosync_aio_tco;
6610 hdspm->texts_autosync_items = 6;
6611 } else {
6612 hdspm->texts_autosync = texts_autosync_aio;
6613 hdspm->texts_autosync_items = 5;
6614 }
6615 break;
6616
6617 }
6618
6619 tasklet_init(&hdspm->midi_tasklet,
6620 hdspm_midi_tasklet, (unsigned long) hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006621
Adrian Knothf7de8ba2012-01-10 20:58:40 +01006622
6623 if (hdspm->io_type != MADIface) {
6624 hdspm->serial = (hdspm_read(hdspm,
6625 HDSPM_midiStatusIn0)>>8) & 0xFFFFFF;
6626 /* id contains either a user-provided value or the default
6627 * NULL. If it's the default, we're safe to
6628 * fill card->id with the serial number.
6629 *
6630 * If the serial number is 0xFFFFFF, then we're dealing with
6631 * an old PCI revision that comes without a sane number. In
6632 * this case, we don't set card->id to avoid collisions
6633 * when running with multiple cards.
6634 */
6635 if (NULL == id[hdspm->dev] && hdspm->serial != 0xFFFFFF) {
6636 sprintf(card->id, "HDSPMx%06x", hdspm->serial);
6637 snd_card_set_id(card, card->id);
6638 }
6639 }
6640
Takashi Iwai763f3562005-06-03 11:25:34 +02006641 snd_printdd("create alsa devices.\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006642 err = snd_hdspm_create_alsa_devices(card, hdspm);
6643 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006644 return err;
6645
6646 snd_hdspm_initialize_midi_flush(hdspm);
6647
6648 return 0;
6649}
6650
Adrian Knoth0dca1792011-01-26 19:32:14 +01006651
Takashi Iwai98274f02005-11-17 14:52:34 +01006652static int snd_hdspm_free(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006653{
6654
6655 if (hdspm->port) {
6656
6657 /* stop th audio, and cancel all interrupts */
6658 hdspm->control_register &=
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006659 ~(HDSPM_Start | HDSPM_AudioInterruptEnable |
Adrian Knoth0dca1792011-01-26 19:32:14 +01006660 HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable |
6661 HDSPM_Midi2InterruptEnable | HDSPM_Midi3InterruptEnable);
Takashi Iwai763f3562005-06-03 11:25:34 +02006662 hdspm_write(hdspm, HDSPM_controlRegister,
6663 hdspm->control_register);
6664 }
6665
6666 if (hdspm->irq >= 0)
6667 free_irq(hdspm->irq, (void *) hdspm);
6668
Jesper Juhlfc584222005-10-24 15:11:28 +02006669 kfree(hdspm->mixer);
Takashi Iwai763f3562005-06-03 11:25:34 +02006670
6671 if (hdspm->iobase)
6672 iounmap(hdspm->iobase);
6673
Takashi Iwai763f3562005-06-03 11:25:34 +02006674 if (hdspm->port)
6675 pci_release_regions(hdspm->pci);
6676
6677 pci_disable_device(hdspm->pci);
6678 return 0;
6679}
6680
Adrian Knoth0dca1792011-01-26 19:32:14 +01006681
Takashi Iwai98274f02005-11-17 14:52:34 +01006682static void snd_hdspm_card_free(struct snd_card *card)
Takashi Iwai763f3562005-06-03 11:25:34 +02006683{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006684 struct hdspm *hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006685
6686 if (hdspm)
6687 snd_hdspm_free(hdspm);
6688}
6689
Adrian Knoth0dca1792011-01-26 19:32:14 +01006690
Bill Pembertone23e7a12012-12-06 12:35:10 -05006691static int snd_hdspm_probe(struct pci_dev *pci,
6692 const struct pci_device_id *pci_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02006693{
6694 static int dev;
Takashi Iwai98274f02005-11-17 14:52:34 +01006695 struct hdspm *hdspm;
6696 struct snd_card *card;
Takashi Iwai763f3562005-06-03 11:25:34 +02006697 int err;
6698
6699 if (dev >= SNDRV_CARDS)
6700 return -ENODEV;
6701 if (!enable[dev]) {
6702 dev++;
6703 return -ENOENT;
6704 }
6705
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006706 err = snd_card_create(index[dev], id[dev],
Adrian Knoth0dca1792011-01-26 19:32:14 +01006707 THIS_MODULE, sizeof(struct hdspm), &card);
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006708 if (err < 0)
6709 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006710
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006711 hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006712 card->private_free = snd_hdspm_card_free;
6713 hdspm->dev = dev;
6714 hdspm->pci = pci;
6715
Takashi Iwaic187c042007-02-19 15:27:33 +01006716 snd_card_set_dev(card, &pci->dev);
6717
Adrian Knoth0dca1792011-01-26 19:32:14 +01006718 err = snd_hdspm_create(card, hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006719 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006720 snd_card_free(card);
6721 return err;
6722 }
6723
Adrian Knoth0dca1792011-01-26 19:32:14 +01006724 if (hdspm->io_type != MADIface) {
6725 sprintf(card->shortname, "%s_%x",
6726 hdspm->card_name,
Adrian Knoth7d53a632012-01-04 14:31:16 +01006727 hdspm->serial);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006728 sprintf(card->longname, "%s S/N 0x%x at 0x%lx, irq %d",
6729 hdspm->card_name,
Adrian Knoth7d53a632012-01-04 14:31:16 +01006730 hdspm->serial,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006731 hdspm->port, hdspm->irq);
6732 } else {
6733 sprintf(card->shortname, "%s", hdspm->card_name);
6734 sprintf(card->longname, "%s at 0x%lx, irq %d",
6735 hdspm->card_name, hdspm->port, hdspm->irq);
6736 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006737
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006738 err = snd_card_register(card);
6739 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006740 snd_card_free(card);
6741 return err;
6742 }
6743
6744 pci_set_drvdata(pci, card);
6745
6746 dev++;
6747 return 0;
6748}
6749
Bill Pembertone23e7a12012-12-06 12:35:10 -05006750static void snd_hdspm_remove(struct pci_dev *pci)
Takashi Iwai763f3562005-06-03 11:25:34 +02006751{
6752 snd_card_free(pci_get_drvdata(pci));
Takashi Iwai763f3562005-06-03 11:25:34 +02006753}
6754
Takashi Iwaie9f66d92012-04-24 12:25:00 +02006755static struct pci_driver hdspm_driver = {
Takashi Iwai3733e422011-06-10 16:20:20 +02006756 .name = KBUILD_MODNAME,
Takashi Iwai763f3562005-06-03 11:25:34 +02006757 .id_table = snd_hdspm_ids,
6758 .probe = snd_hdspm_probe,
Bill Pembertone23e7a12012-12-06 12:35:10 -05006759 .remove = snd_hdspm_remove,
Takashi Iwai763f3562005-06-03 11:25:34 +02006760};
6761
Takashi Iwaie9f66d92012-04-24 12:25:00 +02006762module_pci_driver(hdspm_driver);