blob: 50cba5ce54fe67d621b7d7c833cfcbeffa853e9e [file] [log] [blame]
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001/*
Takashi Iwai763f3562005-06-03 11:25:34 +02002 * ALSA driver for RME Hammerfall DSP MADI audio interface(s)
3 *
4 * Copyright (c) 2003 Winfried Ritsch (IEM)
5 * code based on hdsp.c Paul Davis
6 * Marcus Andersson
7 * Thomas Charbonnel
Remy Bruno3cee5a62006-10-16 12:46:32 +02008 * Modified 2006-06-01 for AES32 support by Remy Bruno
9 * <remy.bruno@trinnov.com>
Takashi Iwai763f3562005-06-03 11:25:34 +020010 *
Adrian Knoth0dca1792011-01-26 19:32:14 +010011 * Modified 2009-04-13 for proper metering by Florian Faber
12 * <faber@faberman.de>
13 *
14 * Modified 2009-04-14 for native float support by Florian Faber
15 * <faber@faberman.de>
16 *
17 * Modified 2009-04-26 fixed bug in rms metering by Florian Faber
18 * <faber@faberman.de>
19 *
20 * Modified 2009-04-30 added hw serial number support by Florian Faber
21 *
22 * Modified 2011-01-14 added S/PDIF input on RayDATs by Adrian Knoth
23 *
24 * Modified 2011-01-25 variable period sizes on RayDAT/AIO by Adrian Knoth
25 *
Takashi Iwai763f3562005-06-03 11:25:34 +020026 * This program is free software; you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License as published by
28 * the Free Software Foundation; either version 2 of the License, or
29 * (at your option) any later version.
30 *
31 * This program is distributed in the hope that it will be useful,
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 * GNU General Public License for more details.
35 *
36 * You should have received a copy of the GNU General Public License
37 * along with this program; if not, write to the Free Software
38 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 *
40 */
Takashi Iwai763f3562005-06-03 11:25:34 +020041#include <linux/init.h>
42#include <linux/delay.h>
43#include <linux/interrupt.h>
Paul Gortmaker65a77212011-07-15 13:13:37 -040044#include <linux/module.h>
Takashi Iwai763f3562005-06-03 11:25:34 +020045#include <linux/slab.h>
46#include <linux/pci.h>
Takashi Iwai3f7440a2009-06-05 17:40:04 +020047#include <linux/math64.h>
Takashi Iwai763f3562005-06-03 11:25:34 +020048#include <asm/io.h>
49
50#include <sound/core.h>
51#include <sound/control.h>
52#include <sound/pcm.h>
Adrian Knoth0dca1792011-01-26 19:32:14 +010053#include <sound/pcm_params.h>
Takashi Iwai763f3562005-06-03 11:25:34 +020054#include <sound/info.h>
55#include <sound/asoundef.h>
56#include <sound/rawmidi.h>
57#include <sound/hwdep.h>
58#include <sound/initval.h>
59
60#include <sound/hdspm.h>
61
62static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
63static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
Rusty Russella67ff6a2011-12-15 13:49:36 +103064static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
Takashi Iwai763f3562005-06-03 11:25:34 +020065
Takashi Iwai763f3562005-06-03 11:25:34 +020066module_param_array(index, int, NULL, 0444);
67MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");
68
69module_param_array(id, charp, NULL, 0444);
70MODULE_PARM_DESC(id, "ID string for RME HDSPM interface.");
71
72module_param_array(enable, bool, NULL, 0444);
73MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");
74
Takashi Iwai763f3562005-06-03 11:25:34 +020075
76MODULE_AUTHOR
Adrian Knoth0dca1792011-01-26 19:32:14 +010077(
78 "Winfried Ritsch <ritsch_AT_iem.at>, "
79 "Paul Davis <paul@linuxaudiosystems.com>, "
80 "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, "
81 "Remy Bruno <remy.bruno@trinnov.com>, "
82 "Florian Faber <faberman@linuxproaudio.org>, "
83 "Adrian Knoth <adi@drcomp.erfurt.thur.de>"
84);
Takashi Iwai763f3562005-06-03 11:25:34 +020085MODULE_DESCRIPTION("RME HDSPM");
86MODULE_LICENSE("GPL");
87MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
88
Adrian Knoth0dca1792011-01-26 19:32:14 +010089/* --- Write registers. ---
Takashi Iwai763f3562005-06-03 11:25:34 +020090 These are defined as byte-offsets from the iobase value. */
91
Adrian Knoth0dca1792011-01-26 19:32:14 +010092#define HDSPM_WR_SETTINGS 0
93#define HDSPM_outputBufferAddress 32
94#define HDSPM_inputBufferAddress 36
Takashi Iwai763f3562005-06-03 11:25:34 +020095#define HDSPM_controlRegister 64
96#define HDSPM_interruptConfirmation 96
97#define HDSPM_control2Reg 256 /* not in specs ???????? */
Remy Brunoffb2c3c2007-03-07 19:08:46 +010098#define HDSPM_freqReg 256 /* for AES32 */
Adrian Knoth0dca1792011-01-26 19:32:14 +010099#define HDSPM_midiDataOut0 352 /* just believe in old code */
100#define HDSPM_midiDataOut1 356
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100101#define HDSPM_eeprom_wr 384 /* for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200102
103/* DMA enable for 64 channels, only Bit 0 is relevant */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100104#define HDSPM_outputEnableBase 512 /* 512-767 input DMA */
Takashi Iwai763f3562005-06-03 11:25:34 +0200105#define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */
106
Adrian Knoth0dca1792011-01-26 19:32:14 +0100107/* 16 page addresses for each of the 64 channels DMA buffer in and out
Takashi Iwai763f3562005-06-03 11:25:34 +0200108 (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */
109#define HDSPM_pageAddressBufferOut 8192
110#define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4)
111
112#define HDSPM_MADI_mixerBase 32768 /* 32768-65535 for 2x64x64 Fader */
113
114#define HDSPM_MATRIX_MIXER_SIZE 8192 /* = 2*64*64 * 4 Byte => 32kB */
115
116/* --- Read registers. ---
117 These are defined as byte-offsets from the iobase value */
118#define HDSPM_statusRegister 0
Remy Bruno3cee5a62006-10-16 12:46:32 +0200119/*#define HDSPM_statusRegister2 96 */
120/* after RME Windows driver sources, status2 is 4-byte word # 48 = word at
121 * offset 192, for AES32 *and* MADI
122 * => need to check that offset 192 is working on MADI */
123#define HDSPM_statusRegister2 192
124#define HDSPM_timecodeRegister 128
Takashi Iwai763f3562005-06-03 11:25:34 +0200125
Adrian Knoth0dca1792011-01-26 19:32:14 +0100126/* AIO, RayDAT */
127#define HDSPM_RD_STATUS_0 0
128#define HDSPM_RD_STATUS_1 64
129#define HDSPM_RD_STATUS_2 128
130#define HDSPM_RD_STATUS_3 192
131
132#define HDSPM_RD_TCO 256
133#define HDSPM_RD_PLL_FREQ 512
134#define HDSPM_WR_TCO 128
135
136#define HDSPM_TCO1_TCO_lock 0x00000001
137#define HDSPM_TCO1_WCK_Input_Range_LSB 0x00000002
138#define HDSPM_TCO1_WCK_Input_Range_MSB 0x00000004
139#define HDSPM_TCO1_LTC_Input_valid 0x00000008
140#define HDSPM_TCO1_WCK_Input_valid 0x00000010
141#define HDSPM_TCO1_Video_Input_Format_NTSC 0x00000020
142#define HDSPM_TCO1_Video_Input_Format_PAL 0x00000040
143
144#define HDSPM_TCO1_set_TC 0x00000100
145#define HDSPM_TCO1_set_drop_frame_flag 0x00000200
146#define HDSPM_TCO1_LTC_Format_LSB 0x00000400
147#define HDSPM_TCO1_LTC_Format_MSB 0x00000800
148
149#define HDSPM_TCO2_TC_run 0x00010000
150#define HDSPM_TCO2_WCK_IO_ratio_LSB 0x00020000
151#define HDSPM_TCO2_WCK_IO_ratio_MSB 0x00040000
152#define HDSPM_TCO2_set_num_drop_frames_LSB 0x00080000
153#define HDSPM_TCO2_set_num_drop_frames_MSB 0x00100000
154#define HDSPM_TCO2_set_jam_sync 0x00200000
155#define HDSPM_TCO2_set_flywheel 0x00400000
156
157#define HDSPM_TCO2_set_01_4 0x01000000
158#define HDSPM_TCO2_set_pull_down 0x02000000
159#define HDSPM_TCO2_set_pull_up 0x04000000
160#define HDSPM_TCO2_set_freq 0x08000000
161#define HDSPM_TCO2_set_term_75R 0x10000000
162#define HDSPM_TCO2_set_input_LSB 0x20000000
163#define HDSPM_TCO2_set_input_MSB 0x40000000
164#define HDSPM_TCO2_set_freq_from_app 0x80000000
165
166
167#define HDSPM_midiDataOut0 352
168#define HDSPM_midiDataOut1 356
169#define HDSPM_midiDataOut2 368
170
Takashi Iwai763f3562005-06-03 11:25:34 +0200171#define HDSPM_midiDataIn0 360
172#define HDSPM_midiDataIn1 364
Adrian Knoth0dca1792011-01-26 19:32:14 +0100173#define HDSPM_midiDataIn2 372
174#define HDSPM_midiDataIn3 376
Takashi Iwai763f3562005-06-03 11:25:34 +0200175
176/* status is data bytes in MIDI-FIFO (0-128) */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100177#define HDSPM_midiStatusOut0 384
178#define HDSPM_midiStatusOut1 388
179#define HDSPM_midiStatusOut2 400
180
181#define HDSPM_midiStatusIn0 392
182#define HDSPM_midiStatusIn1 396
183#define HDSPM_midiStatusIn2 404
184#define HDSPM_midiStatusIn3 408
Takashi Iwai763f3562005-06-03 11:25:34 +0200185
186
187/* the meters are regular i/o-mapped registers, but offset
188 considerably from the rest. the peak registers are reset
Adrian Knoth0dca1792011-01-26 19:32:14 +0100189 when read; the least-significant 4 bits are full-scale counters;
Takashi Iwai763f3562005-06-03 11:25:34 +0200190 the actual peak value is in the most-significant 24 bits.
191*/
Adrian Knoth0dca1792011-01-26 19:32:14 +0100192
193#define HDSPM_MADI_INPUT_PEAK 4096
194#define HDSPM_MADI_PLAYBACK_PEAK 4352
195#define HDSPM_MADI_OUTPUT_PEAK 4608
196
197#define HDSPM_MADI_INPUT_RMS_L 6144
198#define HDSPM_MADI_PLAYBACK_RMS_L 6400
199#define HDSPM_MADI_OUTPUT_RMS_L 6656
200
201#define HDSPM_MADI_INPUT_RMS_H 7168
202#define HDSPM_MADI_PLAYBACK_RMS_H 7424
203#define HDSPM_MADI_OUTPUT_RMS_H 7680
Takashi Iwai763f3562005-06-03 11:25:34 +0200204
205/* --- Control Register bits --------- */
206#define HDSPM_Start (1<<0) /* start engine */
207
208#define HDSPM_Latency0 (1<<1) /* buffer size = 2^n */
209#define HDSPM_Latency1 (1<<2) /* where n is defined */
210#define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */
211
Adrian Knoth0dca1792011-01-26 19:32:14 +0100212#define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Autosync */
213#define HDSPM_c0Master 0x1 /* Master clock bit in settings
214 register [RayDAT, AIO] */
Takashi Iwai763f3562005-06-03 11:25:34 +0200215
216#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */
217
218#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */
219#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */
220#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200221#define HDSPM_QuadSpeed (1<<31) /* quad speed bit */
Takashi Iwai763f3562005-06-03 11:25:34 +0200222
Remy Bruno3cee5a62006-10-16 12:46:32 +0200223#define HDSPM_Professional (1<<9) /* Professional */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200224#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200225 56channelMODE=0 */ /* MADI ONLY*/
226#define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200227
Adrian Knoth0dca1792011-01-26 19:32:14 +0100228#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200229 0=off, 1=on */ /* MADI ONLY */
230#define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200231
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200232#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax
233 * -- MADI ONLY
234 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200235#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
236
Remy Bruno3cee5a62006-10-16 12:46:32 +0200237#define HDSPM_SyncRef2 (1<<13)
238#define HDSPM_SyncRef3 (1<<25)
Takashi Iwai763f3562005-06-03 11:25:34 +0200239
Remy Bruno3cee5a62006-10-16 12:46:32 +0200240#define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100241#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use
Takashi Iwai763f3562005-06-03 11:25:34 +0200242 AES additional bits in
243 lower 5 Audiodatabits ??? */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200244#define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */
245#define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200246
Adrian Knoth0dca1792011-01-26 19:32:14 +0100247#define HDSPM_Midi0InterruptEnable 0x0400000
248#define HDSPM_Midi1InterruptEnable 0x0800000
249#define HDSPM_Midi2InterruptEnable 0x0200000
250#define HDSPM_Midi3InterruptEnable 0x4000000
Takashi Iwai763f3562005-06-03 11:25:34 +0200251
252#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100253#define HDSPe_FLOAT_FORMAT 0x2000000
Takashi Iwai763f3562005-06-03 11:25:34 +0200254
Remy Bruno3cee5a62006-10-16 12:46:32 +0200255#define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */
256#define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */
257#define HDSPM_QS_QuadWire (1<<28) /* AES32 ONLY */
258
259#define HDSPM_wclk_sel (1<<30)
Takashi Iwai763f3562005-06-03 11:25:34 +0200260
261/* --- bit helper defines */
262#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200263#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|\
264 HDSPM_DoubleSpeed|HDSPM_QuadSpeed)
Takashi Iwai763f3562005-06-03 11:25:34 +0200265#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1)
266#define HDSPM_InputOptical 0
267#define HDSPM_InputCoaxial (HDSPM_InputSelect0)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200268#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\
269 HDSPM_SyncRef2|HDSPM_SyncRef3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200270
Adrian Knoth0dca1792011-01-26 19:32:14 +0100271#define HDSPM_c0_SyncRef0 0x2
272#define HDSPM_c0_SyncRef1 0x4
273#define HDSPM_c0_SyncRef2 0x8
274#define HDSPM_c0_SyncRef3 0x10
275#define HDSPM_c0_SyncRefMask (HDSPM_c0_SyncRef0 | HDSPM_c0_SyncRef1 |\
276 HDSPM_c0_SyncRef2 | HDSPM_c0_SyncRef3)
277
278#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */
279#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */
280#define HDSPM_SYNC_FROM_TCO 2
281#define HDSPM_SYNC_FROM_SYNC_IN 3
Takashi Iwai763f3562005-06-03 11:25:34 +0200282
283#define HDSPM_Frequency32KHz HDSPM_Frequency0
284#define HDSPM_Frequency44_1KHz HDSPM_Frequency1
285#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0)
286#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0)
287#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200288#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|\
289 HDSPM_Frequency0)
Remy Bruno3cee5a62006-10-16 12:46:32 +0200290#define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0)
291#define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200292#define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\
293 HDSPM_Frequency0)
Takashi Iwai763f3562005-06-03 11:25:34 +0200294
Takashi Iwai763f3562005-06-03 11:25:34 +0200295
296/* Synccheck Status */
297#define HDSPM_SYNC_CHECK_NO_LOCK 0
298#define HDSPM_SYNC_CHECK_LOCK 1
299#define HDSPM_SYNC_CHECK_SYNC 2
300
301/* AutoSync References - used by "autosync_ref" control switch */
302#define HDSPM_AUTOSYNC_FROM_WORD 0
303#define HDSPM_AUTOSYNC_FROM_MADI 1
Adrian Knoth0dca1792011-01-26 19:32:14 +0100304#define HDSPM_AUTOSYNC_FROM_TCO 2
305#define HDSPM_AUTOSYNC_FROM_SYNC_IN 3
306#define HDSPM_AUTOSYNC_FROM_NONE 4
Takashi Iwai763f3562005-06-03 11:25:34 +0200307
308/* Possible sources of MADI input */
309#define HDSPM_OPTICAL 0 /* optical */
310#define HDSPM_COAXIAL 1 /* BNC */
311
312#define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask)
Adrian Knoth0dca1792011-01-26 19:32:14 +0100313#define hdspm_decode_latency(x) ((((x) & HDSPM_LatencyMask)>>1))
Takashi Iwai763f3562005-06-03 11:25:34 +0200314
315#define hdspm_encode_in(x) (((x)&0x3)<<14)
316#define hdspm_decode_in(x) (((x)>>14)&0x3)
317
318/* --- control2 register bits --- */
319#define HDSPM_TMS (1<<0)
320#define HDSPM_TCK (1<<1)
321#define HDSPM_TDI (1<<2)
322#define HDSPM_JTAG (1<<3)
323#define HDSPM_PWDN (1<<4)
324#define HDSPM_PROGRAM (1<<5)
325#define HDSPM_CONFIG_MODE_0 (1<<6)
326#define HDSPM_CONFIG_MODE_1 (1<<7)
327/*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/
328#define HDSPM_BIGENDIAN_MODE (1<<9)
329#define HDSPM_RD_MULTIPLE (1<<10)
330
Remy Bruno3cee5a62006-10-16 12:46:32 +0200331/* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200332 that do not conflict with specific bits for AES32 seem to be valid also
333 for the AES32
334 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200335#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200336#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn MODE=0 */
337#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1
338 * (like inp0)
339 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100340
Takashi Iwai763f3562005-06-03 11:25:34 +0200341#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100342#define HDSPM_madiSync (1<<18) /* MADI is in sync */
343
344#define HDSPM_tcoLock 0x00000020 /* Optional TCO locked status FOR HDSPe MADI! */
345#define HDSPM_tcoSync 0x10000000 /* Optional TCO sync status */
346
347#define HDSPM_syncInLock 0x00010000 /* Sync In lock status FOR HDSPe MADI! */
348#define HDSPM_syncInSync 0x00020000 /* Sync In sync status FOR HDSPe MADI! */
Takashi Iwai763f3562005-06-03 11:25:34 +0200349
350#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100351 /* since 64byte accurate, last 6 bits are not used */
Takashi Iwai763f3562005-06-03 11:25:34 +0200352
Adrian Knoth0dca1792011-01-26 19:32:14 +0100353
354
Takashi Iwai763f3562005-06-03 11:25:34 +0200355#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */
356
357#define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */
358#define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */
359#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */
360#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */
361
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200362#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with
363 * Interrupt
364 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100365#define HDSPM_tco_detect 0x08000000
366#define HDSPM_tco_lock 0x20000000
367
368#define HDSPM_s2_tco_detect 0x00000040
369#define HDSPM_s2_AEBO_D 0x00000080
370#define HDSPM_s2_AEBI_D 0x00000100
371
372
373#define HDSPM_midi0IRQPending 0x40000000
374#define HDSPM_midi1IRQPending 0x80000000
375#define HDSPM_midi2IRQPending 0x20000000
376#define HDSPM_midi2IRQPendingAES 0x00000020
377#define HDSPM_midi3IRQPending 0x00200000
Takashi Iwai763f3562005-06-03 11:25:34 +0200378
379/* --- status bit helpers */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200380#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\
381 HDSPM_madiFreq2|HDSPM_madiFreq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200382#define HDSPM_madiFreq32 (HDSPM_madiFreq0)
383#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1)
384#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1)
385#define HDSPM_madiFreq64 (HDSPM_madiFreq2)
386#define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2)
387#define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2)
388#define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2)
389#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
390#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0)
391
Remy Bruno3cee5a62006-10-16 12:46:32 +0200392/* Status2 Register bits */ /* MADI ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200393
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300394#define HDSPM_version0 (1<<0) /* not really defined but I guess */
Takashi Iwai763f3562005-06-03 11:25:34 +0200395#define HDSPM_version1 (1<<1) /* in former cards it was ??? */
396#define HDSPM_version2 (1<<2)
397
398#define HDSPM_wcLock (1<<3) /* Wordclock is detected and locked */
399#define HDSPM_wcSync (1<<4) /* Wordclock is in sync with systemclock */
400
401#define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */
402#define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */
403#define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, */
404/* missing Bit for 111=128, 1000=176.4, 1001=192 */
405
Adrian Knoth0dca1792011-01-26 19:32:14 +0100406#define HDSPM_SyncRef0 0x10000 /* Sync Reference */
407#define HDSPM_SyncRef1 0x20000
408
409#define HDSPM_SelSyncRef0 (1<<8) /* AutoSync Source */
Takashi Iwai763f3562005-06-03 11:25:34 +0200410#define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */
411#define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */
412
413#define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync)
414
415#define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2)
416#define HDSPM_wcFreq32 (HDSPM_wc_freq0)
417#define HDSPM_wcFreq44_1 (HDSPM_wc_freq1)
418#define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1)
419#define HDSPM_wcFreq64 (HDSPM_wc_freq2)
420#define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2)
421#define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2)
422
Adrian Knoth0dca1792011-01-26 19:32:14 +0100423#define HDSPM_status1_F_0 0x0400000
424#define HDSPM_status1_F_1 0x0800000
425#define HDSPM_status1_F_2 0x1000000
426#define HDSPM_status1_F_3 0x2000000
427#define HDSPM_status1_freqMask (HDSPM_status1_F_0|HDSPM_status1_F_1|HDSPM_status1_F_2|HDSPM_status1_F_3)
428
Takashi Iwai763f3562005-06-03 11:25:34 +0200429
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200430#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
431 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200432#define HDSPM_SelSyncRef_WORD 0
433#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0)
Adrian Knoth0dca1792011-01-26 19:32:14 +0100434#define HDSPM_SelSyncRef_TCO (HDSPM_SelSyncRef1)
435#define HDSPM_SelSyncRef_SyncIn (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200436#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
437 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200438
Remy Bruno3cee5a62006-10-16 12:46:32 +0200439/*
440 For AES32, bits for status, status2 and timecode are different
441*/
442/* status */
443#define HDSPM_AES32_wcLock 0x0200000
Andre Schramm56bde0f2013-01-09 14:40:18 +0100444#define HDSPM_AES32_wcSync 0x0100000
Remy Bruno3cee5a62006-10-16 12:46:32 +0200445#define HDSPM_AES32_wcFreq_bit 22
Adrian Knoth0dca1792011-01-26 19:32:14 +0100446/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function
Remy Bruno3cee5a62006-10-16 12:46:32 +0200447 HDSPM_bit2freq */
448#define HDSPM_AES32_syncref_bit 16
449/* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */
450
451#define HDSPM_AES32_AUTOSYNC_FROM_WORD 0
452#define HDSPM_AES32_AUTOSYNC_FROM_AES1 1
453#define HDSPM_AES32_AUTOSYNC_FROM_AES2 2
454#define HDSPM_AES32_AUTOSYNC_FROM_AES3 3
455#define HDSPM_AES32_AUTOSYNC_FROM_AES4 4
456#define HDSPM_AES32_AUTOSYNC_FROM_AES5 5
457#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6
458#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7
459#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8
Remy Bruno65345992007-08-31 12:21:08 +0200460#define HDSPM_AES32_AUTOSYNC_FROM_NONE 9
Remy Bruno3cee5a62006-10-16 12:46:32 +0200461
462/* status2 */
463/* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */
464#define HDSPM_LockAES 0x80
465#define HDSPM_LockAES1 0x80
466#define HDSPM_LockAES2 0x40
467#define HDSPM_LockAES3 0x20
468#define HDSPM_LockAES4 0x10
469#define HDSPM_LockAES5 0x8
470#define HDSPM_LockAES6 0x4
471#define HDSPM_LockAES7 0x2
472#define HDSPM_LockAES8 0x1
473/*
474 Timecode
475 After windows driver sources, bits 4*i to 4*i+3 give the input frequency on
476 AES i+1
477 bits 3210
478 0001 32kHz
479 0010 44.1kHz
480 0011 48kHz
481 0100 64kHz
482 0101 88.2kHz
483 0110 96kHz
484 0111 128kHz
485 1000 176.4kHz
486 1001 192kHz
487 NB: Timecode register doesn't seem to work on AES32 card revision 230
488*/
489
Takashi Iwai763f3562005-06-03 11:25:34 +0200490/* Mixer Values */
491#define UNITY_GAIN 32768 /* = 65536/2 */
492#define MINUS_INFINITY_GAIN 0
493
Takashi Iwai763f3562005-06-03 11:25:34 +0200494/* Number of channels for different Speed Modes */
495#define MADI_SS_CHANNELS 64
496#define MADI_DS_CHANNELS 32
497#define MADI_QS_CHANNELS 16
498
Adrian Knoth0dca1792011-01-26 19:32:14 +0100499#define RAYDAT_SS_CHANNELS 36
500#define RAYDAT_DS_CHANNELS 20
501#define RAYDAT_QS_CHANNELS 12
502
503#define AIO_IN_SS_CHANNELS 14
504#define AIO_IN_DS_CHANNELS 10
505#define AIO_IN_QS_CHANNELS 8
506#define AIO_OUT_SS_CHANNELS 16
507#define AIO_OUT_DS_CHANNELS 12
508#define AIO_OUT_QS_CHANNELS 10
509
Adrian Knothd2d10a22011-02-28 15:14:47 +0100510#define AES32_CHANNELS 16
511
Takashi Iwai763f3562005-06-03 11:25:34 +0200512/* the size of a substream (1 mono data stream) */
513#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024)
514#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
515
516/* the size of the area we need to allocate for DMA transfers. the
517 size is the same regardless of the number of channels, and
Adrian Knoth0dca1792011-01-26 19:32:14 +0100518 also the latency to use.
Takashi Iwai763f3562005-06-03 11:25:34 +0200519 for one direction !!!
520*/
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100521#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
Takashi Iwai763f3562005-06-03 11:25:34 +0200522#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
523
Adrian Knoth0dca1792011-01-26 19:32:14 +0100524#define HDSPM_RAYDAT_REV 211
525#define HDSPM_AIO_REV 212
526#define HDSPM_MADIFACE_REV 213
Remy Bruno3cee5a62006-10-16 12:46:32 +0200527
Remy Bruno65345992007-08-31 12:21:08 +0200528/* speed factor modes */
529#define HDSPM_SPEED_SINGLE 0
530#define HDSPM_SPEED_DOUBLE 1
531#define HDSPM_SPEED_QUAD 2
Adrian Knoth0dca1792011-01-26 19:32:14 +0100532
Remy Bruno65345992007-08-31 12:21:08 +0200533/* names for speed modes */
534static char *hdspm_speed_names[] = { "single", "double", "quad" };
535
Adrian Knoth0dca1792011-01-26 19:32:14 +0100536static char *texts_autosync_aes_tco[] = { "Word Clock",
537 "AES1", "AES2", "AES3", "AES4",
538 "AES5", "AES6", "AES7", "AES8",
539 "TCO" };
540static char *texts_autosync_aes[] = { "Word Clock",
541 "AES1", "AES2", "AES3", "AES4",
542 "AES5", "AES6", "AES7", "AES8" };
543static char *texts_autosync_madi_tco[] = { "Word Clock",
544 "MADI", "TCO", "Sync In" };
545static char *texts_autosync_madi[] = { "Word Clock",
546 "MADI", "Sync In" };
547
548static char *texts_autosync_raydat_tco[] = {
549 "Word Clock",
550 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
551 "AES", "SPDIF", "TCO", "Sync In"
552};
553static char *texts_autosync_raydat[] = {
554 "Word Clock",
555 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
556 "AES", "SPDIF", "Sync In"
557};
558static char *texts_autosync_aio_tco[] = {
559 "Word Clock",
560 "ADAT", "AES", "SPDIF", "TCO", "Sync In"
561};
562static char *texts_autosync_aio[] = { "Word Clock",
563 "ADAT", "AES", "SPDIF", "Sync In" };
564
565static char *texts_freq[] = {
566 "No Lock",
567 "32 kHz",
568 "44.1 kHz",
569 "48 kHz",
570 "64 kHz",
571 "88.2 kHz",
572 "96 kHz",
573 "128 kHz",
574 "176.4 kHz",
575 "192 kHz"
576};
577
Adrian Knoth0dca1792011-01-26 19:32:14 +0100578static char *texts_ports_madi[] = {
579 "MADI.1", "MADI.2", "MADI.3", "MADI.4", "MADI.5", "MADI.6",
580 "MADI.7", "MADI.8", "MADI.9", "MADI.10", "MADI.11", "MADI.12",
581 "MADI.13", "MADI.14", "MADI.15", "MADI.16", "MADI.17", "MADI.18",
582 "MADI.19", "MADI.20", "MADI.21", "MADI.22", "MADI.23", "MADI.24",
583 "MADI.25", "MADI.26", "MADI.27", "MADI.28", "MADI.29", "MADI.30",
584 "MADI.31", "MADI.32", "MADI.33", "MADI.34", "MADI.35", "MADI.36",
585 "MADI.37", "MADI.38", "MADI.39", "MADI.40", "MADI.41", "MADI.42",
586 "MADI.43", "MADI.44", "MADI.45", "MADI.46", "MADI.47", "MADI.48",
587 "MADI.49", "MADI.50", "MADI.51", "MADI.52", "MADI.53", "MADI.54",
588 "MADI.55", "MADI.56", "MADI.57", "MADI.58", "MADI.59", "MADI.60",
589 "MADI.61", "MADI.62", "MADI.63", "MADI.64",
590};
591
592
593static char *texts_ports_raydat_ss[] = {
594 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT1.5", "ADAT1.6",
595 "ADAT1.7", "ADAT1.8", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
596 "ADAT2.5", "ADAT2.6", "ADAT2.7", "ADAT2.8", "ADAT3.1", "ADAT3.2",
597 "ADAT3.3", "ADAT3.4", "ADAT3.5", "ADAT3.6", "ADAT3.7", "ADAT3.8",
598 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4", "ADAT4.5", "ADAT4.6",
599 "ADAT4.7", "ADAT4.8",
600 "AES.L", "AES.R",
601 "SPDIF.L", "SPDIF.R"
602};
603
604static char *texts_ports_raydat_ds[] = {
605 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4",
606 "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
607 "ADAT3.1", "ADAT3.2", "ADAT3.3", "ADAT3.4",
608 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4",
609 "AES.L", "AES.R",
610 "SPDIF.L", "SPDIF.R"
611};
612
613static char *texts_ports_raydat_qs[] = {
614 "ADAT1.1", "ADAT1.2",
615 "ADAT2.1", "ADAT2.2",
616 "ADAT3.1", "ADAT3.2",
617 "ADAT4.1", "ADAT4.2",
618 "AES.L", "AES.R",
619 "SPDIF.L", "SPDIF.R"
620};
621
622
623static char *texts_ports_aio_in_ss[] = {
624 "Analogue.L", "Analogue.R",
625 "AES.L", "AES.R",
626 "SPDIF.L", "SPDIF.R",
627 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
628 "ADAT.7", "ADAT.8"
629};
630
631static char *texts_ports_aio_out_ss[] = {
632 "Analogue.L", "Analogue.R",
633 "AES.L", "AES.R",
634 "SPDIF.L", "SPDIF.R",
635 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
636 "ADAT.7", "ADAT.8",
637 "Phone.L", "Phone.R"
638};
639
640static char *texts_ports_aio_in_ds[] = {
641 "Analogue.L", "Analogue.R",
642 "AES.L", "AES.R",
643 "SPDIF.L", "SPDIF.R",
644 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
645};
646
647static char *texts_ports_aio_out_ds[] = {
648 "Analogue.L", "Analogue.R",
649 "AES.L", "AES.R",
650 "SPDIF.L", "SPDIF.R",
651 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
652 "Phone.L", "Phone.R"
653};
654
655static char *texts_ports_aio_in_qs[] = {
656 "Analogue.L", "Analogue.R",
657 "AES.L", "AES.R",
658 "SPDIF.L", "SPDIF.R",
659 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
660};
661
662static char *texts_ports_aio_out_qs[] = {
663 "Analogue.L", "Analogue.R",
664 "AES.L", "AES.R",
665 "SPDIF.L", "SPDIF.R",
666 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
667 "Phone.L", "Phone.R"
668};
669
Adrian Knoth432d2502011-02-23 11:43:08 +0100670static char *texts_ports_aes32[] = {
671 "AES.1", "AES.2", "AES.3", "AES.4", "AES.5", "AES.6", "AES.7",
672 "AES.8", "AES.9.", "AES.10", "AES.11", "AES.12", "AES.13", "AES.14",
673 "AES.15", "AES.16"
674};
675
Adrian Knoth55a57602011-01-27 11:23:15 +0100676/* These tables map the ALSA channels 1..N to the channels that we
677 need to use in order to find the relevant channel buffer. RME
678 refers to this kind of mapping as between "the ADAT channel and
679 the DMA channel." We index it using the logical audio channel,
680 and the value is the DMA channel (i.e. channel buffer number)
681 where the data for that channel can be read/written from/to.
682*/
683
684static char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = {
685 0, 1, 2, 3, 4, 5, 6, 7,
686 8, 9, 10, 11, 12, 13, 14, 15,
687 16, 17, 18, 19, 20, 21, 22, 23,
688 24, 25, 26, 27, 28, 29, 30, 31,
689 32, 33, 34, 35, 36, 37, 38, 39,
690 40, 41, 42, 43, 44, 45, 46, 47,
691 48, 49, 50, 51, 52, 53, 54, 55,
692 56, 57, 58, 59, 60, 61, 62, 63
693};
694
Adrian Knoth55a57602011-01-27 11:23:15 +0100695static char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = {
696 4, 5, 6, 7, 8, 9, 10, 11, /* ADAT 1 */
697 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT 2 */
698 20, 21, 22, 23, 24, 25, 26, 27, /* ADAT 3 */
699 28, 29, 30, 31, 32, 33, 34, 35, /* ADAT 4 */
700 0, 1, /* AES */
701 2, 3, /* SPDIF */
702 -1, -1, -1, -1,
703 -1, -1, -1, -1, -1, -1, -1, -1,
704 -1, -1, -1, -1, -1, -1, -1, -1,
705 -1, -1, -1, -1, -1, -1, -1, -1,
706};
707
708static char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = {
709 4, 5, 6, 7, /* ADAT 1 */
710 8, 9, 10, 11, /* ADAT 2 */
711 12, 13, 14, 15, /* ADAT 3 */
712 16, 17, 18, 19, /* ADAT 4 */
713 0, 1, /* AES */
714 2, 3, /* SPDIF */
715 -1, -1, -1, -1,
716 -1, -1, -1, -1, -1, -1, -1, -1,
717 -1, -1, -1, -1, -1, -1, -1, -1,
718 -1, -1, -1, -1, -1, -1, -1, -1,
719 -1, -1, -1, -1, -1, -1, -1, -1,
720 -1, -1, -1, -1, -1, -1, -1, -1,
721};
722
723static char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = {
724 4, 5, /* ADAT 1 */
725 6, 7, /* ADAT 2 */
726 8, 9, /* ADAT 3 */
727 10, 11, /* ADAT 4 */
728 0, 1, /* AES */
729 2, 3, /* SPDIF */
730 -1, -1, -1, -1,
731 -1, -1, -1, -1, -1, -1, -1, -1,
732 -1, -1, -1, -1, -1, -1, -1, -1,
733 -1, -1, -1, -1, -1, -1, -1, -1,
734 -1, -1, -1, -1, -1, -1, -1, -1,
735 -1, -1, -1, -1, -1, -1, -1, -1,
736 -1, -1, -1, -1, -1, -1, -1, -1,
737};
738
739static char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = {
740 0, 1, /* line in */
741 8, 9, /* aes in, */
742 10, 11, /* spdif in */
743 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT in */
744 -1, -1,
745 -1, -1, -1, -1, -1, -1, -1, -1,
746 -1, -1, -1, -1, -1, -1, -1, -1,
747 -1, -1, -1, -1, -1, -1, -1, -1,
748 -1, -1, -1, -1, -1, -1, -1, -1,
749 -1, -1, -1, -1, -1, -1, -1, -1,
750 -1, -1, -1, -1, -1, -1, -1, -1,
751};
752
753static char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = {
754 0, 1, /* line out */
755 8, 9, /* aes out */
756 10, 11, /* spdif out */
757 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT out */
758 6, 7, /* phone out */
759 -1, -1, -1, -1, -1, -1, -1, -1,
760 -1, -1, -1, -1, -1, -1, -1, -1,
761 -1, -1, -1, -1, -1, -1, -1, -1,
762 -1, -1, -1, -1, -1, -1, -1, -1,
763 -1, -1, -1, -1, -1, -1, -1, -1,
764 -1, -1, -1, -1, -1, -1, -1, -1,
765};
766
767static char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = {
768 0, 1, /* line in */
769 8, 9, /* aes in */
770 10, 11, /* spdif in */
771 12, 14, 16, 18, /* adat in */
772 -1, -1, -1, -1, -1, -1,
773 -1, -1, -1, -1, -1, -1, -1, -1,
774 -1, -1, -1, -1, -1, -1, -1, -1,
775 -1, -1, -1, -1, -1, -1, -1, -1,
776 -1, -1, -1, -1, -1, -1, -1, -1,
777 -1, -1, -1, -1, -1, -1, -1, -1,
778 -1, -1, -1, -1, -1, -1, -1, -1
779};
780
781static char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = {
782 0, 1, /* line out */
783 8, 9, /* aes out */
784 10, 11, /* spdif out */
785 12, 14, 16, 18, /* adat out */
786 6, 7, /* phone out */
787 -1, -1, -1, -1,
788 -1, -1, -1, -1, -1, -1, -1, -1,
789 -1, -1, -1, -1, -1, -1, -1, -1,
790 -1, -1, -1, -1, -1, -1, -1, -1,
791 -1, -1, -1, -1, -1, -1, -1, -1,
792 -1, -1, -1, -1, -1, -1, -1, -1,
793 -1, -1, -1, -1, -1, -1, -1, -1
794};
795
796static char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = {
797 0, 1, /* line in */
798 8, 9, /* aes in */
799 10, 11, /* spdif in */
800 12, 16, /* adat in */
801 -1, -1, -1, -1, -1, -1, -1, -1,
802 -1, -1, -1, -1, -1, -1, -1, -1,
803 -1, -1, -1, -1, -1, -1, -1, -1,
804 -1, -1, -1, -1, -1, -1, -1, -1,
805 -1, -1, -1, -1, -1, -1, -1, -1,
806 -1, -1, -1, -1, -1, -1, -1, -1,
807 -1, -1, -1, -1, -1, -1, -1, -1
808};
809
810static char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = {
811 0, 1, /* line out */
812 8, 9, /* aes out */
813 10, 11, /* spdif out */
814 12, 16, /* adat out */
815 6, 7, /* phone out */
816 -1, -1, -1, -1, -1, -1,
817 -1, -1, -1, -1, -1, -1, -1, -1,
818 -1, -1, -1, -1, -1, -1, -1, -1,
819 -1, -1, -1, -1, -1, -1, -1, -1,
820 -1, -1, -1, -1, -1, -1, -1, -1,
821 -1, -1, -1, -1, -1, -1, -1, -1,
822 -1, -1, -1, -1, -1, -1, -1, -1
823};
824
Adrian Knoth432d2502011-02-23 11:43:08 +0100825static char channel_map_aes32[HDSPM_MAX_CHANNELS] = {
826 0, 1, 2, 3, 4, 5, 6, 7,
827 8, 9, 10, 11, 12, 13, 14, 15,
828 -1, -1, -1, -1, -1, -1, -1, -1,
829 -1, -1, -1, -1, -1, -1, -1, -1,
830 -1, -1, -1, -1, -1, -1, -1, -1,
831 -1, -1, -1, -1, -1, -1, -1, -1,
832 -1, -1, -1, -1, -1, -1, -1, -1,
833 -1, -1, -1, -1, -1, -1, -1, -1
834};
835
Takashi Iwai98274f02005-11-17 14:52:34 +0100836struct hdspm_midi {
837 struct hdspm *hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +0200838 int id;
Takashi Iwai98274f02005-11-17 14:52:34 +0100839 struct snd_rawmidi *rmidi;
840 struct snd_rawmidi_substream *input;
841 struct snd_rawmidi_substream *output;
Takashi Iwai763f3562005-06-03 11:25:34 +0200842 char istimer; /* timer in use */
843 struct timer_list timer;
844 spinlock_t lock;
845 int pending;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100846 int dataIn;
847 int statusIn;
848 int dataOut;
849 int statusOut;
850 int ie;
851 int irq;
852};
853
854struct hdspm_tco {
855 int input;
856 int framerate;
857 int wordclock;
858 int samplerate;
859 int pull;
860 int term; /* 0 = off, 1 = on */
Takashi Iwai763f3562005-06-03 11:25:34 +0200861};
862
Takashi Iwai98274f02005-11-17 14:52:34 +0100863struct hdspm {
Takashi Iwai763f3562005-06-03 11:25:34 +0200864 spinlock_t lock;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200865 /* only one playback and/or capture stream */
866 struct snd_pcm_substream *capture_substream;
867 struct snd_pcm_substream *playback_substream;
Takashi Iwai763f3562005-06-03 11:25:34 +0200868
869 char *card_name; /* for procinfo */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200870 unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
871
Adrian Knoth0dca1792011-01-26 19:32:14 +0100872 uint8_t io_type;
Takashi Iwai763f3562005-06-03 11:25:34 +0200873
Takashi Iwai763f3562005-06-03 11:25:34 +0200874 int monitor_outs; /* set up monitoring outs init flag */
875
876 u32 control_register; /* cached value */
877 u32 control2_register; /* cached value */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100878 u32 settings_register;
Takashi Iwai763f3562005-06-03 11:25:34 +0200879
Adrian Knoth0dca1792011-01-26 19:32:14 +0100880 struct hdspm_midi midi[4];
Takashi Iwai763f3562005-06-03 11:25:34 +0200881 struct tasklet_struct midi_tasklet;
882
883 size_t period_bytes;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100884 unsigned char ss_in_channels;
885 unsigned char ds_in_channels;
886 unsigned char qs_in_channels;
887 unsigned char ss_out_channels;
888 unsigned char ds_out_channels;
889 unsigned char qs_out_channels;
890
891 unsigned char max_channels_in;
892 unsigned char max_channels_out;
893
Takashi Iwai286bed02011-06-30 12:45:36 +0200894 signed char *channel_map_in;
895 signed char *channel_map_out;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100896
Takashi Iwai286bed02011-06-30 12:45:36 +0200897 signed char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs;
898 signed char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100899
900 char **port_names_in;
901 char **port_names_out;
902
903 char **port_names_in_ss, **port_names_in_ds, **port_names_in_qs;
904 char **port_names_out_ss, **port_names_out_ds, **port_names_out_qs;
Takashi Iwai763f3562005-06-03 11:25:34 +0200905
906 unsigned char *playback_buffer; /* suitably aligned address */
907 unsigned char *capture_buffer; /* suitably aligned address */
908
909 pid_t capture_pid; /* process id which uses capture */
910 pid_t playback_pid; /* process id which uses capture */
911 int running; /* running status */
912
913 int last_external_sample_rate; /* samplerate mystic ... */
914 int last_internal_sample_rate;
915 int system_sample_rate;
916
Takashi Iwai763f3562005-06-03 11:25:34 +0200917 int dev; /* Hardware vars... */
918 int irq;
919 unsigned long port;
920 void __iomem *iobase;
921
922 int irq_count; /* for debug */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100923 int midiPorts;
Takashi Iwai763f3562005-06-03 11:25:34 +0200924
Takashi Iwai98274f02005-11-17 14:52:34 +0100925 struct snd_card *card; /* one card */
926 struct snd_pcm *pcm; /* has one pcm */
927 struct snd_hwdep *hwdep; /* and a hwdep for additional ioctl */
Takashi Iwai763f3562005-06-03 11:25:34 +0200928 struct pci_dev *pci; /* and an pci info */
929
930 /* Mixer vars */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200931 /* fast alsa mixer */
932 struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS];
933 /* but input to much, so not used */
934 struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS];
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300935 /* full mixer accessible over mixer ioctl or hwdep-device */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200936 struct hdspm_mixer *mixer;
Takashi Iwai763f3562005-06-03 11:25:34 +0200937
Adrian Knoth0dca1792011-01-26 19:32:14 +0100938 struct hdspm_tco *tco; /* NULL if no TCO detected */
Takashi Iwai763f3562005-06-03 11:25:34 +0200939
Adrian Knoth0dca1792011-01-26 19:32:14 +0100940 char **texts_autosync;
941 int texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +0200942
Adrian Knoth0dca1792011-01-26 19:32:14 +0100943 cycles_t last_interrupt;
Jaroslav Kysela730a5862011-01-27 13:03:15 +0100944
Adrian Knoth7d53a632012-01-04 14:31:16 +0100945 unsigned int serial;
946
Jaroslav Kysela730a5862011-01-27 13:03:15 +0100947 struct hdspm_peak_rms peak_rms;
Takashi Iwai763f3562005-06-03 11:25:34 +0200948};
949
Takashi Iwai763f3562005-06-03 11:25:34 +0200950
Alexey Dobriyancebe41d2010-02-06 00:21:03 +0200951static DEFINE_PCI_DEVICE_TABLE(snd_hdspm_ids) = {
Takashi Iwai763f3562005-06-03 11:25:34 +0200952 {
953 .vendor = PCI_VENDOR_ID_XILINX,
954 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
955 .subvendor = PCI_ANY_ID,
956 .subdevice = PCI_ANY_ID,
957 .class = 0,
958 .class_mask = 0,
959 .driver_data = 0},
960 {0,}
961};
962
963MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
964
965/* prototypes */
Bill Pembertone23e7a12012-12-06 12:35:10 -0500966static int snd_hdspm_create_alsa_devices(struct snd_card *card,
967 struct hdspm *hdspm);
968static int snd_hdspm_create_pcm(struct snd_card *card,
969 struct hdspm *hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +0200970
Adrian Knoth0dca1792011-01-26 19:32:14 +0100971static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
Adrian Knoth3f7bf912013-03-10 00:37:21 +0100972static inline int hdspm_get_pll_freq(struct hdspm *hdspm);
Adrian Knoth0dca1792011-01-26 19:32:14 +0100973static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
974static int hdspm_autosync_ref(struct hdspm *hdspm);
975static int snd_hdspm_set_defaults(struct hdspm *hdspm);
Adrian Knoth21a164d2012-10-19 17:42:23 +0200976static int hdspm_system_clock_mode(struct hdspm *hdspm);
Adrian Knoth0dca1792011-01-26 19:32:14 +0100977static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +0200978 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +0200979 unsigned int reg, int channels);
980
Remy Bruno3cee5a62006-10-16 12:46:32 +0200981static inline int HDSPM_bit2freq(int n)
982{
Denys Vlasenko62cef822008-04-14 13:04:18 +0200983 static const int bit2freq_tab[] = {
984 0, 32000, 44100, 48000, 64000, 88200,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200985 96000, 128000, 176400, 192000 };
986 if (n < 1 || n > 9)
987 return 0;
988 return bit2freq_tab[n];
989}
990
Adrian Knoth0dca1792011-01-26 19:32:14 +0100991/* Write/read to/from HDSPM with Adresses in Bytes
Takashi Iwai763f3562005-06-03 11:25:34 +0200992 not words but only 32Bit writes are allowed */
993
Takashi Iwai98274f02005-11-17 14:52:34 +0100994static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
Takashi Iwai763f3562005-06-03 11:25:34 +0200995 unsigned int val)
996{
997 writel(val, hdspm->iobase + reg);
998}
999
Takashi Iwai98274f02005-11-17 14:52:34 +01001000static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
Takashi Iwai763f3562005-06-03 11:25:34 +02001001{
1002 return readl(hdspm->iobase + reg);
1003}
1004
Adrian Knoth0dca1792011-01-26 19:32:14 +01001005/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
1006 mixer is write only on hardware so we have to cache him for read
Takashi Iwai763f3562005-06-03 11:25:34 +02001007 each fader is a u32, but uses only the first 16 bit */
1008
Takashi Iwai98274f02005-11-17 14:52:34 +01001009static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001010 unsigned int in)
1011{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001012 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001013 return 0;
1014
1015 return hdspm->mixer->ch[chan].in[in];
1016}
1017
Takashi Iwai98274f02005-11-17 14:52:34 +01001018static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001019 unsigned int pb)
1020{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001021 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001022 return 0;
1023 return hdspm->mixer->ch[chan].pb[pb];
1024}
1025
Denys Vlasenko62cef822008-04-14 13:04:18 +02001026static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001027 unsigned int in, unsigned short data)
1028{
1029 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
1030 return -1;
1031
1032 hdspm_write(hdspm,
1033 HDSPM_MADI_mixerBase +
1034 ((in + 128 * chan) * sizeof(u32)),
1035 (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
1036 return 0;
1037}
1038
Denys Vlasenko62cef822008-04-14 13:04:18 +02001039static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001040 unsigned int pb, unsigned short data)
1041{
1042 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
1043 return -1;
1044
1045 hdspm_write(hdspm,
1046 HDSPM_MADI_mixerBase +
1047 ((64 + pb + 128 * chan) * sizeof(u32)),
1048 (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
1049 return 0;
1050}
1051
1052
1053/* enable DMA for specific channels, now available for DSP-MADI */
Takashi Iwai98274f02005-11-17 14:52:34 +01001054static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001055{
1056 hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
1057}
1058
Takashi Iwai98274f02005-11-17 14:52:34 +01001059static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001060{
1061 hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
1062}
1063
1064/* check if same process is writing and reading */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001065static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001066{
1067 unsigned long flags;
1068 int ret = 1;
1069
1070 spin_lock_irqsave(&hdspm->lock, flags);
1071 if ((hdspm->playback_pid != hdspm->capture_pid) &&
1072 (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
1073 ret = 0;
1074 }
1075 spin_unlock_irqrestore(&hdspm->lock, flags);
1076 return ret;
1077}
1078
1079/* check for external sample rate */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001080static int hdspm_external_sample_rate(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001081{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001082 unsigned int status, status2, timecode;
1083 int syncref, rate = 0, rate_bits;
Takashi Iwai763f3562005-06-03 11:25:34 +02001084
Adrian Knoth0dca1792011-01-26 19:32:14 +01001085 switch (hdspm->io_type) {
1086 case AES32:
1087 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1088 status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01001089 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001090
1091 syncref = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001092
Remy Bruno3cee5a62006-10-16 12:46:32 +02001093 if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD &&
1094 status & HDSPM_AES32_wcLock)
Adrian Knoth0dca1792011-01-26 19:32:14 +01001095 return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF);
1096
Remy Bruno3cee5a62006-10-16 12:46:32 +02001097 if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001098 syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
1099 status2 & (HDSPM_LockAES >>
1100 (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1)))
1101 return HDSPM_bit2freq((timecode >> (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF);
Remy Bruno3cee5a62006-10-16 12:46:32 +02001102 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001103 break;
1104
1105 case MADIface:
1106 status = hdspm_read(hdspm, HDSPM_statusRegister);
1107
1108 if (!(status & HDSPM_madiLock)) {
1109 rate = 0; /* no lock */
1110 } else {
1111 switch (status & (HDSPM_status1_freqMask)) {
1112 case HDSPM_status1_F_0*1:
1113 rate = 32000; break;
1114 case HDSPM_status1_F_0*2:
1115 rate = 44100; break;
1116 case HDSPM_status1_F_0*3:
1117 rate = 48000; break;
1118 case HDSPM_status1_F_0*4:
1119 rate = 64000; break;
1120 case HDSPM_status1_F_0*5:
1121 rate = 88200; break;
1122 case HDSPM_status1_F_0*6:
1123 rate = 96000; break;
1124 case HDSPM_status1_F_0*7:
1125 rate = 128000; break;
1126 case HDSPM_status1_F_0*8:
1127 rate = 176400; break;
1128 case HDSPM_status1_F_0*9:
1129 rate = 192000; break;
1130 default:
1131 rate = 0; break;
1132 }
1133 }
1134
1135 break;
1136
1137 case MADI:
1138 case AIO:
1139 case RayDAT:
1140 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1141 status = hdspm_read(hdspm, HDSPM_statusRegister);
1142 rate = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02001143
Remy Bruno3cee5a62006-10-16 12:46:32 +02001144 /* if wordclock has synced freq and wordclock is valid */
1145 if ((status2 & HDSPM_wcLock) != 0 &&
Adrian Knothfedf1532011-06-12 17:26:18 +02001146 (status2 & HDSPM_SelSyncRef0) == 0) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02001147
1148 rate_bits = status2 & HDSPM_wcFreqMask;
1149
Adrian Knoth0dca1792011-01-26 19:32:14 +01001150
Remy Bruno3cee5a62006-10-16 12:46:32 +02001151 switch (rate_bits) {
1152 case HDSPM_wcFreq32:
1153 rate = 32000;
1154 break;
1155 case HDSPM_wcFreq44_1:
1156 rate = 44100;
1157 break;
1158 case HDSPM_wcFreq48:
1159 rate = 48000;
1160 break;
1161 case HDSPM_wcFreq64:
1162 rate = 64000;
1163 break;
1164 case HDSPM_wcFreq88_2:
1165 rate = 88200;
1166 break;
1167 case HDSPM_wcFreq96:
1168 rate = 96000;
1169 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001170 default:
1171 rate = 0;
1172 break;
1173 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001174 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001175
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001176 /* if rate detected and Syncref is Word than have it,
1177 * word has priority to MADI
1178 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001179 if (rate != 0 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001180 (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
Remy Bruno3cee5a62006-10-16 12:46:32 +02001181 return rate;
1182
Adrian Knoth0dca1792011-01-26 19:32:14 +01001183 /* maybe a madi input (which is taken if sel sync is madi) */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001184 if (status & HDSPM_madiLock) {
1185 rate_bits = status & HDSPM_madiFreqMask;
1186
1187 switch (rate_bits) {
1188 case HDSPM_madiFreq32:
1189 rate = 32000;
1190 break;
1191 case HDSPM_madiFreq44_1:
1192 rate = 44100;
1193 break;
1194 case HDSPM_madiFreq48:
1195 rate = 48000;
1196 break;
1197 case HDSPM_madiFreq64:
1198 rate = 64000;
1199 break;
1200 case HDSPM_madiFreq88_2:
1201 rate = 88200;
1202 break;
1203 case HDSPM_madiFreq96:
1204 rate = 96000;
1205 break;
1206 case HDSPM_madiFreq128:
1207 rate = 128000;
1208 break;
1209 case HDSPM_madiFreq176_4:
1210 rate = 176400;
1211 break;
1212 case HDSPM_madiFreq192:
1213 rate = 192000;
1214 break;
1215 default:
1216 rate = 0;
1217 break;
1218 }
Adrian Knothd12c51d2011-07-29 03:11:03 +02001219
1220 /* QS and DS rates normally can not be detected
1221 * automatically by the card. Only exception is MADI
1222 * in 96k frame mode.
1223 *
1224 * So if we read SS values (32 .. 48k), check for
1225 * user-provided DS/QS bits in the control register
1226 * and multiply the base frequency accordingly.
1227 */
1228 if (rate <= 48000) {
1229 if (hdspm->control_register & HDSPM_QuadSpeed)
1230 rate *= 4;
1231 else if (hdspm->control_register &
1232 HDSPM_DoubleSpeed)
1233 rate *= 2;
1234 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02001235 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001236 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001237 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001238
1239 return rate;
Takashi Iwai763f3562005-06-03 11:25:34 +02001240}
1241
Adrian Knoth7cb155f2011-08-15 00:22:53 +02001242/* return latency in samples per period */
1243static int hdspm_get_latency(struct hdspm *hdspm)
1244{
1245 int n;
1246
1247 n = hdspm_decode_latency(hdspm->control_register);
1248
1249 /* Special case for new RME cards with 32 samples period size.
1250 * The three latency bits in the control register
1251 * (HDSP_LatencyMask) encode latency values of 64 samples as
1252 * 0, 128 samples as 1 ... 4096 samples as 6. For old cards, 7
1253 * denotes 8192 samples, but on new cards like RayDAT or AIO,
1254 * it corresponds to 32 samples.
1255 */
1256 if ((7 == n) && (RayDAT == hdspm->io_type || AIO == hdspm->io_type))
1257 n = -1;
1258
1259 return 1 << (n + 6);
1260}
1261
Takashi Iwai763f3562005-06-03 11:25:34 +02001262/* Latency function */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001263static inline void hdspm_compute_period_size(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001264{
Adrian Knoth7cb155f2011-08-15 00:22:53 +02001265 hdspm->period_bytes = 4 * hdspm_get_latency(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001266}
1267
Adrian Knoth0dca1792011-01-26 19:32:14 +01001268
1269static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001270{
1271 int position;
1272
1273 position = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth483cee72011-02-23 11:43:09 +01001274
1275 switch (hdspm->io_type) {
1276 case RayDAT:
1277 case AIO:
1278 position &= HDSPM_BufferPositionMask;
1279 position /= 4; /* Bytes per sample */
1280 break;
1281 default:
1282 position = (position & HDSPM_BufferID) ?
1283 (hdspm->period_bytes / 4) : 0;
1284 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001285
1286 return position;
1287}
1288
1289
Takashi Iwai98274f02005-11-17 14:52:34 +01001290static inline void hdspm_start_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001291{
1292 s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
1293 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1294}
1295
Takashi Iwai98274f02005-11-17 14:52:34 +01001296static inline void hdspm_stop_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001297{
1298 s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
1299 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1300}
1301
1302/* should I silence all or only opened ones ? doit all for first even is 4MB*/
Denys Vlasenko62cef822008-04-14 13:04:18 +02001303static void hdspm_silence_playback(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001304{
1305 int i;
1306 int n = hdspm->period_bytes;
1307 void *buf = hdspm->playback_buffer;
1308
Remy Bruno3cee5a62006-10-16 12:46:32 +02001309 if (buf == NULL)
1310 return;
Takashi Iwai763f3562005-06-03 11:25:34 +02001311
1312 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
1313 memset(buf, 0, n);
1314 buf += HDSPM_CHANNEL_BUFFER_BYTES;
1315 }
1316}
1317
Adrian Knoth0dca1792011-01-26 19:32:14 +01001318static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames)
Takashi Iwai763f3562005-06-03 11:25:34 +02001319{
1320 int n;
1321
1322 spin_lock_irq(&s->lock);
1323
Adrian Knoth2e610272011-08-15 00:22:54 +02001324 if (32 == frames) {
1325 /* Special case for new RME cards like RayDAT/AIO which
1326 * support period sizes of 32 samples. Since latency is
1327 * encoded in the three bits of HDSP_LatencyMask, we can only
1328 * have values from 0 .. 7. While 0 still means 64 samples and
1329 * 6 represents 4096 samples on all cards, 7 represents 8192
1330 * on older cards and 32 samples on new cards.
1331 *
1332 * In other words, period size in samples is calculated by
1333 * 2^(n+6) with n ranging from 0 .. 7.
1334 */
1335 n = 7;
1336 } else {
1337 frames >>= 7;
1338 n = 0;
1339 while (frames) {
1340 n++;
1341 frames >>= 1;
1342 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001343 }
Adrian Knoth2e610272011-08-15 00:22:54 +02001344
Takashi Iwai763f3562005-06-03 11:25:34 +02001345 s->control_register &= ~HDSPM_LatencyMask;
1346 s->control_register |= hdspm_encode_latency(n);
1347
1348 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1349
1350 hdspm_compute_period_size(s);
1351
1352 spin_unlock_irq(&s->lock);
1353
1354 return 0;
1355}
1356
Adrian Knoth0dca1792011-01-26 19:32:14 +01001357static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period)
1358{
1359 u64 freq_const;
1360
1361 if (period == 0)
1362 return 0;
1363
1364 switch (hdspm->io_type) {
1365 case MADI:
1366 case AES32:
1367 freq_const = 110069313433624ULL;
1368 break;
1369 case RayDAT:
1370 case AIO:
1371 freq_const = 104857600000000ULL;
1372 break;
1373 case MADIface:
1374 freq_const = 131072000000000ULL;
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001375 break;
1376 default:
1377 snd_BUG();
1378 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001379 }
1380
1381 return div_u64(freq_const, period);
1382}
1383
1384
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001385static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
1386{
1387 u64 n;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001388
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001389 if (rate >= 112000)
1390 rate /= 4;
1391 else if (rate >= 56000)
1392 rate /= 2;
1393
Adrian Knoth0dca1792011-01-26 19:32:14 +01001394 switch (hdspm->io_type) {
1395 case MADIface:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001396 n = 131072000000000ULL; /* 125 MHz */
1397 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001398 case MADI:
1399 case AES32:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001400 n = 110069313433624ULL; /* 105 MHz */
1401 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001402 case RayDAT:
1403 case AIO:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001404 n = 104857600000000ULL; /* 100 MHz */
1405 break;
1406 default:
1407 snd_BUG();
1408 return;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001409 }
1410
Takashi Iwai3f7440a2009-06-05 17:40:04 +02001411 n = div_u64(n, rate);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001412 /* n should be less than 2^32 for being written to FREQ register */
Takashi Iwaida3cec32008-08-08 17:12:14 +02001413 snd_BUG_ON(n >> 32);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001414 hdspm_write(hdspm, HDSPM_freqReg, (u32)n);
1415}
Takashi Iwai763f3562005-06-03 11:25:34 +02001416
1417/* dummy set rate lets see what happens */
Takashi Iwai98274f02005-11-17 14:52:34 +01001418static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
Takashi Iwai763f3562005-06-03 11:25:34 +02001419{
Takashi Iwai763f3562005-06-03 11:25:34 +02001420 int current_rate;
1421 int rate_bits;
1422 int not_set = 0;
Remy Bruno65345992007-08-31 12:21:08 +02001423 int current_speed, target_speed;
Takashi Iwai763f3562005-06-03 11:25:34 +02001424
1425 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
1426 it (e.g. during module initialization).
1427 */
1428
1429 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
1430
Adrian Knoth0dca1792011-01-26 19:32:14 +01001431 /* SLAVE --- */
Takashi Iwai763f3562005-06-03 11:25:34 +02001432 if (called_internally) {
1433
Adrian Knoth0dca1792011-01-26 19:32:14 +01001434 /* request from ctl or card initialization
1435 just make a warning an remember setting
1436 for future master mode switching */
1437
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001438 snd_printk(KERN_WARNING "HDSPM: "
1439 "Warning: device is not running "
1440 "as a clock master.\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001441 not_set = 1;
1442 } else {
1443
1444 /* hw_param request while in AutoSync mode */
1445 int external_freq =
1446 hdspm_external_sample_rate(hdspm);
1447
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001448 if (hdspm_autosync_ref(hdspm) ==
1449 HDSPM_AUTOSYNC_FROM_NONE) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001450
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001451 snd_printk(KERN_WARNING "HDSPM: "
1452 "Detected no Externel Sync \n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001453 not_set = 1;
1454
1455 } else if (rate != external_freq) {
1456
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001457 snd_printk(KERN_WARNING "HDSPM: "
1458 "Warning: No AutoSync source for "
1459 "requested rate\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001460 not_set = 1;
1461 }
1462 }
1463 }
1464
1465 current_rate = hdspm->system_sample_rate;
1466
1467 /* Changing between Singe, Double and Quad speed is not
1468 allowed if any substreams are open. This is because such a change
1469 causes a shift in the location of the DMA buffers and a reduction
1470 in the number of available buffers.
1471
1472 Note that a similar but essentially insoluble problem exists for
1473 externally-driven rate changes. All we can do is to flag rate
Adrian Knoth0dca1792011-01-26 19:32:14 +01001474 changes in the read/write routines.
Takashi Iwai763f3562005-06-03 11:25:34 +02001475 */
1476
Remy Bruno65345992007-08-31 12:21:08 +02001477 if (current_rate <= 48000)
1478 current_speed = HDSPM_SPEED_SINGLE;
1479 else if (current_rate <= 96000)
1480 current_speed = HDSPM_SPEED_DOUBLE;
1481 else
1482 current_speed = HDSPM_SPEED_QUAD;
1483
1484 if (rate <= 48000)
1485 target_speed = HDSPM_SPEED_SINGLE;
1486 else if (rate <= 96000)
1487 target_speed = HDSPM_SPEED_DOUBLE;
1488 else
1489 target_speed = HDSPM_SPEED_QUAD;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001490
Takashi Iwai763f3562005-06-03 11:25:34 +02001491 switch (rate) {
1492 case 32000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001493 rate_bits = HDSPM_Frequency32KHz;
1494 break;
1495 case 44100:
Takashi Iwai763f3562005-06-03 11:25:34 +02001496 rate_bits = HDSPM_Frequency44_1KHz;
1497 break;
1498 case 48000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001499 rate_bits = HDSPM_Frequency48KHz;
1500 break;
1501 case 64000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001502 rate_bits = HDSPM_Frequency64KHz;
1503 break;
1504 case 88200:
Takashi Iwai763f3562005-06-03 11:25:34 +02001505 rate_bits = HDSPM_Frequency88_2KHz;
1506 break;
1507 case 96000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001508 rate_bits = HDSPM_Frequency96KHz;
1509 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001510 case 128000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001511 rate_bits = HDSPM_Frequency128KHz;
1512 break;
1513 case 176400:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001514 rate_bits = HDSPM_Frequency176_4KHz;
1515 break;
1516 case 192000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001517 rate_bits = HDSPM_Frequency192KHz;
1518 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001519 default:
1520 return -EINVAL;
1521 }
1522
Remy Bruno65345992007-08-31 12:21:08 +02001523 if (current_speed != target_speed
Takashi Iwai763f3562005-06-03 11:25:34 +02001524 && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
1525 snd_printk
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001526 (KERN_ERR "HDSPM: "
Remy Bruno65345992007-08-31 12:21:08 +02001527 "cannot change from %s speed to %s speed mode "
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001528 "(capture PID = %d, playback PID = %d)\n",
Remy Bruno65345992007-08-31 12:21:08 +02001529 hdspm_speed_names[current_speed],
1530 hdspm_speed_names[target_speed],
Takashi Iwai763f3562005-06-03 11:25:34 +02001531 hdspm->capture_pid, hdspm->playback_pid);
1532 return -EBUSY;
1533 }
1534
1535 hdspm->control_register &= ~HDSPM_FrequencyMask;
1536 hdspm->control_register |= rate_bits;
1537 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1538
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001539 /* For AES32, need to set DDS value in FREQ register
1540 For MADI, also apparently */
1541 hdspm_set_dds_value(hdspm, rate);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001542
1543 if (AES32 == hdspm->io_type && rate != current_rate)
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001544 hdspm_write(hdspm, HDSPM_eeprom_wr, 0);
Takashi Iwai763f3562005-06-03 11:25:34 +02001545
1546 hdspm->system_sample_rate = rate;
1547
Adrian Knoth0dca1792011-01-26 19:32:14 +01001548 if (rate <= 48000) {
1549 hdspm->channel_map_in = hdspm->channel_map_in_ss;
1550 hdspm->channel_map_out = hdspm->channel_map_out_ss;
1551 hdspm->max_channels_in = hdspm->ss_in_channels;
1552 hdspm->max_channels_out = hdspm->ss_out_channels;
1553 hdspm->port_names_in = hdspm->port_names_in_ss;
1554 hdspm->port_names_out = hdspm->port_names_out_ss;
1555 } else if (rate <= 96000) {
1556 hdspm->channel_map_in = hdspm->channel_map_in_ds;
1557 hdspm->channel_map_out = hdspm->channel_map_out_ds;
1558 hdspm->max_channels_in = hdspm->ds_in_channels;
1559 hdspm->max_channels_out = hdspm->ds_out_channels;
1560 hdspm->port_names_in = hdspm->port_names_in_ds;
1561 hdspm->port_names_out = hdspm->port_names_out_ds;
1562 } else {
1563 hdspm->channel_map_in = hdspm->channel_map_in_qs;
1564 hdspm->channel_map_out = hdspm->channel_map_out_qs;
1565 hdspm->max_channels_in = hdspm->qs_in_channels;
1566 hdspm->max_channels_out = hdspm->qs_out_channels;
1567 hdspm->port_names_in = hdspm->port_names_in_qs;
1568 hdspm->port_names_out = hdspm->port_names_out_qs;
1569 }
1570
Takashi Iwai763f3562005-06-03 11:25:34 +02001571 if (not_set != 0)
1572 return -1;
1573
1574 return 0;
1575}
1576
1577/* mainly for init to 0 on load */
Takashi Iwai98274f02005-11-17 14:52:34 +01001578static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
Takashi Iwai763f3562005-06-03 11:25:34 +02001579{
1580 int i, j;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001581 unsigned int gain;
1582
1583 if (sgain > UNITY_GAIN)
1584 gain = UNITY_GAIN;
1585 else if (sgain < 0)
1586 gain = 0;
1587 else
1588 gain = sgain;
Takashi Iwai763f3562005-06-03 11:25:34 +02001589
1590 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
1591 for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
1592 hdspm_write_in_gain(hdspm, i, j, gain);
1593 hdspm_write_pb_gain(hdspm, i, j, gain);
1594 }
1595}
1596
1597/*----------------------------------------------------------------------------
1598 MIDI
1599 ----------------------------------------------------------------------------*/
1600
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001601static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm,
1602 int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001603{
1604 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001605 return hdspm_read(hdspm, hdspm->midi[id].dataIn);
Takashi Iwai763f3562005-06-03 11:25:34 +02001606}
1607
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001608static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
1609 int val)
Takashi Iwai763f3562005-06-03 11:25:34 +02001610{
1611 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001612 return hdspm_write(hdspm, hdspm->midi[id].dataOut, val);
Takashi Iwai763f3562005-06-03 11:25:34 +02001613}
1614
Takashi Iwai98274f02005-11-17 14:52:34 +01001615static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001616{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001617 return hdspm_read(hdspm, hdspm->midi[id].statusIn) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001618}
1619
Takashi Iwai98274f02005-11-17 14:52:34 +01001620static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001621{
1622 int fifo_bytes_used;
1623
Adrian Knoth0dca1792011-01-26 19:32:14 +01001624 fifo_bytes_used = hdspm_read(hdspm, hdspm->midi[id].statusOut) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001625
1626 if (fifo_bytes_used < 128)
1627 return 128 - fifo_bytes_used;
1628 else
1629 return 0;
1630}
1631
Denys Vlasenko62cef822008-04-14 13:04:18 +02001632static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001633{
1634 while (snd_hdspm_midi_input_available (hdspm, id))
1635 snd_hdspm_midi_read_byte (hdspm, id);
1636}
1637
Takashi Iwai98274f02005-11-17 14:52:34 +01001638static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001639{
1640 unsigned long flags;
1641 int n_pending;
1642 int to_write;
1643 int i;
1644 unsigned char buf[128];
1645
1646 /* Output is not interrupt driven */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001647
Takashi Iwai763f3562005-06-03 11:25:34 +02001648 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001649 if (hmidi->output &&
1650 !snd_rawmidi_transmit_empty (hmidi->output)) {
1651 n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm,
1652 hmidi->id);
1653 if (n_pending > 0) {
1654 if (n_pending > (int)sizeof (buf))
1655 n_pending = sizeof (buf);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001656
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001657 to_write = snd_rawmidi_transmit (hmidi->output, buf,
1658 n_pending);
1659 if (to_write > 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001660 for (i = 0; i < to_write; ++i)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001661 snd_hdspm_midi_write_byte (hmidi->hdspm,
1662 hmidi->id,
1663 buf[i]);
Takashi Iwai763f3562005-06-03 11:25:34 +02001664 }
1665 }
1666 }
1667 spin_unlock_irqrestore (&hmidi->lock, flags);
1668 return 0;
1669}
1670
Takashi Iwai98274f02005-11-17 14:52:34 +01001671static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001672{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001673 unsigned char buf[128]; /* this buffer is designed to match the MIDI
1674 * input FIFO size
1675 */
Takashi Iwai763f3562005-06-03 11:25:34 +02001676 unsigned long flags;
1677 int n_pending;
1678 int i;
1679
1680 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001681 n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id);
1682 if (n_pending > 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001683 if (hmidi->input) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001684 if (n_pending > (int)sizeof (buf))
Takashi Iwai763f3562005-06-03 11:25:34 +02001685 n_pending = sizeof (buf);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001686 for (i = 0; i < n_pending; ++i)
1687 buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm,
1688 hmidi->id);
1689 if (n_pending)
1690 snd_rawmidi_receive (hmidi->input, buf,
1691 n_pending);
Takashi Iwai763f3562005-06-03 11:25:34 +02001692 } else {
1693 /* flush the MIDI input FIFO */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001694 while (n_pending--)
1695 snd_hdspm_midi_read_byte (hmidi->hdspm,
1696 hmidi->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02001697 }
1698 }
1699 hmidi->pending = 0;
Adrian Knothc0da0012011-06-12 17:26:17 +02001700 spin_unlock_irqrestore(&hmidi->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001701
Adrian Knothc0da0012011-06-12 17:26:17 +02001702 spin_lock_irqsave(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001703 hmidi->hdspm->control_register |= hmidi->ie;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001704 hdspm_write(hmidi->hdspm, HDSPM_controlRegister,
1705 hmidi->hdspm->control_register);
Adrian Knothc0da0012011-06-12 17:26:17 +02001706 spin_unlock_irqrestore(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001707
Takashi Iwai763f3562005-06-03 11:25:34 +02001708 return snd_hdspm_midi_output_write (hmidi);
1709}
1710
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001711static void
1712snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001713{
Takashi Iwai98274f02005-11-17 14:52:34 +01001714 struct hdspm *hdspm;
1715 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001716 unsigned long flags;
Takashi Iwai763f3562005-06-03 11:25:34 +02001717
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001718 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001719 hdspm = hmidi->hdspm;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001720
Takashi Iwai763f3562005-06-03 11:25:34 +02001721 spin_lock_irqsave (&hdspm->lock, flags);
1722 if (up) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001723 if (!(hdspm->control_register & hmidi->ie)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001724 snd_hdspm_flush_midi_input (hdspm, hmidi->id);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001725 hdspm->control_register |= hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001726 }
1727 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001728 hdspm->control_register &= ~hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001729 }
1730
1731 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1732 spin_unlock_irqrestore (&hdspm->lock, flags);
1733}
1734
1735static void snd_hdspm_midi_output_timer(unsigned long data)
1736{
Takashi Iwai98274f02005-11-17 14:52:34 +01001737 struct hdspm_midi *hmidi = (struct hdspm_midi *) data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001738 unsigned long flags;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001739
Takashi Iwai763f3562005-06-03 11:25:34 +02001740 snd_hdspm_midi_output_write(hmidi);
1741 spin_lock_irqsave (&hmidi->lock, flags);
1742
1743 /* this does not bump hmidi->istimer, because the
1744 kernel automatically removed the timer when it
1745 expired, and we are now adding it back, thus
Adrian Knoth0dca1792011-01-26 19:32:14 +01001746 leaving istimer wherever it was set before.
Takashi Iwai763f3562005-06-03 11:25:34 +02001747 */
1748
1749 if (hmidi->istimer) {
1750 hmidi->timer.expires = 1 + jiffies;
1751 add_timer(&hmidi->timer);
1752 }
1753
1754 spin_unlock_irqrestore (&hmidi->lock, flags);
1755}
1756
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001757static void
1758snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001759{
Takashi Iwai98274f02005-11-17 14:52:34 +01001760 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001761 unsigned long flags;
1762
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001763 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001764 spin_lock_irqsave (&hmidi->lock, flags);
1765 if (up) {
1766 if (!hmidi->istimer) {
1767 init_timer(&hmidi->timer);
1768 hmidi->timer.function = snd_hdspm_midi_output_timer;
1769 hmidi->timer.data = (unsigned long) hmidi;
1770 hmidi->timer.expires = 1 + jiffies;
1771 add_timer(&hmidi->timer);
1772 hmidi->istimer++;
1773 }
1774 } else {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001775 if (hmidi->istimer && --hmidi->istimer <= 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02001776 del_timer (&hmidi->timer);
Takashi Iwai763f3562005-06-03 11:25:34 +02001777 }
1778 spin_unlock_irqrestore (&hmidi->lock, flags);
1779 if (up)
1780 snd_hdspm_midi_output_write(hmidi);
1781}
1782
Takashi Iwai98274f02005-11-17 14:52:34 +01001783static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001784{
Takashi Iwai98274f02005-11-17 14:52:34 +01001785 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001786
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001787 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001788 spin_lock_irq (&hmidi->lock);
1789 snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
1790 hmidi->input = substream;
1791 spin_unlock_irq (&hmidi->lock);
1792
1793 return 0;
1794}
1795
Takashi Iwai98274f02005-11-17 14:52:34 +01001796static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001797{
Takashi Iwai98274f02005-11-17 14:52:34 +01001798 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001799
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001800 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001801 spin_lock_irq (&hmidi->lock);
1802 hmidi->output = substream;
1803 spin_unlock_irq (&hmidi->lock);
1804
1805 return 0;
1806}
1807
Takashi Iwai98274f02005-11-17 14:52:34 +01001808static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
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
1812 snd_hdspm_midi_input_trigger (substream, 0);
1813
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001814 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001815 spin_lock_irq (&hmidi->lock);
1816 hmidi->input = NULL;
1817 spin_unlock_irq (&hmidi->lock);
1818
1819 return 0;
1820}
1821
Takashi Iwai98274f02005-11-17 14:52:34 +01001822static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001823{
Takashi Iwai98274f02005-11-17 14:52:34 +01001824 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001825
1826 snd_hdspm_midi_output_trigger (substream, 0);
1827
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001828 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001829 spin_lock_irq (&hmidi->lock);
1830 hmidi->output = NULL;
1831 spin_unlock_irq (&hmidi->lock);
1832
1833 return 0;
1834}
1835
Takashi Iwai98274f02005-11-17 14:52:34 +01001836static struct snd_rawmidi_ops snd_hdspm_midi_output =
Takashi Iwai763f3562005-06-03 11:25:34 +02001837{
1838 .open = snd_hdspm_midi_output_open,
1839 .close = snd_hdspm_midi_output_close,
1840 .trigger = snd_hdspm_midi_output_trigger,
1841};
1842
Takashi Iwai98274f02005-11-17 14:52:34 +01001843static struct snd_rawmidi_ops snd_hdspm_midi_input =
Takashi Iwai763f3562005-06-03 11:25:34 +02001844{
1845 .open = snd_hdspm_midi_input_open,
1846 .close = snd_hdspm_midi_input_close,
1847 .trigger = snd_hdspm_midi_input_trigger,
1848};
1849
Bill Pembertone23e7a12012-12-06 12:35:10 -05001850static int snd_hdspm_create_midi(struct snd_card *card,
1851 struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001852{
1853 int err;
1854 char buf[32];
1855
1856 hdspm->midi[id].id = id;
Takashi Iwai763f3562005-06-03 11:25:34 +02001857 hdspm->midi[id].hdspm = hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +02001858 spin_lock_init (&hdspm->midi[id].lock);
1859
Adrian Knoth0dca1792011-01-26 19:32:14 +01001860 if (0 == id) {
1861 if (MADIface == hdspm->io_type) {
1862 /* MIDI-over-MADI on HDSPe MADIface */
1863 hdspm->midi[0].dataIn = HDSPM_midiDataIn2;
1864 hdspm->midi[0].statusIn = HDSPM_midiStatusIn2;
1865 hdspm->midi[0].dataOut = HDSPM_midiDataOut2;
1866 hdspm->midi[0].statusOut = HDSPM_midiStatusOut2;
1867 hdspm->midi[0].ie = HDSPM_Midi2InterruptEnable;
1868 hdspm->midi[0].irq = HDSPM_midi2IRQPending;
1869 } else {
1870 hdspm->midi[0].dataIn = HDSPM_midiDataIn0;
1871 hdspm->midi[0].statusIn = HDSPM_midiStatusIn0;
1872 hdspm->midi[0].dataOut = HDSPM_midiDataOut0;
1873 hdspm->midi[0].statusOut = HDSPM_midiStatusOut0;
1874 hdspm->midi[0].ie = HDSPM_Midi0InterruptEnable;
1875 hdspm->midi[0].irq = HDSPM_midi0IRQPending;
1876 }
1877 } else if (1 == id) {
1878 hdspm->midi[1].dataIn = HDSPM_midiDataIn1;
1879 hdspm->midi[1].statusIn = HDSPM_midiStatusIn1;
1880 hdspm->midi[1].dataOut = HDSPM_midiDataOut1;
1881 hdspm->midi[1].statusOut = HDSPM_midiStatusOut1;
1882 hdspm->midi[1].ie = HDSPM_Midi1InterruptEnable;
1883 hdspm->midi[1].irq = HDSPM_midi1IRQPending;
1884 } else if ((2 == id) && (MADI == hdspm->io_type)) {
1885 /* MIDI-over-MADI on HDSPe MADI */
1886 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1887 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1888 hdspm->midi[2].dataOut = HDSPM_midiDataOut2;
1889 hdspm->midi[2].statusOut = HDSPM_midiStatusOut2;
1890 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1891 hdspm->midi[2].irq = HDSPM_midi2IRQPending;
1892 } else if (2 == id) {
1893 /* TCO MTC, read only */
1894 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1895 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1896 hdspm->midi[2].dataOut = -1;
1897 hdspm->midi[2].statusOut = -1;
1898 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1899 hdspm->midi[2].irq = HDSPM_midi2IRQPendingAES;
1900 } else if (3 == id) {
1901 /* TCO MTC on HDSPe MADI */
1902 hdspm->midi[3].dataIn = HDSPM_midiDataIn3;
1903 hdspm->midi[3].statusIn = HDSPM_midiStatusIn3;
1904 hdspm->midi[3].dataOut = -1;
1905 hdspm->midi[3].statusOut = -1;
1906 hdspm->midi[3].ie = HDSPM_Midi3InterruptEnable;
1907 hdspm->midi[3].irq = HDSPM_midi3IRQPending;
1908 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001909
Adrian Knoth0dca1792011-01-26 19:32:14 +01001910 if ((id < 2) || ((2 == id) && ((MADI == hdspm->io_type) ||
1911 (MADIface == hdspm->io_type)))) {
1912 if ((id == 0) && (MADIface == hdspm->io_type)) {
1913 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1914 } else if ((id == 2) && (MADI == hdspm->io_type)) {
1915 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1916 } else {
1917 sprintf(buf, "%s MIDI %d", card->shortname, id+1);
1918 }
1919 err = snd_rawmidi_new(card, buf, id, 1, 1,
1920 &hdspm->midi[id].rmidi);
1921 if (err < 0)
1922 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02001923
Adrian Knoth0dca1792011-01-26 19:32:14 +01001924 sprintf(hdspm->midi[id].rmidi->name, "%s MIDI %d",
1925 card->id, id+1);
1926 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
Takashi Iwai763f3562005-06-03 11:25:34 +02001927
Adrian Knoth0dca1792011-01-26 19:32:14 +01001928 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1929 SNDRV_RAWMIDI_STREAM_OUTPUT,
1930 &snd_hdspm_midi_output);
1931 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1932 SNDRV_RAWMIDI_STREAM_INPUT,
1933 &snd_hdspm_midi_input);
1934
1935 hdspm->midi[id].rmidi->info_flags |=
1936 SNDRV_RAWMIDI_INFO_OUTPUT |
1937 SNDRV_RAWMIDI_INFO_INPUT |
1938 SNDRV_RAWMIDI_INFO_DUPLEX;
1939 } else {
1940 /* TCO MTC, read only */
1941 sprintf(buf, "%s MTC %d", card->shortname, id+1);
1942 err = snd_rawmidi_new(card, buf, id, 1, 1,
1943 &hdspm->midi[id].rmidi);
1944 if (err < 0)
1945 return err;
1946
1947 sprintf(hdspm->midi[id].rmidi->name,
1948 "%s MTC %d", card->id, id+1);
1949 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
1950
1951 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1952 SNDRV_RAWMIDI_STREAM_INPUT,
1953 &snd_hdspm_midi_input);
1954
1955 hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
1956 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001957
1958 return 0;
1959}
1960
1961
1962static void hdspm_midi_tasklet(unsigned long arg)
1963{
Takashi Iwai98274f02005-11-17 14:52:34 +01001964 struct hdspm *hdspm = (struct hdspm *)arg;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001965 int i = 0;
1966
1967 while (i < hdspm->midiPorts) {
1968 if (hdspm->midi[i].pending)
1969 snd_hdspm_midi_input_read(&hdspm->midi[i]);
1970
1971 i++;
1972 }
1973}
Takashi Iwai763f3562005-06-03 11:25:34 +02001974
1975
1976/*-----------------------------------------------------------------------------
1977 Status Interface
1978 ----------------------------------------------------------------------------*/
1979
1980/* get the system sample rate which is set */
1981
Adrian Knoth0dca1792011-01-26 19:32:14 +01001982
Adrian Knoth3f7bf912013-03-10 00:37:21 +01001983static inline int hdspm_get_pll_freq(struct hdspm *hdspm)
1984{
1985 unsigned int period, rate;
1986
1987 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
1988 rate = hdspm_calc_dds_value(hdspm, period);
1989
1990 return rate;
1991}
1992
Adrian Knoth0dca1792011-01-26 19:32:14 +01001993/**
1994 * Calculate the real sample rate from the
1995 * current DDS value.
1996 **/
1997static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
1998{
Adrian Knoth3f7bf912013-03-10 00:37:21 +01001999 unsigned int rate;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002000
Adrian Knoth3f7bf912013-03-10 00:37:21 +01002001 rate = hdspm_get_pll_freq(hdspm);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002002
Adrian Knotha97bda72012-05-30 14:23:18 +02002003 if (rate > 207000) {
Adrian Knoth21a164d2012-10-19 17:42:23 +02002004 /* Unreasonable high sample rate as seen on PCI MADI cards. */
2005 if (0 == hdspm_system_clock_mode(hdspm)) {
2006 /* master mode, return internal sample rate */
2007 rate = hdspm->system_sample_rate;
2008 } else {
2009 /* slave mode, return external sample rate */
2010 rate = hdspm_external_sample_rate(hdspm);
2011 }
Adrian Knotha97bda72012-05-30 14:23:18 +02002012 }
2013
Adrian Knoth0dca1792011-01-26 19:32:14 +01002014 return rate;
2015}
2016
2017
Takashi Iwai763f3562005-06-03 11:25:34 +02002018#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02002019{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2020 .name = xname, \
2021 .index = xindex, \
2022 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2023 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2024 .info = snd_hdspm_info_system_sample_rate, \
2025 .put = snd_hdspm_put_system_sample_rate, \
2026 .get = snd_hdspm_get_system_sample_rate \
Takashi Iwai763f3562005-06-03 11:25:34 +02002027}
2028
Takashi Iwai98274f02005-11-17 14:52:34 +01002029static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
2030 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002031{
2032 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2033 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002034 uinfo->value.integer.min = 27000;
2035 uinfo->value.integer.max = 207000;
2036 uinfo->value.integer.step = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002037 return 0;
2038}
2039
Adrian Knoth0dca1792011-01-26 19:32:14 +01002040
Takashi Iwai98274f02005-11-17 14:52:34 +01002041static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
2042 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002043 ucontrol)
2044{
Takashi Iwai98274f02005-11-17 14:52:34 +01002045 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002046
Adrian Knoth0dca1792011-01-26 19:32:14 +01002047 ucontrol->value.integer.value[0] = hdspm_get_system_sample_rate(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002048 return 0;
2049}
2050
Adrian Knoth41285a92012-10-19 17:42:22 +02002051static int snd_hdspm_put_system_sample_rate(struct snd_kcontrol *kcontrol,
2052 struct snd_ctl_elem_value *
2053 ucontrol)
2054{
2055 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2056
2057 hdspm_set_dds_value(hdspm, ucontrol->value.enumerated.item[0]);
2058 return 0;
2059}
2060
Adrian Knoth0dca1792011-01-26 19:32:14 +01002061
2062/**
2063 * Returns the WordClock sample rate class for the given card.
2064 **/
2065static int hdspm_get_wc_sample_rate(struct hdspm *hdspm)
2066{
2067 int status;
2068
2069 switch (hdspm->io_type) {
2070 case RayDAT:
2071 case AIO:
2072 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2073 return (status >> 16) & 0xF;
2074 break;
2075 default:
2076 break;
2077 }
2078
2079
2080 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002081}
2082
Adrian Knoth0dca1792011-01-26 19:32:14 +01002083
2084/**
2085 * Returns the TCO sample rate class for the given card.
2086 **/
2087static int hdspm_get_tco_sample_rate(struct hdspm *hdspm)
2088{
2089 int status;
2090
2091 if (hdspm->tco) {
2092 switch (hdspm->io_type) {
2093 case RayDAT:
2094 case AIO:
2095 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2096 return (status >> 20) & 0xF;
2097 break;
2098 default:
2099 break;
2100 }
2101 }
2102
2103 return 0;
2104}
2105
2106
2107/**
2108 * Returns the SYNC_IN sample rate class for the given card.
2109 **/
2110static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm)
2111{
2112 int status;
2113
2114 if (hdspm->tco) {
2115 switch (hdspm->io_type) {
2116 case RayDAT:
2117 case AIO:
2118 status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2119 return (status >> 12) & 0xF;
2120 break;
2121 default:
2122 break;
2123 }
2124 }
2125
2126 return 0;
2127}
2128
2129
2130/**
2131 * Returns the sample rate class for input source <idx> for
2132 * 'new style' cards like the AIO and RayDAT.
2133 **/
2134static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
2135{
2136 int status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2137
2138 return (status >> (idx*4)) & 0xF;
2139}
2140
2141
2142
2143#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
2144{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2145 .name = xname, \
2146 .private_value = xindex, \
2147 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2148 .info = snd_hdspm_info_autosync_sample_rate, \
2149 .get = snd_hdspm_get_autosync_sample_rate \
2150}
2151
2152
Takashi Iwai98274f02005-11-17 14:52:34 +01002153static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2154 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002155{
Takashi Iwai763f3562005-06-03 11:25:34 +02002156 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2157 uinfo->count = 1;
2158 uinfo->value.enumerated.items = 10;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002159
Takashi Iwai763f3562005-06-03 11:25:34 +02002160 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
Adrian Knoth0dca1792011-01-26 19:32:14 +01002161 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002162 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002163 texts_freq[uinfo->value.enumerated.item]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002164 return 0;
2165}
2166
Adrian Knoth0dca1792011-01-26 19:32:14 +01002167
Takashi Iwai98274f02005-11-17 14:52:34 +01002168static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2169 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002170 ucontrol)
2171{
Takashi Iwai98274f02005-11-17 14:52:34 +01002172 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002173
Adrian Knoth0dca1792011-01-26 19:32:14 +01002174 switch (hdspm->io_type) {
2175 case RayDAT:
2176 switch (kcontrol->private_value) {
2177 case 0:
2178 ucontrol->value.enumerated.item[0] =
2179 hdspm_get_wc_sample_rate(hdspm);
2180 break;
2181 case 7:
2182 ucontrol->value.enumerated.item[0] =
2183 hdspm_get_tco_sample_rate(hdspm);
2184 break;
2185 case 8:
2186 ucontrol->value.enumerated.item[0] =
2187 hdspm_get_sync_in_sample_rate(hdspm);
2188 break;
2189 default:
2190 ucontrol->value.enumerated.item[0] =
2191 hdspm_get_s1_sample_rate(hdspm,
2192 kcontrol->private_value-1);
2193 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002194 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002195
Adrian Knoth0dca1792011-01-26 19:32:14 +01002196 case AIO:
2197 switch (kcontrol->private_value) {
2198 case 0: /* WC */
2199 ucontrol->value.enumerated.item[0] =
2200 hdspm_get_wc_sample_rate(hdspm);
2201 break;
2202 case 4: /* TCO */
2203 ucontrol->value.enumerated.item[0] =
2204 hdspm_get_tco_sample_rate(hdspm);
2205 break;
2206 case 5: /* SYNC_IN */
2207 ucontrol->value.enumerated.item[0] =
2208 hdspm_get_sync_in_sample_rate(hdspm);
2209 break;
2210 default:
2211 ucontrol->value.enumerated.item[0] =
2212 hdspm_get_s1_sample_rate(hdspm,
2213 ucontrol->id.index-1);
2214 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002215 break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002216
2217 case AES32:
2218
2219 switch (kcontrol->private_value) {
2220 case 0: /* WC */
2221 ucontrol->value.enumerated.item[0] =
2222 hdspm_get_wc_sample_rate(hdspm);
2223 break;
2224 case 9: /* TCO */
2225 ucontrol->value.enumerated.item[0] =
2226 hdspm_get_tco_sample_rate(hdspm);
2227 break;
2228 case 10: /* SYNC_IN */
2229 ucontrol->value.enumerated.item[0] =
2230 hdspm_get_sync_in_sample_rate(hdspm);
2231 break;
2232 default: /* AES1 to AES8 */
2233 ucontrol->value.enumerated.item[0] =
2234 hdspm_get_s1_sample_rate(hdspm,
2235 kcontrol->private_value-1);
2236 break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002237 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002238 break;
Adrian Knothb8812c52012-10-19 17:42:26 +02002239
2240 case MADI:
2241 case MADIface:
2242 {
2243 int rate = hdspm_external_sample_rate(hdspm);
2244 int i, selected_rate = 0;
2245 for (i = 1; i < 10; i++)
2246 if (HDSPM_bit2freq(i) == rate) {
2247 selected_rate = i;
2248 break;
2249 }
2250 ucontrol->value.enumerated.item[0] = selected_rate;
2251 }
2252 break;
2253
Takashi Iwai763f3562005-06-03 11:25:34 +02002254 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002255 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002256 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002257
Takashi Iwai763f3562005-06-03 11:25:34 +02002258 return 0;
2259}
2260
Adrian Knoth0dca1792011-01-26 19:32:14 +01002261
Takashi Iwai763f3562005-06-03 11:25:34 +02002262#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002263{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2264 .name = xname, \
2265 .index = xindex, \
2266 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2267 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2268 .info = snd_hdspm_info_system_clock_mode, \
2269 .get = snd_hdspm_get_system_clock_mode, \
2270 .put = snd_hdspm_put_system_clock_mode, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002271}
2272
2273
Adrian Knoth0dca1792011-01-26 19:32:14 +01002274/**
2275 * Returns the system clock mode for the given card.
2276 * @returns 0 - master, 1 - slave
2277 **/
2278static int hdspm_system_clock_mode(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002279{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002280 switch (hdspm->io_type) {
2281 case AIO:
2282 case RayDAT:
2283 if (hdspm->settings_register & HDSPM_c0Master)
2284 return 0;
2285 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002286
Adrian Knoth0dca1792011-01-26 19:32:14 +01002287 default:
2288 if (hdspm->control_register & HDSPM_ClockModeMaster)
2289 return 0;
2290 }
2291
Takashi Iwai763f3562005-06-03 11:25:34 +02002292 return 1;
2293}
2294
Adrian Knoth0dca1792011-01-26 19:32:14 +01002295
2296/**
2297 * Sets the system clock mode.
2298 * @param mode 0 - master, 1 - slave
2299 **/
2300static void hdspm_set_system_clock_mode(struct hdspm *hdspm, int mode)
2301{
2302 switch (hdspm->io_type) {
2303 case AIO:
2304 case RayDAT:
2305 if (0 == mode)
2306 hdspm->settings_register |= HDSPM_c0Master;
2307 else
2308 hdspm->settings_register &= ~HDSPM_c0Master;
2309
2310 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2311 break;
2312
2313 default:
2314 if (0 == mode)
2315 hdspm->control_register |= HDSPM_ClockModeMaster;
2316 else
2317 hdspm->control_register &= ~HDSPM_ClockModeMaster;
2318
2319 hdspm_write(hdspm, HDSPM_controlRegister,
2320 hdspm->control_register);
2321 }
2322}
2323
2324
Takashi Iwai98274f02005-11-17 14:52:34 +01002325static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
2326 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002327{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002328 static char *texts[] = { "Master", "AutoSync" };
Takashi Iwai763f3562005-06-03 11:25:34 +02002329
2330 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2331 uinfo->count = 1;
2332 uinfo->value.enumerated.items = 2;
2333 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2334 uinfo->value.enumerated.item =
2335 uinfo->value.enumerated.items - 1;
2336 strcpy(uinfo->value.enumerated.name,
2337 texts[uinfo->value.enumerated.item]);
2338 return 0;
2339}
2340
Takashi Iwai98274f02005-11-17 14:52:34 +01002341static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
2342 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002343{
Takashi Iwai98274f02005-11-17 14:52:34 +01002344 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002345
Adrian Knoth0dca1792011-01-26 19:32:14 +01002346 ucontrol->value.enumerated.item[0] = hdspm_system_clock_mode(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002347 return 0;
2348}
2349
Adrian Knoth0dca1792011-01-26 19:32:14 +01002350static int snd_hdspm_put_system_clock_mode(struct snd_kcontrol *kcontrol,
2351 struct snd_ctl_elem_value *ucontrol)
2352{
2353 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2354 int val;
2355
2356 if (!snd_hdspm_use_is_exclusive(hdspm))
2357 return -EBUSY;
2358
2359 val = ucontrol->value.enumerated.item[0];
2360 if (val < 0)
2361 val = 0;
2362 else if (val > 1)
2363 val = 1;
2364
2365 hdspm_set_system_clock_mode(hdspm, val);
2366
2367 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002368}
2369
Adrian Knoth0dca1792011-01-26 19:32:14 +01002370
2371#define HDSPM_INTERNAL_CLOCK(xname, xindex) \
2372{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2373 .name = xname, \
2374 .index = xindex, \
2375 .info = snd_hdspm_info_clock_source, \
2376 .get = snd_hdspm_get_clock_source, \
2377 .put = snd_hdspm_put_clock_source \
2378}
2379
2380
Takashi Iwai98274f02005-11-17 14:52:34 +01002381static int hdspm_clock_source(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002382{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002383 switch (hdspm->system_sample_rate) {
2384 case 32000: return 0;
2385 case 44100: return 1;
2386 case 48000: return 2;
2387 case 64000: return 3;
2388 case 88200: return 4;
2389 case 96000: return 5;
2390 case 128000: return 6;
2391 case 176400: return 7;
2392 case 192000: return 8;
Takashi Iwai763f3562005-06-03 11:25:34 +02002393 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002394
2395 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002396}
2397
Takashi Iwai98274f02005-11-17 14:52:34 +01002398static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
Takashi Iwai763f3562005-06-03 11:25:34 +02002399{
2400 int rate;
2401 switch (mode) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002402 case 0:
2403 rate = 32000; break;
2404 case 1:
2405 rate = 44100; break;
2406 case 2:
2407 rate = 48000; break;
2408 case 3:
2409 rate = 64000; break;
2410 case 4:
2411 rate = 88200; break;
2412 case 5:
2413 rate = 96000; break;
2414 case 6:
2415 rate = 128000; break;
2416 case 7:
2417 rate = 176400; break;
2418 case 8:
2419 rate = 192000; break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002420 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002421 rate = 48000;
Takashi Iwai763f3562005-06-03 11:25:34 +02002422 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002423 hdspm_set_rate(hdspm, rate, 1);
2424 return 0;
2425}
2426
Takashi Iwai98274f02005-11-17 14:52:34 +01002427static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
2428 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002429{
Takashi Iwai763f3562005-06-03 11:25:34 +02002430 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2431 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002432 uinfo->value.enumerated.items = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002433
2434 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2435 uinfo->value.enumerated.item =
2436 uinfo->value.enumerated.items - 1;
2437
2438 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002439 texts_freq[uinfo->value.enumerated.item+1]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002440
2441 return 0;
2442}
2443
Takashi Iwai98274f02005-11-17 14:52:34 +01002444static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
2445 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002446{
Takashi Iwai98274f02005-11-17 14:52:34 +01002447 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002448
2449 ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
2450 return 0;
2451}
2452
Takashi Iwai98274f02005-11-17 14:52:34 +01002453static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
2454 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002455{
Takashi Iwai98274f02005-11-17 14:52:34 +01002456 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002457 int change;
2458 int val;
2459
2460 if (!snd_hdspm_use_is_exclusive(hdspm))
2461 return -EBUSY;
2462 val = ucontrol->value.enumerated.item[0];
2463 if (val < 0)
2464 val = 0;
Remy Bruno65345992007-08-31 12:21:08 +02002465 if (val > 9)
2466 val = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002467 spin_lock_irq(&hdspm->lock);
2468 if (val != hdspm_clock_source(hdspm))
2469 change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
2470 else
2471 change = 0;
2472 spin_unlock_irq(&hdspm->lock);
2473 return change;
2474}
2475
Adrian Knoth0dca1792011-01-26 19:32:14 +01002476
Takashi Iwai763f3562005-06-03 11:25:34 +02002477#define HDSPM_PREF_SYNC_REF(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02002478{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002479 .name = xname, \
2480 .index = xindex, \
2481 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2482 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2483 .info = snd_hdspm_info_pref_sync_ref, \
2484 .get = snd_hdspm_get_pref_sync_ref, \
2485 .put = snd_hdspm_put_pref_sync_ref \
Takashi Iwai763f3562005-06-03 11:25:34 +02002486}
2487
Adrian Knoth0dca1792011-01-26 19:32:14 +01002488
2489/**
2490 * Returns the current preferred sync reference setting.
2491 * The semantics of the return value are depending on the
2492 * card, please see the comments for clarification.
2493 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002494static int hdspm_pref_sync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002495{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002496 switch (hdspm->io_type) {
2497 case AES32:
Remy Bruno3cee5a62006-10-16 12:46:32 +02002498 switch (hdspm->control_register & HDSPM_SyncRefMask) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002499 case 0: return 0; /* WC */
2500 case HDSPM_SyncRef0: return 1; /* AES 1 */
2501 case HDSPM_SyncRef1: return 2; /* AES 2 */
2502 case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; /* AES 3 */
2503 case HDSPM_SyncRef2: return 4; /* AES 4 */
2504 case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; /* AES 5 */
2505 case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; /* AES 6 */
2506 case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0:
2507 return 7; /* AES 7 */
2508 case HDSPM_SyncRef3: return 8; /* AES 8 */
2509 case HDSPM_SyncRef3+HDSPM_SyncRef0: return 9; /* TCO */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002510 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002511 break;
2512
2513 case MADI:
2514 case MADIface:
2515 if (hdspm->tco) {
2516 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2517 case 0: return 0; /* WC */
2518 case HDSPM_SyncRef0: return 1; /* MADI */
2519 case HDSPM_SyncRef1: return 2; /* TCO */
2520 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2521 return 3; /* SYNC_IN */
2522 }
2523 } else {
2524 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2525 case 0: return 0; /* WC */
2526 case HDSPM_SyncRef0: return 1; /* MADI */
2527 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2528 return 2; /* SYNC_IN */
2529 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02002530 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002531 break;
2532
2533 case RayDAT:
2534 if (hdspm->tco) {
2535 switch ((hdspm->settings_register &
2536 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2537 case 0: return 0; /* WC */
2538 case 3: return 1; /* ADAT 1 */
2539 case 4: return 2; /* ADAT 2 */
2540 case 5: return 3; /* ADAT 3 */
2541 case 6: return 4; /* ADAT 4 */
2542 case 1: return 5; /* AES */
2543 case 2: return 6; /* SPDIF */
2544 case 9: return 7; /* TCO */
2545 case 10: return 8; /* SYNC_IN */
2546 }
2547 } else {
2548 switch ((hdspm->settings_register &
2549 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2550 case 0: return 0; /* WC */
2551 case 3: return 1; /* ADAT 1 */
2552 case 4: return 2; /* ADAT 2 */
2553 case 5: return 3; /* ADAT 3 */
2554 case 6: return 4; /* ADAT 4 */
2555 case 1: return 5; /* AES */
2556 case 2: return 6; /* SPDIF */
2557 case 10: return 7; /* SYNC_IN */
2558 }
2559 }
2560
2561 break;
2562
2563 case AIO:
2564 if (hdspm->tco) {
2565 switch ((hdspm->settings_register &
2566 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2567 case 0: return 0; /* WC */
2568 case 3: return 1; /* ADAT */
2569 case 1: return 2; /* AES */
2570 case 2: return 3; /* SPDIF */
2571 case 9: return 4; /* TCO */
2572 case 10: return 5; /* SYNC_IN */
2573 }
2574 } else {
2575 switch ((hdspm->settings_register &
2576 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2577 case 0: return 0; /* WC */
2578 case 3: return 1; /* ADAT */
2579 case 1: return 2; /* AES */
2580 case 2: return 3; /* SPDIF */
2581 case 10: return 4; /* SYNC_IN */
2582 }
2583 }
2584
2585 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002586 }
2587
Adrian Knoth0dca1792011-01-26 19:32:14 +01002588 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002589}
2590
Adrian Knoth0dca1792011-01-26 19:32:14 +01002591
2592/**
2593 * Set the preferred sync reference to <pref>. The semantics
2594 * of <pref> are depending on the card type, see the comments
2595 * for clarification.
2596 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002597static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
Takashi Iwai763f3562005-06-03 11:25:34 +02002598{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002599 int p = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002600
Adrian Knoth0dca1792011-01-26 19:32:14 +01002601 switch (hdspm->io_type) {
2602 case AES32:
2603 hdspm->control_register &= ~HDSPM_SyncRefMask;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002604 switch (pref) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002605 case 0: /* WC */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002606 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002607 case 1: /* AES 1 */
2608 hdspm->control_register |= HDSPM_SyncRef0;
2609 break;
2610 case 2: /* AES 2 */
2611 hdspm->control_register |= HDSPM_SyncRef1;
2612 break;
2613 case 3: /* AES 3 */
2614 hdspm->control_register |=
2615 HDSPM_SyncRef1+HDSPM_SyncRef0;
2616 break;
2617 case 4: /* AES 4 */
2618 hdspm->control_register |= HDSPM_SyncRef2;
2619 break;
2620 case 5: /* AES 5 */
2621 hdspm->control_register |=
2622 HDSPM_SyncRef2+HDSPM_SyncRef0;
2623 break;
2624 case 6: /* AES 6 */
2625 hdspm->control_register |=
2626 HDSPM_SyncRef2+HDSPM_SyncRef1;
2627 break;
2628 case 7: /* AES 7 */
2629 hdspm->control_register |=
2630 HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
2631 break;
2632 case 8: /* AES 8 */
2633 hdspm->control_register |= HDSPM_SyncRef3;
2634 break;
2635 case 9: /* TCO */
2636 hdspm->control_register |=
2637 HDSPM_SyncRef3+HDSPM_SyncRef0;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002638 break;
2639 default:
2640 return -1;
2641 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002642
2643 break;
2644
2645 case MADI:
2646 case MADIface:
2647 hdspm->control_register &= ~HDSPM_SyncRefMask;
2648 if (hdspm->tco) {
2649 switch (pref) {
2650 case 0: /* WC */
2651 break;
2652 case 1: /* MADI */
2653 hdspm->control_register |= HDSPM_SyncRef0;
2654 break;
2655 case 2: /* TCO */
2656 hdspm->control_register |= HDSPM_SyncRef1;
2657 break;
2658 case 3: /* SYNC_IN */
2659 hdspm->control_register |=
2660 HDSPM_SyncRef0+HDSPM_SyncRef1;
2661 break;
2662 default:
2663 return -1;
2664 }
2665 } else {
2666 switch (pref) {
2667 case 0: /* WC */
2668 break;
2669 case 1: /* MADI */
2670 hdspm->control_register |= HDSPM_SyncRef0;
2671 break;
2672 case 2: /* SYNC_IN */
2673 hdspm->control_register |=
2674 HDSPM_SyncRef0+HDSPM_SyncRef1;
2675 break;
2676 default:
2677 return -1;
2678 }
2679 }
2680
2681 break;
2682
2683 case RayDAT:
2684 if (hdspm->tco) {
2685 switch (pref) {
2686 case 0: p = 0; break; /* WC */
2687 case 1: p = 3; break; /* ADAT 1 */
2688 case 2: p = 4; break; /* ADAT 2 */
2689 case 3: p = 5; break; /* ADAT 3 */
2690 case 4: p = 6; break; /* ADAT 4 */
2691 case 5: p = 1; break; /* AES */
2692 case 6: p = 2; break; /* SPDIF */
2693 case 7: p = 9; break; /* TCO */
2694 case 8: p = 10; break; /* SYNC_IN */
2695 default: return -1;
2696 }
2697 } else {
2698 switch (pref) {
2699 case 0: p = 0; break; /* WC */
2700 case 1: p = 3; break; /* ADAT 1 */
2701 case 2: p = 4; break; /* ADAT 2 */
2702 case 3: p = 5; break; /* ADAT 3 */
2703 case 4: p = 6; break; /* ADAT 4 */
2704 case 5: p = 1; break; /* AES */
2705 case 6: p = 2; break; /* SPDIF */
2706 case 7: p = 10; break; /* SYNC_IN */
2707 default: return -1;
2708 }
2709 }
2710 break;
2711
2712 case AIO:
2713 if (hdspm->tco) {
2714 switch (pref) {
2715 case 0: p = 0; break; /* WC */
2716 case 1: p = 3; break; /* ADAT */
2717 case 2: p = 1; break; /* AES */
2718 case 3: p = 2; break; /* SPDIF */
2719 case 4: p = 9; break; /* TCO */
2720 case 5: p = 10; break; /* SYNC_IN */
2721 default: return -1;
2722 }
2723 } else {
2724 switch (pref) {
2725 case 0: p = 0; break; /* WC */
2726 case 1: p = 3; break; /* ADAT */
2727 case 2: p = 1; break; /* AES */
2728 case 3: p = 2; break; /* SPDIF */
2729 case 4: p = 10; break; /* SYNC_IN */
2730 default: return -1;
2731 }
2732 }
2733 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002734 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002735
2736 switch (hdspm->io_type) {
2737 case RayDAT:
2738 case AIO:
2739 hdspm->settings_register &= ~HDSPM_c0_SyncRefMask;
2740 hdspm->settings_register |= HDSPM_c0_SyncRef0 * p;
2741 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2742 break;
2743
2744 case MADI:
2745 case MADIface:
2746 case AES32:
2747 hdspm_write(hdspm, HDSPM_controlRegister,
2748 hdspm->control_register);
2749 }
2750
Takashi Iwai763f3562005-06-03 11:25:34 +02002751 return 0;
2752}
2753
Adrian Knoth0dca1792011-01-26 19:32:14 +01002754
Takashi Iwai98274f02005-11-17 14:52:34 +01002755static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
2756 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002757{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002758 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002759
Adrian Knoth0dca1792011-01-26 19:32:14 +01002760 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2761 uinfo->count = 1;
2762 uinfo->value.enumerated.items = hdspm->texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +02002763
Adrian Knoth0dca1792011-01-26 19:32:14 +01002764 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2765 uinfo->value.enumerated.item =
2766 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002767
Adrian Knoth0dca1792011-01-26 19:32:14 +01002768 strcpy(uinfo->value.enumerated.name,
2769 hdspm->texts_autosync[uinfo->value.enumerated.item]);
Remy Bruno3cee5a62006-10-16 12:46:32 +02002770
Takashi Iwai763f3562005-06-03 11:25:34 +02002771 return 0;
2772}
2773
Takashi Iwai98274f02005-11-17 14:52:34 +01002774static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
2775 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002776{
Takashi Iwai98274f02005-11-17 14:52:34 +01002777 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002778 int psf = hdspm_pref_sync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002779
Adrian Knoth0dca1792011-01-26 19:32:14 +01002780 if (psf >= 0) {
2781 ucontrol->value.enumerated.item[0] = psf;
2782 return 0;
2783 }
2784
2785 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002786}
2787
Takashi Iwai98274f02005-11-17 14:52:34 +01002788static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
2789 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002790{
Takashi Iwai98274f02005-11-17 14:52:34 +01002791 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002792 int val, change = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002793
2794 if (!snd_hdspm_use_is_exclusive(hdspm))
2795 return -EBUSY;
2796
Adrian Knoth0dca1792011-01-26 19:32:14 +01002797 val = ucontrol->value.enumerated.item[0];
2798
2799 if (val < 0)
2800 val = 0;
2801 else if (val >= hdspm->texts_autosync_items)
2802 val = hdspm->texts_autosync_items-1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002803
2804 spin_lock_irq(&hdspm->lock);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002805 if (val != hdspm_pref_sync_ref(hdspm))
2806 change = (0 == hdspm_set_pref_sync_ref(hdspm, val)) ? 1 : 0;
2807
Takashi Iwai763f3562005-06-03 11:25:34 +02002808 spin_unlock_irq(&hdspm->lock);
2809 return change;
2810}
2811
Adrian Knoth0dca1792011-01-26 19:32:14 +01002812
Takashi Iwai763f3562005-06-03 11:25:34 +02002813#define HDSPM_AUTOSYNC_REF(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02002814{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2815 .name = xname, \
2816 .index = xindex, \
2817 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2818 .info = snd_hdspm_info_autosync_ref, \
2819 .get = snd_hdspm_get_autosync_ref, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002820}
2821
Adrian Knoth0dca1792011-01-26 19:32:14 +01002822static int hdspm_autosync_ref(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002823{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002824 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002825 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002826 unsigned int syncref =
2827 (status >> HDSPM_AES32_syncref_bit) & 0xF;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002828 if (syncref == 0)
2829 return HDSPM_AES32_AUTOSYNC_FROM_WORD;
2830 if (syncref <= 8)
2831 return syncref;
2832 return HDSPM_AES32_AUTOSYNC_FROM_NONE;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002833 } else if (MADI == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002834 /* This looks at the autosync selected sync reference */
2835 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Takashi Iwai763f3562005-06-03 11:25:34 +02002836
Remy Bruno3cee5a62006-10-16 12:46:32 +02002837 switch (status2 & HDSPM_SelSyncRefMask) {
2838 case HDSPM_SelSyncRef_WORD:
2839 return HDSPM_AUTOSYNC_FROM_WORD;
2840 case HDSPM_SelSyncRef_MADI:
2841 return HDSPM_AUTOSYNC_FROM_MADI;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002842 case HDSPM_SelSyncRef_TCO:
2843 return HDSPM_AUTOSYNC_FROM_TCO;
2844 case HDSPM_SelSyncRef_SyncIn:
2845 return HDSPM_AUTOSYNC_FROM_SYNC_IN;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002846 case HDSPM_SelSyncRef_NVALID:
2847 return HDSPM_AUTOSYNC_FROM_NONE;
2848 default:
2849 return 0;
2850 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002851
Takashi Iwai763f3562005-06-03 11:25:34 +02002852 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002853 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002854}
2855
Adrian Knoth0dca1792011-01-26 19:32:14 +01002856
Takashi Iwai98274f02005-11-17 14:52:34 +01002857static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
2858 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002859{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002860 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002861
Adrian Knoth0dca1792011-01-26 19:32:14 +01002862 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002863 static char *texts[] = { "WordClock", "AES1", "AES2", "AES3",
2864 "AES4", "AES5", "AES6", "AES7", "AES8", "None"};
2865
2866 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2867 uinfo->count = 1;
2868 uinfo->value.enumerated.items = 10;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002869 if (uinfo->value.enumerated.item >=
2870 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002871 uinfo->value.enumerated.item =
2872 uinfo->value.enumerated.items - 1;
2873 strcpy(uinfo->value.enumerated.name,
2874 texts[uinfo->value.enumerated.item]);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002875 } else if (MADI == hdspm->io_type) {
2876 static char *texts[] = {"Word Clock", "MADI", "TCO",
2877 "Sync In", "None" };
Remy Bruno3cee5a62006-10-16 12:46:32 +02002878
2879 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2880 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002881 uinfo->value.enumerated.items = 5;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002882 if (uinfo->value.enumerated.item >=
Adrian Knoth0dca1792011-01-26 19:32:14 +01002883 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002884 uinfo->value.enumerated.item =
2885 uinfo->value.enumerated.items - 1;
2886 strcpy(uinfo->value.enumerated.name,
2887 texts[uinfo->value.enumerated.item]);
2888 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002889 return 0;
2890}
2891
Takashi Iwai98274f02005-11-17 14:52:34 +01002892static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
2893 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002894{
Takashi Iwai98274f02005-11-17 14:52:34 +01002895 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002896
Remy Bruno65345992007-08-31 12:21:08 +02002897 ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002898 return 0;
2899}
2900
Adrian Knothbf0ff872012-12-03 14:55:49 +01002901#define HDSPM_TOGGLE_SETTING(xname, xindex) \
2902{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2903 .name = xname, \
2904 .private_value = xindex, \
2905 .info = snd_hdspm_info_toggle_setting, \
2906 .get = snd_hdspm_get_toggle_setting, \
2907 .put = snd_hdspm_put_toggle_setting \
2908}
2909
2910static int hdspm_toggle_setting(struct hdspm *hdspm, u32 regmask)
2911{
2912 return (hdspm->control_register & regmask) ? 1 : 0;
2913}
2914
2915static int hdspm_set_toggle_setting(struct hdspm *hdspm, u32 regmask, int out)
2916{
2917 if (out)
2918 hdspm->control_register |= regmask;
2919 else
2920 hdspm->control_register &= ~regmask;
2921 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2922
2923 return 0;
2924}
2925
2926#define snd_hdspm_info_toggle_setting snd_ctl_boolean_mono_info
2927
2928static int snd_hdspm_get_toggle_setting(struct snd_kcontrol *kcontrol,
2929 struct snd_ctl_elem_value *ucontrol)
2930{
2931 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2932 u32 regmask = kcontrol->private_value;
2933
2934 spin_lock_irq(&hdspm->lock);
2935 ucontrol->value.integer.value[0] = hdspm_toggle_setting(hdspm, regmask);
2936 spin_unlock_irq(&hdspm->lock);
2937 return 0;
2938}
2939
2940static int snd_hdspm_put_toggle_setting(struct snd_kcontrol *kcontrol,
2941 struct snd_ctl_elem_value *ucontrol)
2942{
2943 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2944 u32 regmask = kcontrol->private_value;
2945 int change;
2946 unsigned int val;
2947
2948 if (!snd_hdspm_use_is_exclusive(hdspm))
2949 return -EBUSY;
2950 val = ucontrol->value.integer.value[0] & 1;
2951 spin_lock_irq(&hdspm->lock);
2952 change = (int) val != hdspm_toggle_setting(hdspm, regmask);
2953 hdspm_set_toggle_setting(hdspm, regmask, val);
2954 spin_unlock_irq(&hdspm->lock);
2955 return change;
2956}
2957
Takashi Iwai763f3562005-06-03 11:25:34 +02002958#define HDSPM_INPUT_SELECT(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02002959{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2960 .name = xname, \
2961 .index = xindex, \
2962 .info = snd_hdspm_info_input_select, \
2963 .get = snd_hdspm_get_input_select, \
2964 .put = snd_hdspm_put_input_select \
Takashi Iwai763f3562005-06-03 11:25:34 +02002965}
2966
Takashi Iwai98274f02005-11-17 14:52:34 +01002967static int hdspm_input_select(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002968{
2969 return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
2970}
2971
Takashi Iwai98274f02005-11-17 14:52:34 +01002972static int hdspm_set_input_select(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002973{
2974 if (out)
2975 hdspm->control_register |= HDSPM_InputSelect0;
2976 else
2977 hdspm->control_register &= ~HDSPM_InputSelect0;
2978 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2979
2980 return 0;
2981}
2982
Takashi Iwai98274f02005-11-17 14:52:34 +01002983static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
2984 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002985{
2986 static char *texts[] = { "optical", "coaxial" };
2987
2988 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2989 uinfo->count = 1;
2990 uinfo->value.enumerated.items = 2;
2991
2992 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2993 uinfo->value.enumerated.item =
2994 uinfo->value.enumerated.items - 1;
2995 strcpy(uinfo->value.enumerated.name,
2996 texts[uinfo->value.enumerated.item]);
2997
2998 return 0;
2999}
3000
Takashi Iwai98274f02005-11-17 14:52:34 +01003001static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
3002 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003003{
Takashi Iwai98274f02005-11-17 14:52:34 +01003004 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003005
3006 spin_lock_irq(&hdspm->lock);
3007 ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
3008 spin_unlock_irq(&hdspm->lock);
3009 return 0;
3010}
3011
Takashi Iwai98274f02005-11-17 14:52:34 +01003012static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
3013 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003014{
Takashi Iwai98274f02005-11-17 14:52:34 +01003015 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003016 int change;
3017 unsigned int val;
3018
3019 if (!snd_hdspm_use_is_exclusive(hdspm))
3020 return -EBUSY;
3021 val = ucontrol->value.integer.value[0] & 1;
3022 spin_lock_irq(&hdspm->lock);
3023 change = (int) val != hdspm_input_select(hdspm);
3024 hdspm_set_input_select(hdspm, val);
3025 spin_unlock_irq(&hdspm->lock);
3026 return change;
3027}
3028
Adrian Knoth0dca1792011-01-26 19:32:14 +01003029
Remy Bruno3cee5a62006-10-16 12:46:32 +02003030#define HDSPM_DS_WIRE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003031{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3032 .name = xname, \
3033 .index = xindex, \
3034 .info = snd_hdspm_info_ds_wire, \
3035 .get = snd_hdspm_get_ds_wire, \
3036 .put = snd_hdspm_put_ds_wire \
Remy Bruno3cee5a62006-10-16 12:46:32 +02003037}
3038
3039static int hdspm_ds_wire(struct hdspm * hdspm)
3040{
3041 return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
3042}
3043
3044static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
3045{
3046 if (ds)
3047 hdspm->control_register |= HDSPM_DS_DoubleWire;
3048 else
3049 hdspm->control_register &= ~HDSPM_DS_DoubleWire;
3050 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3051
3052 return 0;
3053}
3054
3055static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
3056 struct snd_ctl_elem_info *uinfo)
3057{
3058 static char *texts[] = { "Single", "Double" };
3059
3060 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3061 uinfo->count = 1;
3062 uinfo->value.enumerated.items = 2;
3063
3064 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3065 uinfo->value.enumerated.item =
3066 uinfo->value.enumerated.items - 1;
3067 strcpy(uinfo->value.enumerated.name,
3068 texts[uinfo->value.enumerated.item]);
3069
3070 return 0;
3071}
3072
3073static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
3074 struct snd_ctl_elem_value *ucontrol)
3075{
3076 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3077
3078 spin_lock_irq(&hdspm->lock);
3079 ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
3080 spin_unlock_irq(&hdspm->lock);
3081 return 0;
3082}
3083
3084static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
3085 struct snd_ctl_elem_value *ucontrol)
3086{
3087 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3088 int change;
3089 unsigned int val;
3090
3091 if (!snd_hdspm_use_is_exclusive(hdspm))
3092 return -EBUSY;
3093 val = ucontrol->value.integer.value[0] & 1;
3094 spin_lock_irq(&hdspm->lock);
3095 change = (int) val != hdspm_ds_wire(hdspm);
3096 hdspm_set_ds_wire(hdspm, val);
3097 spin_unlock_irq(&hdspm->lock);
3098 return change;
3099}
3100
Adrian Knoth0dca1792011-01-26 19:32:14 +01003101
Remy Bruno3cee5a62006-10-16 12:46:32 +02003102#define HDSPM_QS_WIRE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003103{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3104 .name = xname, \
3105 .index = xindex, \
3106 .info = snd_hdspm_info_qs_wire, \
3107 .get = snd_hdspm_get_qs_wire, \
3108 .put = snd_hdspm_put_qs_wire \
Remy Bruno3cee5a62006-10-16 12:46:32 +02003109}
3110
3111static int hdspm_qs_wire(struct hdspm * hdspm)
3112{
3113 if (hdspm->control_register & HDSPM_QS_DoubleWire)
3114 return 1;
3115 if (hdspm->control_register & HDSPM_QS_QuadWire)
3116 return 2;
3117 return 0;
3118}
3119
3120static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
3121{
3122 hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
3123 switch (mode) {
3124 case 0:
3125 break;
3126 case 1:
3127 hdspm->control_register |= HDSPM_QS_DoubleWire;
3128 break;
3129 case 2:
3130 hdspm->control_register |= HDSPM_QS_QuadWire;
3131 break;
3132 }
3133 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3134
3135 return 0;
3136}
3137
3138static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
3139 struct snd_ctl_elem_info *uinfo)
3140{
3141 static char *texts[] = { "Single", "Double", "Quad" };
3142
3143 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3144 uinfo->count = 1;
3145 uinfo->value.enumerated.items = 3;
3146
3147 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3148 uinfo->value.enumerated.item =
3149 uinfo->value.enumerated.items - 1;
3150 strcpy(uinfo->value.enumerated.name,
3151 texts[uinfo->value.enumerated.item]);
3152
3153 return 0;
3154}
3155
3156static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
3157 struct snd_ctl_elem_value *ucontrol)
3158{
3159 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3160
3161 spin_lock_irq(&hdspm->lock);
3162 ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
3163 spin_unlock_irq(&hdspm->lock);
3164 return 0;
3165}
3166
3167static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
3168 struct snd_ctl_elem_value *ucontrol)
3169{
3170 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3171 int change;
3172 int val;
3173
3174 if (!snd_hdspm_use_is_exclusive(hdspm))
3175 return -EBUSY;
3176 val = ucontrol->value.integer.value[0];
3177 if (val < 0)
3178 val = 0;
3179 if (val > 2)
3180 val = 2;
3181 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003182 change = val != hdspm_qs_wire(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003183 hdspm_set_qs_wire(hdspm, val);
3184 spin_unlock_irq(&hdspm->lock);
3185 return change;
3186}
3187
Adrian Knoth700d1ef2011-07-29 03:11:02 +02003188#define HDSPM_MADI_SPEEDMODE(xname, xindex) \
3189{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3190 .name = xname, \
3191 .index = xindex, \
3192 .info = snd_hdspm_info_madi_speedmode, \
3193 .get = snd_hdspm_get_madi_speedmode, \
3194 .put = snd_hdspm_put_madi_speedmode \
3195}
3196
3197static int hdspm_madi_speedmode(struct hdspm *hdspm)
3198{
3199 if (hdspm->control_register & HDSPM_QuadSpeed)
3200 return 2;
3201 if (hdspm->control_register & HDSPM_DoubleSpeed)
3202 return 1;
3203 return 0;
3204}
3205
3206static int hdspm_set_madi_speedmode(struct hdspm *hdspm, int mode)
3207{
3208 hdspm->control_register &= ~(HDSPM_DoubleSpeed | HDSPM_QuadSpeed);
3209 switch (mode) {
3210 case 0:
3211 break;
3212 case 1:
3213 hdspm->control_register |= HDSPM_DoubleSpeed;
3214 break;
3215 case 2:
3216 hdspm->control_register |= HDSPM_QuadSpeed;
3217 break;
3218 }
3219 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3220
3221 return 0;
3222}
3223
3224static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol,
3225 struct snd_ctl_elem_info *uinfo)
3226{
3227 static char *texts[] = { "Single", "Double", "Quad" };
3228
3229 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3230 uinfo->count = 1;
3231 uinfo->value.enumerated.items = 3;
3232
3233 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3234 uinfo->value.enumerated.item =
3235 uinfo->value.enumerated.items - 1;
3236 strcpy(uinfo->value.enumerated.name,
3237 texts[uinfo->value.enumerated.item]);
3238
3239 return 0;
3240}
3241
3242static int snd_hdspm_get_madi_speedmode(struct snd_kcontrol *kcontrol,
3243 struct snd_ctl_elem_value *ucontrol)
3244{
3245 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3246
3247 spin_lock_irq(&hdspm->lock);
3248 ucontrol->value.enumerated.item[0] = hdspm_madi_speedmode(hdspm);
3249 spin_unlock_irq(&hdspm->lock);
3250 return 0;
3251}
3252
3253static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol,
3254 struct snd_ctl_elem_value *ucontrol)
3255{
3256 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3257 int change;
3258 int val;
3259
3260 if (!snd_hdspm_use_is_exclusive(hdspm))
3261 return -EBUSY;
3262 val = ucontrol->value.integer.value[0];
3263 if (val < 0)
3264 val = 0;
3265 if (val > 2)
3266 val = 2;
3267 spin_lock_irq(&hdspm->lock);
3268 change = val != hdspm_madi_speedmode(hdspm);
3269 hdspm_set_madi_speedmode(hdspm, val);
3270 spin_unlock_irq(&hdspm->lock);
3271 return change;
3272}
Takashi Iwai763f3562005-06-03 11:25:34 +02003273
3274#define HDSPM_MIXER(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003275{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
3276 .name = xname, \
3277 .index = xindex, \
3278 .device = 0, \
3279 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
3280 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3281 .info = snd_hdspm_info_mixer, \
3282 .get = snd_hdspm_get_mixer, \
3283 .put = snd_hdspm_put_mixer \
Takashi Iwai763f3562005-06-03 11:25:34 +02003284}
3285
Takashi Iwai98274f02005-11-17 14:52:34 +01003286static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
3287 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003288{
3289 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3290 uinfo->count = 3;
3291 uinfo->value.integer.min = 0;
3292 uinfo->value.integer.max = 65535;
3293 uinfo->value.integer.step = 1;
3294 return 0;
3295}
3296
Takashi Iwai98274f02005-11-17 14:52:34 +01003297static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
3298 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003299{
Takashi Iwai98274f02005-11-17 14:52:34 +01003300 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003301 int source;
3302 int destination;
3303
3304 source = ucontrol->value.integer.value[0];
3305 if (source < 0)
3306 source = 0;
3307 else if (source >= 2 * HDSPM_MAX_CHANNELS)
3308 source = 2 * HDSPM_MAX_CHANNELS - 1;
3309
3310 destination = ucontrol->value.integer.value[1];
3311 if (destination < 0)
3312 destination = 0;
3313 else if (destination >= HDSPM_MAX_CHANNELS)
3314 destination = HDSPM_MAX_CHANNELS - 1;
3315
3316 spin_lock_irq(&hdspm->lock);
3317 if (source >= HDSPM_MAX_CHANNELS)
3318 ucontrol->value.integer.value[2] =
3319 hdspm_read_pb_gain(hdspm, destination,
3320 source - HDSPM_MAX_CHANNELS);
3321 else
3322 ucontrol->value.integer.value[2] =
3323 hdspm_read_in_gain(hdspm, destination, source);
3324
3325 spin_unlock_irq(&hdspm->lock);
3326
3327 return 0;
3328}
3329
Takashi Iwai98274f02005-11-17 14:52:34 +01003330static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
3331 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003332{
Takashi Iwai98274f02005-11-17 14:52:34 +01003333 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003334 int change;
3335 int source;
3336 int destination;
3337 int gain;
3338
3339 if (!snd_hdspm_use_is_exclusive(hdspm))
3340 return -EBUSY;
3341
3342 source = ucontrol->value.integer.value[0];
3343 destination = ucontrol->value.integer.value[1];
3344
3345 if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
3346 return -1;
3347 if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
3348 return -1;
3349
3350 gain = ucontrol->value.integer.value[2];
3351
3352 spin_lock_irq(&hdspm->lock);
3353
3354 if (source >= HDSPM_MAX_CHANNELS)
3355 change = gain != hdspm_read_pb_gain(hdspm, destination,
3356 source -
3357 HDSPM_MAX_CHANNELS);
3358 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003359 change = gain != hdspm_read_in_gain(hdspm, destination,
3360 source);
Takashi Iwai763f3562005-06-03 11:25:34 +02003361
3362 if (change) {
3363 if (source >= HDSPM_MAX_CHANNELS)
3364 hdspm_write_pb_gain(hdspm, destination,
3365 source - HDSPM_MAX_CHANNELS,
3366 gain);
3367 else
3368 hdspm_write_in_gain(hdspm, destination, source,
3369 gain);
3370 }
3371 spin_unlock_irq(&hdspm->lock);
3372
3373 return change;
3374}
3375
3376/* The simple mixer control(s) provide gain control for the
3377 basic 1:1 mappings of playback streams to output
Adrian Knoth0dca1792011-01-26 19:32:14 +01003378 streams.
Takashi Iwai763f3562005-06-03 11:25:34 +02003379*/
3380
3381#define HDSPM_PLAYBACK_MIXER \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003382{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3383 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
3384 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3385 .info = snd_hdspm_info_playback_mixer, \
3386 .get = snd_hdspm_get_playback_mixer, \
3387 .put = snd_hdspm_put_playback_mixer \
Takashi Iwai763f3562005-06-03 11:25:34 +02003388}
3389
Takashi Iwai98274f02005-11-17 14:52:34 +01003390static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
3391 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003392{
3393 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3394 uinfo->count = 1;
3395 uinfo->value.integer.min = 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003396 uinfo->value.integer.max = 64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003397 uinfo->value.integer.step = 1;
3398 return 0;
3399}
3400
Takashi Iwai98274f02005-11-17 14:52:34 +01003401static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
3402 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003403{
Takashi Iwai98274f02005-11-17 14:52:34 +01003404 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003405 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003406
3407 channel = ucontrol->id.index - 1;
3408
Takashi Iwaida3cec32008-08-08 17:12:14 +02003409 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3410 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003411
Takashi Iwai763f3562005-06-03 11:25:34 +02003412 spin_lock_irq(&hdspm->lock);
3413 ucontrol->value.integer.value[0] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003414 (hdspm_read_pb_gain(hdspm, channel, channel)*64)/UNITY_GAIN;
Takashi Iwai763f3562005-06-03 11:25:34 +02003415 spin_unlock_irq(&hdspm->lock);
3416
Takashi Iwai763f3562005-06-03 11:25:34 +02003417 return 0;
3418}
3419
Takashi Iwai98274f02005-11-17 14:52:34 +01003420static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
3421 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003422{
Takashi Iwai98274f02005-11-17 14:52:34 +01003423 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003424 int change;
3425 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003426 int gain;
3427
3428 if (!snd_hdspm_use_is_exclusive(hdspm))
3429 return -EBUSY;
3430
3431 channel = ucontrol->id.index - 1;
3432
Takashi Iwaida3cec32008-08-08 17:12:14 +02003433 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3434 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003435
Adrian Knoth0dca1792011-01-26 19:32:14 +01003436 gain = ucontrol->value.integer.value[0]*UNITY_GAIN/64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003437
3438 spin_lock_irq(&hdspm->lock);
3439 change =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003440 gain != hdspm_read_pb_gain(hdspm, channel,
3441 channel);
Takashi Iwai763f3562005-06-03 11:25:34 +02003442 if (change)
Adrian Knoth0dca1792011-01-26 19:32:14 +01003443 hdspm_write_pb_gain(hdspm, channel, channel,
Takashi Iwai763f3562005-06-03 11:25:34 +02003444 gain);
3445 spin_unlock_irq(&hdspm->lock);
3446 return change;
3447}
3448
Adrian Knoth0dca1792011-01-26 19:32:14 +01003449#define HDSPM_SYNC_CHECK(xname, xindex) \
3450{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3451 .name = xname, \
3452 .private_value = xindex, \
3453 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3454 .info = snd_hdspm_info_sync_check, \
3455 .get = snd_hdspm_get_sync_check \
Takashi Iwai763f3562005-06-03 11:25:34 +02003456}
3457
Adrian Knoth0dca1792011-01-26 19:32:14 +01003458
Takashi Iwai98274f02005-11-17 14:52:34 +01003459static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
3460 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003461{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003462 static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" };
Takashi Iwai763f3562005-06-03 11:25:34 +02003463 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3464 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003465 uinfo->value.enumerated.items = 4;
Takashi Iwai763f3562005-06-03 11:25:34 +02003466 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3467 uinfo->value.enumerated.item =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003468 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02003469 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01003470 texts[uinfo->value.enumerated.item]);
Takashi Iwai763f3562005-06-03 11:25:34 +02003471 return 0;
3472}
3473
Adrian Knoth0dca1792011-01-26 19:32:14 +01003474static int hdspm_wc_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003475{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003476 int status, status2;
3477
3478 switch (hdspm->io_type) {
3479 case AES32:
3480 status = hdspm_read(hdspm, HDSPM_statusRegister);
Andre Schramm56bde0f2013-01-09 14:40:18 +01003481 if (status & HDSPM_AES32_wcLock) {
3482 if (status & HDSPM_AES32_wcSync)
3483 return 2;
3484 else
3485 return 1;
3486 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02003487 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003488 break;
3489
3490 case MADI:
3491 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003492 if (status2 & HDSPM_wcLock) {
3493 if (status2 & HDSPM_wcSync)
3494 return 2;
3495 else
3496 return 1;
3497 }
3498 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003499 break;
3500
3501 case RayDAT:
3502 case AIO:
3503 status = hdspm_read(hdspm, HDSPM_statusRegister);
3504
3505 if (status & 0x2000000)
3506 return 2;
3507 else if (status & 0x1000000)
3508 return 1;
3509 return 0;
3510
3511 break;
3512
3513 case MADIface:
3514 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02003515 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003516
Takashi Iwai763f3562005-06-03 11:25:34 +02003517
Adrian Knoth0dca1792011-01-26 19:32:14 +01003518 return 3;
Takashi Iwai763f3562005-06-03 11:25:34 +02003519}
3520
3521
Adrian Knoth0dca1792011-01-26 19:32:14 +01003522static int hdspm_madi_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003523{
3524 int status = hdspm_read(hdspm, HDSPM_statusRegister);
3525 if (status & HDSPM_madiLock) {
3526 if (status & HDSPM_madiSync)
3527 return 2;
3528 else
3529 return 1;
3530 }
3531 return 0;
3532}
3533
Adrian Knoth0dca1792011-01-26 19:32:14 +01003534
3535static int hdspm_s1_sync_check(struct hdspm *hdspm, int idx)
3536{
3537 int status, lock, sync;
3538
3539 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3540
3541 lock = (status & (0x1<<idx)) ? 1 : 0;
3542 sync = (status & (0x100<<idx)) ? 1 : 0;
3543
3544 if (lock && sync)
3545 return 2;
3546 else if (lock)
3547 return 1;
3548 return 0;
3549}
3550
3551
3552static int hdspm_sync_in_sync_check(struct hdspm *hdspm)
3553{
3554 int status, lock = 0, sync = 0;
3555
3556 switch (hdspm->io_type) {
3557 case RayDAT:
3558 case AIO:
3559 status = hdspm_read(hdspm, HDSPM_RD_STATUS_3);
3560 lock = (status & 0x400) ? 1 : 0;
3561 sync = (status & 0x800) ? 1 : 0;
3562 break;
3563
3564 case MADI:
Adrian Knoth2e0452f2012-10-19 17:42:27 +02003565 status = hdspm_read(hdspm, HDSPM_statusRegister);
3566 lock = (status & HDSPM_syncInLock) ? 1 : 0;
3567 sync = (status & HDSPM_syncInSync) ? 1 : 0;
3568 break;
3569
Adrian Knoth0dca1792011-01-26 19:32:14 +01003570 case AES32:
3571 status = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth9a215f42012-10-19 17:42:28 +02003572 lock = (status & 0x100000) ? 1 : 0;
3573 sync = (status & 0x200000) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003574 break;
3575
3576 case MADIface:
3577 break;
3578 }
3579
3580 if (lock && sync)
3581 return 2;
3582 else if (lock)
3583 return 1;
3584
3585 return 0;
3586}
3587
3588static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx)
3589{
3590 int status2, lock, sync;
3591 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
3592
3593 lock = (status2 & (0x0080 >> idx)) ? 1 : 0;
3594 sync = (status2 & (0x8000 >> idx)) ? 1 : 0;
3595
3596 if (sync)
3597 return 2;
3598 else if (lock)
3599 return 1;
3600 return 0;
3601}
3602
3603
3604static int hdspm_tco_sync_check(struct hdspm *hdspm)
3605{
3606 int status;
3607
3608 if (hdspm->tco) {
3609 switch (hdspm->io_type) {
3610 case MADI:
3611 case AES32:
3612 status = hdspm_read(hdspm, HDSPM_statusRegister);
3613 if (status & HDSPM_tcoLock) {
3614 if (status & HDSPM_tcoSync)
3615 return 2;
3616 else
3617 return 1;
3618 }
3619 return 0;
3620
3621 break;
3622
3623 case RayDAT:
3624 case AIO:
3625 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3626
3627 if (status & 0x8000000)
3628 return 2; /* Sync */
3629 if (status & 0x4000000)
3630 return 1; /* Lock */
3631 return 0; /* No signal */
3632 break;
3633
3634 default:
3635 break;
3636 }
3637 }
3638
3639 return 3; /* N/A */
3640}
3641
3642
3643static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
3644 struct snd_ctl_elem_value *ucontrol)
3645{
3646 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3647 int val = -1;
3648
3649 switch (hdspm->io_type) {
3650 case RayDAT:
3651 switch (kcontrol->private_value) {
3652 case 0: /* WC */
3653 val = hdspm_wc_sync_check(hdspm); break;
3654 case 7: /* TCO */
3655 val = hdspm_tco_sync_check(hdspm); break;
3656 case 8: /* SYNC IN */
3657 val = hdspm_sync_in_sync_check(hdspm); break;
3658 default:
Adrian Knothd1a3c982012-11-07 18:00:09 +01003659 val = hdspm_s1_sync_check(hdspm,
3660 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003661 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02003662 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003663
3664 case AIO:
3665 switch (kcontrol->private_value) {
3666 case 0: /* WC */
3667 val = hdspm_wc_sync_check(hdspm); break;
3668 case 4: /* TCO */
3669 val = hdspm_tco_sync_check(hdspm); break;
3670 case 5: /* SYNC IN */
3671 val = hdspm_sync_in_sync_check(hdspm); break;
3672 default:
3673 val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
3674 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02003675 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003676
3677 case MADI:
3678 switch (kcontrol->private_value) {
3679 case 0: /* WC */
3680 val = hdspm_wc_sync_check(hdspm); break;
3681 case 1: /* MADI */
3682 val = hdspm_madi_sync_check(hdspm); break;
3683 case 2: /* TCO */
3684 val = hdspm_tco_sync_check(hdspm); break;
3685 case 3: /* SYNC_IN */
3686 val = hdspm_sync_in_sync_check(hdspm); break;
3687 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02003688 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003689
3690 case MADIface:
3691 val = hdspm_madi_sync_check(hdspm); /* MADI */
3692 break;
3693
3694 case AES32:
3695 switch (kcontrol->private_value) {
3696 case 0: /* WC */
3697 val = hdspm_wc_sync_check(hdspm); break;
3698 case 9: /* TCO */
3699 val = hdspm_tco_sync_check(hdspm); break;
3700 case 10 /* SYNC IN */:
3701 val = hdspm_sync_in_sync_check(hdspm); break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01003702 default: /* AES1 to AES8 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01003703 val = hdspm_aes_sync_check(hdspm,
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01003704 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003705 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02003706 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003707
3708 }
3709
3710 if (-1 == val)
3711 val = 3;
3712
3713 ucontrol->value.enumerated.item[0] = val;
3714 return 0;
3715}
3716
3717
3718
3719/**
3720 * TCO controls
3721 **/
3722static void hdspm_tco_write(struct hdspm *hdspm)
3723{
3724 unsigned int tc[4] = { 0, 0, 0, 0};
3725
3726 switch (hdspm->tco->input) {
3727 case 0:
3728 tc[2] |= HDSPM_TCO2_set_input_MSB;
3729 break;
3730 case 1:
3731 tc[2] |= HDSPM_TCO2_set_input_LSB;
3732 break;
3733 default:
3734 break;
3735 }
3736
3737 switch (hdspm->tco->framerate) {
3738 case 1:
3739 tc[1] |= HDSPM_TCO1_LTC_Format_LSB;
3740 break;
3741 case 2:
3742 tc[1] |= HDSPM_TCO1_LTC_Format_MSB;
3743 break;
3744 case 3:
3745 tc[1] |= HDSPM_TCO1_LTC_Format_MSB +
3746 HDSPM_TCO1_set_drop_frame_flag;
3747 break;
3748 case 4:
3749 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
3750 HDSPM_TCO1_LTC_Format_MSB;
3751 break;
3752 case 5:
3753 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
3754 HDSPM_TCO1_LTC_Format_MSB +
3755 HDSPM_TCO1_set_drop_frame_flag;
3756 break;
3757 default:
3758 break;
3759 }
3760
3761 switch (hdspm->tco->wordclock) {
3762 case 1:
3763 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_LSB;
3764 break;
3765 case 2:
3766 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_MSB;
3767 break;
3768 default:
3769 break;
3770 }
3771
3772 switch (hdspm->tco->samplerate) {
3773 case 1:
3774 tc[2] |= HDSPM_TCO2_set_freq;
3775 break;
3776 case 2:
3777 tc[2] |= HDSPM_TCO2_set_freq_from_app;
3778 break;
3779 default:
3780 break;
3781 }
3782
3783 switch (hdspm->tco->pull) {
3784 case 1:
3785 tc[2] |= HDSPM_TCO2_set_pull_up;
3786 break;
3787 case 2:
3788 tc[2] |= HDSPM_TCO2_set_pull_down;
3789 break;
3790 case 3:
3791 tc[2] |= HDSPM_TCO2_set_pull_up + HDSPM_TCO2_set_01_4;
3792 break;
3793 case 4:
3794 tc[2] |= HDSPM_TCO2_set_pull_down + HDSPM_TCO2_set_01_4;
3795 break;
3796 default:
3797 break;
3798 }
3799
3800 if (1 == hdspm->tco->term) {
3801 tc[2] |= HDSPM_TCO2_set_term_75R;
3802 }
3803
3804 hdspm_write(hdspm, HDSPM_WR_TCO, tc[0]);
3805 hdspm_write(hdspm, HDSPM_WR_TCO+4, tc[1]);
3806 hdspm_write(hdspm, HDSPM_WR_TCO+8, tc[2]);
3807 hdspm_write(hdspm, HDSPM_WR_TCO+12, tc[3]);
3808}
3809
3810
3811#define HDSPM_TCO_SAMPLE_RATE(xname, xindex) \
3812{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3813 .name = xname, \
3814 .index = xindex, \
3815 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
3816 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3817 .info = snd_hdspm_info_tco_sample_rate, \
3818 .get = snd_hdspm_get_tco_sample_rate, \
3819 .put = snd_hdspm_put_tco_sample_rate \
3820}
3821
3822static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol,
3823 struct snd_ctl_elem_info *uinfo)
3824{
3825 static char *texts[] = { "44.1 kHz", "48 kHz" };
3826 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3827 uinfo->count = 1;
3828 uinfo->value.enumerated.items = 2;
3829
3830 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3831 uinfo->value.enumerated.item =
3832 uinfo->value.enumerated.items - 1;
3833
3834 strcpy(uinfo->value.enumerated.name,
3835 texts[uinfo->value.enumerated.item]);
3836
3837 return 0;
3838}
3839
3840static int snd_hdspm_get_tco_sample_rate(struct snd_kcontrol *kcontrol,
3841 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003842{
Takashi Iwai98274f02005-11-17 14:52:34 +01003843 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003844
Adrian Knoth0dca1792011-01-26 19:32:14 +01003845 ucontrol->value.enumerated.item[0] = hdspm->tco->samplerate;
3846
Takashi Iwai763f3562005-06-03 11:25:34 +02003847 return 0;
3848}
3849
Adrian Knoth0dca1792011-01-26 19:32:14 +01003850static int snd_hdspm_put_tco_sample_rate(struct snd_kcontrol *kcontrol,
3851 struct snd_ctl_elem_value *ucontrol)
Remy Bruno3cee5a62006-10-16 12:46:32 +02003852{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003853 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3854
3855 if (hdspm->tco->samplerate != ucontrol->value.enumerated.item[0]) {
3856 hdspm->tco->samplerate = ucontrol->value.enumerated.item[0];
3857
3858 hdspm_tco_write(hdspm);
3859
3860 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003861 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01003862
Remy Bruno3cee5a62006-10-16 12:46:32 +02003863 return 0;
3864}
3865
Adrian Knoth0dca1792011-01-26 19:32:14 +01003866
3867#define HDSPM_TCO_PULL(xname, xindex) \
3868{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3869 .name = xname, \
3870 .index = xindex, \
3871 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
3872 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3873 .info = snd_hdspm_info_tco_pull, \
3874 .get = snd_hdspm_get_tco_pull, \
3875 .put = snd_hdspm_put_tco_pull \
3876}
3877
3878static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol,
3879 struct snd_ctl_elem_info *uinfo)
3880{
3881 static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" };
3882 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3883 uinfo->count = 1;
3884 uinfo->value.enumerated.items = 5;
3885
3886 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3887 uinfo->value.enumerated.item =
3888 uinfo->value.enumerated.items - 1;
3889
3890 strcpy(uinfo->value.enumerated.name,
3891 texts[uinfo->value.enumerated.item]);
3892
3893 return 0;
3894}
3895
3896static int snd_hdspm_get_tco_pull(struct snd_kcontrol *kcontrol,
3897 struct snd_ctl_elem_value *ucontrol)
3898{
3899 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3900
3901 ucontrol->value.enumerated.item[0] = hdspm->tco->pull;
3902
3903 return 0;
3904}
3905
3906static int snd_hdspm_put_tco_pull(struct snd_kcontrol *kcontrol,
3907 struct snd_ctl_elem_value *ucontrol)
3908{
3909 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3910
3911 if (hdspm->tco->pull != ucontrol->value.enumerated.item[0]) {
3912 hdspm->tco->pull = ucontrol->value.enumerated.item[0];
3913
3914 hdspm_tco_write(hdspm);
3915
3916 return 1;
3917 }
3918
3919 return 0;
3920}
3921
3922#define HDSPM_TCO_WCK_CONVERSION(xname, xindex) \
3923{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3924 .name = xname, \
3925 .index = xindex, \
3926 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
3927 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3928 .info = snd_hdspm_info_tco_wck_conversion, \
3929 .get = snd_hdspm_get_tco_wck_conversion, \
3930 .put = snd_hdspm_put_tco_wck_conversion \
3931}
3932
3933static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol,
3934 struct snd_ctl_elem_info *uinfo)
3935{
3936 static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
3937 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3938 uinfo->count = 1;
3939 uinfo->value.enumerated.items = 3;
3940
3941 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3942 uinfo->value.enumerated.item =
3943 uinfo->value.enumerated.items - 1;
3944
3945 strcpy(uinfo->value.enumerated.name,
3946 texts[uinfo->value.enumerated.item]);
3947
3948 return 0;
3949}
3950
3951static int snd_hdspm_get_tco_wck_conversion(struct snd_kcontrol *kcontrol,
3952 struct snd_ctl_elem_value *ucontrol)
3953{
3954 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3955
3956 ucontrol->value.enumerated.item[0] = hdspm->tco->wordclock;
3957
3958 return 0;
3959}
3960
3961static int snd_hdspm_put_tco_wck_conversion(struct snd_kcontrol *kcontrol,
3962 struct snd_ctl_elem_value *ucontrol)
3963{
3964 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3965
3966 if (hdspm->tco->wordclock != ucontrol->value.enumerated.item[0]) {
3967 hdspm->tco->wordclock = ucontrol->value.enumerated.item[0];
3968
3969 hdspm_tco_write(hdspm);
3970
3971 return 1;
3972 }
3973
3974 return 0;
3975}
3976
3977
3978#define HDSPM_TCO_FRAME_RATE(xname, xindex) \
3979{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3980 .name = xname, \
3981 .index = xindex, \
3982 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
3983 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3984 .info = snd_hdspm_info_tco_frame_rate, \
3985 .get = snd_hdspm_get_tco_frame_rate, \
3986 .put = snd_hdspm_put_tco_frame_rate \
3987}
3988
3989static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol,
3990 struct snd_ctl_elem_info *uinfo)
3991{
3992 static char *texts[] = { "24 fps", "25 fps", "29.97fps",
3993 "29.97 dfps", "30 fps", "30 dfps" };
3994 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3995 uinfo->count = 1;
3996 uinfo->value.enumerated.items = 6;
3997
3998 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3999 uinfo->value.enumerated.item =
4000 uinfo->value.enumerated.items - 1;
4001
4002 strcpy(uinfo->value.enumerated.name,
4003 texts[uinfo->value.enumerated.item]);
4004
4005 return 0;
4006}
4007
4008static int snd_hdspm_get_tco_frame_rate(struct snd_kcontrol *kcontrol,
Remy Bruno3cee5a62006-10-16 12:46:32 +02004009 struct snd_ctl_elem_value *ucontrol)
4010{
Remy Bruno3cee5a62006-10-16 12:46:32 +02004011 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4012
Adrian Knoth0dca1792011-01-26 19:32:14 +01004013 ucontrol->value.enumerated.item[0] = hdspm->tco->framerate;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004014
Remy Bruno3cee5a62006-10-16 12:46:32 +02004015 return 0;
4016}
Takashi Iwai763f3562005-06-03 11:25:34 +02004017
Adrian Knoth0dca1792011-01-26 19:32:14 +01004018static int snd_hdspm_put_tco_frame_rate(struct snd_kcontrol *kcontrol,
4019 struct snd_ctl_elem_value *ucontrol)
4020{
4021 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4022
4023 if (hdspm->tco->framerate != ucontrol->value.enumerated.item[0]) {
4024 hdspm->tco->framerate = ucontrol->value.enumerated.item[0];
4025
4026 hdspm_tco_write(hdspm);
4027
4028 return 1;
4029 }
4030
4031 return 0;
4032}
4033
4034
4035#define HDSPM_TCO_SYNC_SOURCE(xname, xindex) \
4036{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4037 .name = xname, \
4038 .index = xindex, \
4039 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4040 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4041 .info = snd_hdspm_info_tco_sync_source, \
4042 .get = snd_hdspm_get_tco_sync_source, \
4043 .put = snd_hdspm_put_tco_sync_source \
4044}
4045
4046static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol,
4047 struct snd_ctl_elem_info *uinfo)
4048{
4049 static char *texts[] = { "LTC", "Video", "WCK" };
4050 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4051 uinfo->count = 1;
4052 uinfo->value.enumerated.items = 3;
4053
4054 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4055 uinfo->value.enumerated.item =
4056 uinfo->value.enumerated.items - 1;
4057
4058 strcpy(uinfo->value.enumerated.name,
4059 texts[uinfo->value.enumerated.item]);
4060
4061 return 0;
4062}
4063
4064static int snd_hdspm_get_tco_sync_source(struct snd_kcontrol *kcontrol,
4065 struct snd_ctl_elem_value *ucontrol)
4066{
4067 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4068
4069 ucontrol->value.enumerated.item[0] = hdspm->tco->input;
4070
4071 return 0;
4072}
4073
4074static int snd_hdspm_put_tco_sync_source(struct snd_kcontrol *kcontrol,
4075 struct snd_ctl_elem_value *ucontrol)
4076{
4077 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4078
4079 if (hdspm->tco->input != ucontrol->value.enumerated.item[0]) {
4080 hdspm->tco->input = ucontrol->value.enumerated.item[0];
4081
4082 hdspm_tco_write(hdspm);
4083
4084 return 1;
4085 }
4086
4087 return 0;
4088}
4089
4090
4091#define HDSPM_TCO_WORD_TERM(xname, xindex) \
4092{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4093 .name = xname, \
4094 .index = xindex, \
4095 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4096 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4097 .info = snd_hdspm_info_tco_word_term, \
4098 .get = snd_hdspm_get_tco_word_term, \
4099 .put = snd_hdspm_put_tco_word_term \
4100}
4101
4102static int snd_hdspm_info_tco_word_term(struct snd_kcontrol *kcontrol,
4103 struct snd_ctl_elem_info *uinfo)
4104{
4105 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
4106 uinfo->count = 1;
4107 uinfo->value.integer.min = 0;
4108 uinfo->value.integer.max = 1;
4109
4110 return 0;
4111}
4112
4113
4114static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol,
4115 struct snd_ctl_elem_value *ucontrol)
4116{
4117 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4118
4119 ucontrol->value.enumerated.item[0] = hdspm->tco->term;
4120
4121 return 0;
4122}
4123
4124
4125static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol,
4126 struct snd_ctl_elem_value *ucontrol)
4127{
4128 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4129
4130 if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) {
4131 hdspm->tco->term = ucontrol->value.enumerated.item[0];
4132
4133 hdspm_tco_write(hdspm);
4134
4135 return 1;
4136 }
4137
4138 return 0;
4139}
4140
4141
4142
Takashi Iwai763f3562005-06-03 11:25:34 +02004143
Remy Bruno3cee5a62006-10-16 12:46:32 +02004144static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004145 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004146 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Takashi Iwai763f3562005-06-03 11:25:34 +02004147 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4148 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4149 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4150 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Adrian Knothb8812c52012-10-19 17:42:26 +02004151 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004152 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4153 HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
Adrian Knoth930f4ff2012-10-19 17:42:29 +02004154 HDSPM_SYNC_CHECK("TCO SyncCheck", 2),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004155 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
Adrian Knothc9e16682012-12-03 14:55:50 +01004156 HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
4157 HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
4158 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
4159 HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
Adrian Knoth700d1ef2011-07-29 03:11:02 +02004160 HDSPM_INPUT_SELECT("Input Select", 0),
4161 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004162};
4163
4164
4165static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
4166 HDSPM_MIXER("Mixer", 0),
4167 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4168 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4169 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4170 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4171 HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
Adrian Knothc9e16682012-12-03 14:55:50 +01004172 HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
4173 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
4174 HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
Adrian Knoth700d1ef2011-07-29 03:11:02 +02004175 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004176};
4177
Adrian Knoth0dca1792011-01-26 19:32:14 +01004178static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004179 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004180 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004181 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4182 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4183 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4184 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004185 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004186 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4187 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4188 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4189 HDSPM_SYNC_CHECK("ADAT SyncCheck", 3),
4190 HDSPM_SYNC_CHECK("TCO SyncCheck", 4),
4191 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 5),
4192 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4193 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4194 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4195 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT Frequency", 3),
4196 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 4),
4197 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5)
4198
4199 /*
4200 HDSPM_INPUT_SELECT("Input Select", 0),
4201 HDSPM_SPDIF_OPTICAL("SPDIF Out Optical", 0),
4202 HDSPM_PROFESSIONAL("SPDIF Out Professional", 0);
4203 HDSPM_SPDIF_IN("SPDIF In", 0);
4204 HDSPM_BREAKOUT_CABLE("Breakout Cable", 0);
4205 HDSPM_INPUT_LEVEL("Input Level", 0);
4206 HDSPM_OUTPUT_LEVEL("Output Level", 0);
4207 HDSPM_PHONES("Phones", 0);
4208 */
4209};
4210
4211static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = {
4212 HDSPM_MIXER("Mixer", 0),
4213 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4214 HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0),
4215 HDSPM_PREF_SYNC_REF("Pref Sync Ref", 0),
4216 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4217 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4218 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4219 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4220 HDSPM_SYNC_CHECK("ADAT1 SyncCheck", 3),
4221 HDSPM_SYNC_CHECK("ADAT2 SyncCheck", 4),
4222 HDSPM_SYNC_CHECK("ADAT3 SyncCheck", 5),
4223 HDSPM_SYNC_CHECK("ADAT4 SyncCheck", 6),
4224 HDSPM_SYNC_CHECK("TCO SyncCheck", 7),
4225 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 8),
4226 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4227 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4228 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4229 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT1 Frequency", 3),
4230 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT2 Frequency", 4),
4231 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT3 Frequency", 5),
4232 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT4 Frequency", 6),
4233 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 7),
4234 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8)
4235};
4236
4237static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
4238 HDSPM_MIXER("Mixer", 0),
4239 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4240 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4241 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4242 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4243 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4244 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4245 HDSPM_SYNC_CHECK("WC Sync Check", 0),
4246 HDSPM_SYNC_CHECK("AES1 Sync Check", 1),
4247 HDSPM_SYNC_CHECK("AES2 Sync Check", 2),
4248 HDSPM_SYNC_CHECK("AES3 Sync Check", 3),
4249 HDSPM_SYNC_CHECK("AES4 Sync Check", 4),
4250 HDSPM_SYNC_CHECK("AES5 Sync Check", 5),
4251 HDSPM_SYNC_CHECK("AES6 Sync Check", 6),
4252 HDSPM_SYNC_CHECK("AES7 Sync Check", 7),
4253 HDSPM_SYNC_CHECK("AES8 Sync Check", 8),
4254 HDSPM_SYNC_CHECK("TCO Sync Check", 9),
4255 HDSPM_SYNC_CHECK("SYNC IN Sync Check", 10),
4256 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4257 HDSPM_AUTOSYNC_SAMPLE_RATE("AES1 Frequency", 1),
4258 HDSPM_AUTOSYNC_SAMPLE_RATE("AES2 Frequency", 2),
4259 HDSPM_AUTOSYNC_SAMPLE_RATE("AES3 Frequency", 3),
4260 HDSPM_AUTOSYNC_SAMPLE_RATE("AES4 Frequency", 4),
4261 HDSPM_AUTOSYNC_SAMPLE_RATE("AES5 Frequency", 5),
4262 HDSPM_AUTOSYNC_SAMPLE_RATE("AES6 Frequency", 6),
4263 HDSPM_AUTOSYNC_SAMPLE_RATE("AES7 Frequency", 7),
4264 HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8),
4265 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9),
4266 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10),
Adrian Knothc9e16682012-12-03 14:55:50 +01004267 HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
4268 HDSPM_TOGGLE_SETTING("Emphasis", HDSPM_Emphasis),
4269 HDSPM_TOGGLE_SETTING("Non Audio", HDSPM_Dolby),
4270 HDSPM_TOGGLE_SETTING("Professional", HDSPM_Professional),
4271 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004272 HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
4273 HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
4274};
4275
Adrian Knoth0dca1792011-01-26 19:32:14 +01004276
4277
4278/* Control elements for the optional TCO module */
4279static struct snd_kcontrol_new snd_hdspm_controls_tco[] = {
4280 HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0),
4281 HDSPM_TCO_PULL("TCO Pull", 0),
4282 HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0),
4283 HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0),
4284 HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0),
4285 HDSPM_TCO_WORD_TERM("TCO Word Term", 0)
4286};
4287
4288
Takashi Iwai98274f02005-11-17 14:52:34 +01004289static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
Takashi Iwai763f3562005-06-03 11:25:34 +02004290
4291
Takashi Iwai98274f02005-11-17 14:52:34 +01004292static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004293{
4294 int i;
4295
Adrian Knoth0dca1792011-01-26 19:32:14 +01004296 for (i = hdspm->ds_out_channels; i < hdspm->ss_out_channels; ++i) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004297 if (hdspm->system_sample_rate > 48000) {
4298 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004299 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
4300 SNDRV_CTL_ELEM_ACCESS_READ |
4301 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004302 } else {
4303 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004304 SNDRV_CTL_ELEM_ACCESS_READWRITE |
4305 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004306 }
4307 snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
Adrian Knoth0dca1792011-01-26 19:32:14 +01004308 SNDRV_CTL_EVENT_MASK_INFO,
4309 &hdspm->playback_mixer_ctls[i]->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02004310 }
4311
4312 return 0;
4313}
4314
4315
Adrian Knoth0dca1792011-01-26 19:32:14 +01004316static int snd_hdspm_create_controls(struct snd_card *card,
4317 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004318{
4319 unsigned int idx, limit;
4320 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01004321 struct snd_kcontrol *kctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004322 struct snd_kcontrol_new *list = NULL;
Takashi Iwai763f3562005-06-03 11:25:34 +02004323
Adrian Knoth0dca1792011-01-26 19:32:14 +01004324 switch (hdspm->io_type) {
4325 case MADI:
4326 list = snd_hdspm_controls_madi;
4327 limit = ARRAY_SIZE(snd_hdspm_controls_madi);
4328 break;
4329 case MADIface:
4330 list = snd_hdspm_controls_madiface;
4331 limit = ARRAY_SIZE(snd_hdspm_controls_madiface);
4332 break;
4333 case AIO:
4334 list = snd_hdspm_controls_aio;
4335 limit = ARRAY_SIZE(snd_hdspm_controls_aio);
4336 break;
4337 case RayDAT:
4338 list = snd_hdspm_controls_raydat;
4339 limit = ARRAY_SIZE(snd_hdspm_controls_raydat);
4340 break;
4341 case AES32:
4342 list = snd_hdspm_controls_aes32;
4343 limit = ARRAY_SIZE(snd_hdspm_controls_aes32);
4344 break;
4345 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004346
Adrian Knoth0dca1792011-01-26 19:32:14 +01004347 if (NULL != list) {
4348 for (idx = 0; idx < limit; idx++) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004349 err = snd_ctl_add(card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004350 snd_ctl_new1(&list[idx], hdspm));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004351 if (err < 0)
4352 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004353 }
4354 }
4355
Takashi Iwai763f3562005-06-03 11:25:34 +02004356
Adrian Knoth0dca1792011-01-26 19:32:14 +01004357 /* create simple 1:1 playback mixer controls */
Takashi Iwai763f3562005-06-03 11:25:34 +02004358 snd_hdspm_playback_mixer.name = "Chn";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004359 if (hdspm->system_sample_rate >= 128000) {
4360 limit = hdspm->qs_out_channels;
4361 } else if (hdspm->system_sample_rate >= 64000) {
4362 limit = hdspm->ds_out_channels;
4363 } else {
4364 limit = hdspm->ss_out_channels;
4365 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004366 for (idx = 0; idx < limit; ++idx) {
4367 snd_hdspm_playback_mixer.index = idx + 1;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004368 kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm);
4369 err = snd_ctl_add(card, kctl);
4370 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004371 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004372 hdspm->playback_mixer_ctls[idx] = kctl;
4373 }
4374
Adrian Knoth0dca1792011-01-26 19:32:14 +01004375
4376 if (hdspm->tco) {
4377 /* add tco control elements */
4378 list = snd_hdspm_controls_tco;
4379 limit = ARRAY_SIZE(snd_hdspm_controls_tco);
4380 for (idx = 0; idx < limit; idx++) {
4381 err = snd_ctl_add(card,
4382 snd_ctl_new1(&list[idx], hdspm));
4383 if (err < 0)
4384 return err;
4385 }
4386 }
4387
Takashi Iwai763f3562005-06-03 11:25:34 +02004388 return 0;
4389}
4390
4391/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01004392 /proc interface
Takashi Iwai763f3562005-06-03 11:25:34 +02004393 ------------------------------------------------------------*/
4394
4395static void
Remy Bruno3cee5a62006-10-16 12:46:32 +02004396snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
4397 struct snd_info_buffer *buffer)
Takashi Iwai763f3562005-06-03 11:25:34 +02004398{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004399 struct hdspm *hdspm = entry->private_data;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004400 unsigned int status, status2, control, freq;
4401
Takashi Iwai763f3562005-06-03 11:25:34 +02004402 char *pref_sync_ref;
4403 char *autosync_ref;
4404 char *system_clock_mode;
Takashi Iwai763f3562005-06-03 11:25:34 +02004405 char *insel;
Takashi Iwai763f3562005-06-03 11:25:34 +02004406 int x, x2;
4407
Adrian Knoth0dca1792011-01-26 19:32:14 +01004408 /* TCO stuff */
4409 int a, ltc, frames, seconds, minutes, hours;
4410 unsigned int period;
4411 u64 freq_const = 0;
4412 u32 rate;
4413
Takashi Iwai763f3562005-06-03 11:25:34 +02004414 status = hdspm_read(hdspm, HDSPM_statusRegister);
4415 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004416 control = hdspm->control_register;
4417 freq = hdspm_read(hdspm, HDSPM_timecodeRegister);
Takashi Iwai763f3562005-06-03 11:25:34 +02004418
4419 snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004420 hdspm->card_name, hdspm->card->number + 1,
4421 hdspm->firmware_rev,
4422 (status2 & HDSPM_version0) |
4423 (status2 & HDSPM_version1) | (status2 &
4424 HDSPM_version2));
4425
4426 snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n",
4427 (hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF,
Adrian Knoth7d53a632012-01-04 14:31:16 +01004428 hdspm->serial);
Takashi Iwai763f3562005-06-03 11:25:34 +02004429
4430 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004431 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
Takashi Iwai763f3562005-06-03 11:25:34 +02004432
4433 snd_iprintf(buffer, "--- System ---\n");
4434
4435 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004436 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4437 status & HDSPM_audioIRQPending,
4438 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4439 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4440 hdspm->irq_count);
Takashi Iwai763f3562005-06-03 11:25:34 +02004441 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004442 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4443 "estimated= %ld (bytes)\n",
4444 ((status & HDSPM_BufferID) ? 1 : 0),
4445 (status & HDSPM_BufferPositionMask),
4446 (status & HDSPM_BufferPositionMask) %
4447 (2 * (int)hdspm->period_bytes),
4448 ((status & HDSPM_BufferPositionMask) - 64) %
4449 (2 * (int)hdspm->period_bytes),
4450 (long) hdspm_hw_pointer(hdspm) * 4);
Takashi Iwai763f3562005-06-03 11:25:34 +02004451
4452 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004453 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4454 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4455 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4456 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4457 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
Takashi Iwai763f3562005-06-03 11:25:34 +02004458 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004459 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4460 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4461 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4462 snd_iprintf(buffer,
4463 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4464 "status2=0x%x\n",
4465 hdspm->control_register, hdspm->control2_register,
4466 status, status2);
4467 if (status & HDSPM_tco_detect) {
4468 snd_iprintf(buffer, "TCO module detected.\n");
4469 a = hdspm_read(hdspm, HDSPM_RD_TCO+4);
4470 if (a & HDSPM_TCO1_LTC_Input_valid) {
4471 snd_iprintf(buffer, " LTC valid, ");
4472 switch (a & (HDSPM_TCO1_LTC_Format_LSB |
4473 HDSPM_TCO1_LTC_Format_MSB)) {
4474 case 0:
4475 snd_iprintf(buffer, "24 fps, ");
4476 break;
4477 case HDSPM_TCO1_LTC_Format_LSB:
4478 snd_iprintf(buffer, "25 fps, ");
4479 break;
4480 case HDSPM_TCO1_LTC_Format_MSB:
4481 snd_iprintf(buffer, "29.97 fps, ");
4482 break;
4483 default:
4484 snd_iprintf(buffer, "30 fps, ");
4485 break;
4486 }
4487 if (a & HDSPM_TCO1_set_drop_frame_flag) {
4488 snd_iprintf(buffer, "drop frame\n");
4489 } else {
4490 snd_iprintf(buffer, "full frame\n");
4491 }
4492 } else {
4493 snd_iprintf(buffer, " no LTC\n");
4494 }
4495 if (a & HDSPM_TCO1_Video_Input_Format_NTSC) {
4496 snd_iprintf(buffer, " Video: NTSC\n");
4497 } else if (a & HDSPM_TCO1_Video_Input_Format_PAL) {
4498 snd_iprintf(buffer, " Video: PAL\n");
4499 } else {
4500 snd_iprintf(buffer, " No video\n");
4501 }
4502 if (a & HDSPM_TCO1_TCO_lock) {
4503 snd_iprintf(buffer, " Sync: lock\n");
4504 } else {
4505 snd_iprintf(buffer, " Sync: no lock\n");
4506 }
4507
4508 switch (hdspm->io_type) {
4509 case MADI:
4510 case AES32:
4511 freq_const = 110069313433624ULL;
4512 break;
4513 case RayDAT:
4514 case AIO:
4515 freq_const = 104857600000000ULL;
4516 break;
4517 case MADIface:
4518 break; /* no TCO possible */
4519 }
4520
4521 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
4522 snd_iprintf(buffer, " period: %u\n", period);
4523
4524
4525 /* rate = freq_const/period; */
4526 rate = div_u64(freq_const, period);
4527
4528 if (control & HDSPM_QuadSpeed) {
4529 rate *= 4;
4530 } else if (control & HDSPM_DoubleSpeed) {
4531 rate *= 2;
4532 }
4533
4534 snd_iprintf(buffer, " Frequency: %u Hz\n",
4535 (unsigned int) rate);
4536
4537 ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
4538 frames = ltc & 0xF;
4539 ltc >>= 4;
4540 frames += (ltc & 0x3) * 10;
4541 ltc >>= 4;
4542 seconds = ltc & 0xF;
4543 ltc >>= 4;
4544 seconds += (ltc & 0x7) * 10;
4545 ltc >>= 4;
4546 minutes = ltc & 0xF;
4547 ltc >>= 4;
4548 minutes += (ltc & 0x7) * 10;
4549 ltc >>= 4;
4550 hours = ltc & 0xF;
4551 ltc >>= 4;
4552 hours += (ltc & 0x3) * 10;
4553 snd_iprintf(buffer,
4554 " LTC In: %02d:%02d:%02d:%02d\n",
4555 hours, minutes, seconds, frames);
4556
4557 } else {
4558 snd_iprintf(buffer, "No TCO module detected.\n");
4559 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004560
4561 snd_iprintf(buffer, "--- Settings ---\n");
4562
Adrian Knoth7cb155f2011-08-15 00:22:53 +02004563 x = hdspm_get_latency(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02004564
4565 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004566 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4567 x, (unsigned long) hdspm->period_bytes);
Takashi Iwai763f3562005-06-03 11:25:34 +02004568
Adrian Knoth0dca1792011-01-26 19:32:14 +01004569 snd_iprintf(buffer, "Line out: %s\n",
4570 (hdspm->control_register & HDSPM_LineOut) ? "on " : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004571
4572 switch (hdspm->control_register & HDSPM_InputMask) {
4573 case HDSPM_InputOptical:
4574 insel = "Optical";
4575 break;
4576 case HDSPM_InputCoaxial:
4577 insel = "Coaxial";
4578 break;
4579 default:
Masanari Iidaec8f53f2012-11-02 00:28:50 +09004580 insel = "Unknown";
Takashi Iwai763f3562005-06-03 11:25:34 +02004581 }
4582
Takashi Iwai763f3562005-06-03 11:25:34 +02004583 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004584 "ClearTrackMarker = %s, Transmit in %s Channel Mode, "
4585 "Auto Input %s\n",
4586 (hdspm->control_register & HDSPM_clr_tms) ? "on" : "off",
4587 (hdspm->control_register & HDSPM_TX_64ch) ? "64" : "56",
4588 (hdspm->control_register & HDSPM_AutoInp) ? "on" : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004589
Adrian Knoth0dca1792011-01-26 19:32:14 +01004590
Remy Bruno3cee5a62006-10-16 12:46:32 +02004591 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
Adrian Knoth0dca1792011-01-26 19:32:14 +01004592 system_clock_mode = "AutoSync";
Remy Bruno3cee5a62006-10-16 12:46:32 +02004593 else
Takashi Iwai763f3562005-06-03 11:25:34 +02004594 system_clock_mode = "Master";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004595 snd_iprintf(buffer, "AutoSync Reference: %s\n", system_clock_mode);
Takashi Iwai763f3562005-06-03 11:25:34 +02004596
4597 switch (hdspm_pref_sync_ref(hdspm)) {
4598 case HDSPM_SYNC_FROM_WORD:
4599 pref_sync_ref = "Word Clock";
4600 break;
4601 case HDSPM_SYNC_FROM_MADI:
4602 pref_sync_ref = "MADI Sync";
4603 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004604 case HDSPM_SYNC_FROM_TCO:
4605 pref_sync_ref = "TCO";
4606 break;
4607 case HDSPM_SYNC_FROM_SYNC_IN:
4608 pref_sync_ref = "Sync In";
4609 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004610 default:
4611 pref_sync_ref = "XXXX Clock";
4612 break;
4613 }
4614 snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004615 pref_sync_ref);
Takashi Iwai763f3562005-06-03 11:25:34 +02004616
4617 snd_iprintf(buffer, "System Clock Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004618 hdspm->system_sample_rate);
Takashi Iwai763f3562005-06-03 11:25:34 +02004619
4620
4621 snd_iprintf(buffer, "--- Status:\n");
4622
4623 x = status & HDSPM_madiSync;
4624 x2 = status2 & HDSPM_wcSync;
4625
4626 snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004627 (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
4628 "NoLock",
4629 (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
4630 "NoLock");
Takashi Iwai763f3562005-06-03 11:25:34 +02004631
4632 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004633 case HDSPM_AUTOSYNC_FROM_SYNC_IN:
4634 autosync_ref = "Sync In";
4635 break;
4636 case HDSPM_AUTOSYNC_FROM_TCO:
4637 autosync_ref = "TCO";
4638 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004639 case HDSPM_AUTOSYNC_FROM_WORD:
4640 autosync_ref = "Word Clock";
4641 break;
4642 case HDSPM_AUTOSYNC_FROM_MADI:
4643 autosync_ref = "MADI Sync";
4644 break;
4645 case HDSPM_AUTOSYNC_FROM_NONE:
4646 autosync_ref = "Input not valid";
4647 break;
4648 default:
4649 autosync_ref = "---";
4650 break;
4651 }
4652 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004653 "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
4654 autosync_ref, hdspm_external_sample_rate(hdspm),
4655 (status & HDSPM_madiFreqMask) >> 22,
4656 (status2 & HDSPM_wcFreqMask) >> 5);
Takashi Iwai763f3562005-06-03 11:25:34 +02004657
4658 snd_iprintf(buffer, "Input: %s, Mode=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004659 (status & HDSPM_AB_int) ? "Coax" : "Optical",
4660 (status & HDSPM_RX_64ch) ? "64 channels" :
4661 "56 channels");
Takashi Iwai763f3562005-06-03 11:25:34 +02004662
4663 snd_iprintf(buffer, "\n");
4664}
4665
Remy Bruno3cee5a62006-10-16 12:46:32 +02004666static void
4667snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
4668 struct snd_info_buffer *buffer)
4669{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004670 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004671 unsigned int status;
4672 unsigned int status2;
4673 unsigned int timecode;
Andre Schramm56bde0f2013-01-09 14:40:18 +01004674 unsigned int wcLock, wcSync;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004675 int pref_syncref;
4676 char *autosync_ref;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004677 int x;
4678
4679 status = hdspm_read(hdspm, HDSPM_statusRegister);
4680 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
4681 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
4682
4683 snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
4684 hdspm->card_name, hdspm->card->number + 1,
4685 hdspm->firmware_rev);
4686
4687 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
4688 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
4689
4690 snd_iprintf(buffer, "--- System ---\n");
4691
4692 snd_iprintf(buffer,
4693 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4694 status & HDSPM_audioIRQPending,
4695 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4696 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4697 hdspm->irq_count);
4698 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004699 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4700 "estimated= %ld (bytes)\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004701 ((status & HDSPM_BufferID) ? 1 : 0),
4702 (status & HDSPM_BufferPositionMask),
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004703 (status & HDSPM_BufferPositionMask) %
4704 (2 * (int)hdspm->period_bytes),
4705 ((status & HDSPM_BufferPositionMask) - 64) %
4706 (2 * (int)hdspm->period_bytes),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004707 (long) hdspm_hw_pointer(hdspm) * 4);
4708
4709 snd_iprintf(buffer,
4710 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4711 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4712 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4713 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4714 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
4715 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004716 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4717 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4718 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4719 snd_iprintf(buffer,
4720 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4721 "status2=0x%x\n",
4722 hdspm->control_register, hdspm->control2_register,
4723 status, status2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02004724
4725 snd_iprintf(buffer, "--- Settings ---\n");
4726
Adrian Knoth7cb155f2011-08-15 00:22:53 +02004727 x = hdspm_get_latency(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02004728
4729 snd_iprintf(buffer,
4730 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4731 x, (unsigned long) hdspm->period_bytes);
4732
Adrian Knoth0dca1792011-01-26 19:32:14 +01004733 snd_iprintf(buffer, "Line out: %s\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004734 (hdspm->
Adrian Knoth0dca1792011-01-26 19:32:14 +01004735 control_register & HDSPM_LineOut) ? "on " : "off");
Remy Bruno3cee5a62006-10-16 12:46:32 +02004736
4737 snd_iprintf(buffer,
4738 "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
4739 (hdspm->
4740 control_register & HDSPM_clr_tms) ? "on" : "off",
4741 (hdspm->
4742 control_register & HDSPM_Emphasis) ? "on" : "off",
4743 (hdspm->
4744 control_register & HDSPM_Dolby) ? "on" : "off");
4745
Remy Bruno3cee5a62006-10-16 12:46:32 +02004746
4747 pref_syncref = hdspm_pref_sync_ref(hdspm);
4748 if (pref_syncref == 0)
4749 snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
4750 else
4751 snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
4752 pref_syncref);
4753
4754 snd_iprintf(buffer, "System Clock Frequency: %d\n",
4755 hdspm->system_sample_rate);
4756
4757 snd_iprintf(buffer, "Double speed: %s\n",
4758 hdspm->control_register & HDSPM_DS_DoubleWire?
4759 "Double wire" : "Single wire");
4760 snd_iprintf(buffer, "Quad speed: %s\n",
4761 hdspm->control_register & HDSPM_QS_DoubleWire?
4762 "Double wire" :
4763 hdspm->control_register & HDSPM_QS_QuadWire?
4764 "Quad wire" : "Single wire");
4765
4766 snd_iprintf(buffer, "--- Status:\n");
4767
Andre Schramm56bde0f2013-01-09 14:40:18 +01004768 wcLock = status & HDSPM_AES32_wcLock;
4769 wcSync = wcLock && (status & HDSPM_AES32_wcSync);
4770
Remy Bruno3cee5a62006-10-16 12:46:32 +02004771 snd_iprintf(buffer, "Word: %s Frequency: %d\n",
Andre Schramm56bde0f2013-01-09 14:40:18 +01004772 (wcLock) ? (wcSync ? "Sync " : "Lock ") : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004773 HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004774
4775 for (x = 0; x < 8; x++) {
4776 snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004777 x+1,
4778 (status2 & (HDSPM_LockAES >> x)) ?
Adrian Knoth0dca1792011-01-26 19:32:14 +01004779 "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004780 HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004781 }
4782
4783 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004784 case HDSPM_AES32_AUTOSYNC_FROM_NONE:
4785 autosync_ref = "None"; break;
4786 case HDSPM_AES32_AUTOSYNC_FROM_WORD:
4787 autosync_ref = "Word Clock"; break;
4788 case HDSPM_AES32_AUTOSYNC_FROM_AES1:
4789 autosync_ref = "AES1"; break;
4790 case HDSPM_AES32_AUTOSYNC_FROM_AES2:
4791 autosync_ref = "AES2"; break;
4792 case HDSPM_AES32_AUTOSYNC_FROM_AES3:
4793 autosync_ref = "AES3"; break;
4794 case HDSPM_AES32_AUTOSYNC_FROM_AES4:
4795 autosync_ref = "AES4"; break;
4796 case HDSPM_AES32_AUTOSYNC_FROM_AES5:
4797 autosync_ref = "AES5"; break;
4798 case HDSPM_AES32_AUTOSYNC_FROM_AES6:
4799 autosync_ref = "AES6"; break;
4800 case HDSPM_AES32_AUTOSYNC_FROM_AES7:
4801 autosync_ref = "AES7"; break;
4802 case HDSPM_AES32_AUTOSYNC_FROM_AES8:
4803 autosync_ref = "AES8"; break;
4804 default:
4805 autosync_ref = "---"; break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004806 }
4807 snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
4808
4809 snd_iprintf(buffer, "\n");
4810}
4811
Adrian Knoth0dca1792011-01-26 19:32:14 +01004812static void
4813snd_hdspm_proc_read_raydat(struct snd_info_entry *entry,
4814 struct snd_info_buffer *buffer)
4815{
4816 struct hdspm *hdspm = entry->private_data;
4817 unsigned int status1, status2, status3, control, i;
4818 unsigned int lock, sync;
4819
4820 status1 = hdspm_read(hdspm, HDSPM_RD_STATUS_1); /* s1 */
4821 status2 = hdspm_read(hdspm, HDSPM_RD_STATUS_2); /* freq */
4822 status3 = hdspm_read(hdspm, HDSPM_RD_STATUS_3); /* s2 */
4823
4824 control = hdspm->control_register;
4825
4826 snd_iprintf(buffer, "STATUS1: 0x%08x\n", status1);
4827 snd_iprintf(buffer, "STATUS2: 0x%08x\n", status2);
4828 snd_iprintf(buffer, "STATUS3: 0x%08x\n", status3);
4829
4830
4831 snd_iprintf(buffer, "\n*** CLOCK MODE\n\n");
4832
4833 snd_iprintf(buffer, "Clock mode : %s\n",
4834 (hdspm_system_clock_mode(hdspm) == 0) ? "master" : "slave");
4835 snd_iprintf(buffer, "System frequency: %d Hz\n",
4836 hdspm_get_system_sample_rate(hdspm));
4837
4838 snd_iprintf(buffer, "\n*** INPUT STATUS\n\n");
4839
4840 lock = 0x1;
4841 sync = 0x100;
4842
4843 for (i = 0; i < 8; i++) {
4844 snd_iprintf(buffer, "s1_input %d: Lock %d, Sync %d, Freq %s\n",
4845 i,
4846 (status1 & lock) ? 1 : 0,
4847 (status1 & sync) ? 1 : 0,
4848 texts_freq[(status2 >> (i * 4)) & 0xF]);
4849
4850 lock = lock<<1;
4851 sync = sync<<1;
4852 }
4853
4854 snd_iprintf(buffer, "WC input: Lock %d, Sync %d, Freq %s\n",
4855 (status1 & 0x1000000) ? 1 : 0,
4856 (status1 & 0x2000000) ? 1 : 0,
4857 texts_freq[(status1 >> 16) & 0xF]);
4858
4859 snd_iprintf(buffer, "TCO input: Lock %d, Sync %d, Freq %s\n",
4860 (status1 & 0x4000000) ? 1 : 0,
4861 (status1 & 0x8000000) ? 1 : 0,
4862 texts_freq[(status1 >> 20) & 0xF]);
4863
4864 snd_iprintf(buffer, "SYNC IN: Lock %d, Sync %d, Freq %s\n",
4865 (status3 & 0x400) ? 1 : 0,
4866 (status3 & 0x800) ? 1 : 0,
4867 texts_freq[(status2 >> 12) & 0xF]);
4868
4869}
4870
Remy Bruno3cee5a62006-10-16 12:46:32 +02004871#ifdef CONFIG_SND_DEBUG
4872static void
Adrian Knoth0dca1792011-01-26 19:32:14 +01004873snd_hdspm_proc_read_debug(struct snd_info_entry *entry,
Remy Bruno3cee5a62006-10-16 12:46:32 +02004874 struct snd_info_buffer *buffer)
4875{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004876 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004877
4878 int j,i;
4879
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004880 for (i = 0; i < 256 /* 1024*64 */; i += j) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004881 snd_iprintf(buffer, "0x%08X: ", i);
4882 for (j = 0; j < 16; j += 4)
4883 snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
4884 snd_iprintf(buffer, "\n");
4885 }
4886}
4887#endif
4888
4889
Adrian Knoth0dca1792011-01-26 19:32:14 +01004890static void snd_hdspm_proc_ports_in(struct snd_info_entry *entry,
4891 struct snd_info_buffer *buffer)
4892{
4893 struct hdspm *hdspm = entry->private_data;
4894 int i;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004895
Adrian Knoth0dca1792011-01-26 19:32:14 +01004896 snd_iprintf(buffer, "# generated by hdspm\n");
4897
4898 for (i = 0; i < hdspm->max_channels_in; i++) {
4899 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_in[i]);
4900 }
4901}
4902
4903static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry,
4904 struct snd_info_buffer *buffer)
4905{
4906 struct hdspm *hdspm = entry->private_data;
4907 int i;
4908
4909 snd_iprintf(buffer, "# generated by hdspm\n");
4910
4911 for (i = 0; i < hdspm->max_channels_out; i++) {
4912 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_out[i]);
4913 }
4914}
4915
4916
Bill Pembertone23e7a12012-12-06 12:35:10 -05004917static void snd_hdspm_proc_init(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004918{
Takashi Iwai98274f02005-11-17 14:52:34 +01004919 struct snd_info_entry *entry;
Takashi Iwai763f3562005-06-03 11:25:34 +02004920
Adrian Knoth0dca1792011-01-26 19:32:14 +01004921 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) {
4922 switch (hdspm->io_type) {
4923 case AES32:
4924 snd_info_set_text_ops(entry, hdspm,
4925 snd_hdspm_proc_read_aes32);
4926 break;
4927 case MADI:
4928 snd_info_set_text_ops(entry, hdspm,
4929 snd_hdspm_proc_read_madi);
4930 break;
4931 case MADIface:
4932 /* snd_info_set_text_ops(entry, hdspm,
4933 snd_hdspm_proc_read_madiface); */
4934 break;
4935 case RayDAT:
4936 snd_info_set_text_ops(entry, hdspm,
4937 snd_hdspm_proc_read_raydat);
4938 break;
4939 case AIO:
4940 break;
4941 }
4942 }
4943
4944 if (!snd_card_proc_new(hdspm->card, "ports.in", &entry)) {
4945 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_in);
4946 }
4947
4948 if (!snd_card_proc_new(hdspm->card, "ports.out", &entry)) {
4949 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_out);
4950 }
4951
Remy Bruno3cee5a62006-10-16 12:46:32 +02004952#ifdef CONFIG_SND_DEBUG
4953 /* debug file to read all hdspm registers */
4954 if (!snd_card_proc_new(hdspm->card, "debug", &entry))
4955 snd_info_set_text_ops(entry, hdspm,
4956 snd_hdspm_proc_read_debug);
4957#endif
Takashi Iwai763f3562005-06-03 11:25:34 +02004958}
4959
4960/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01004961 hdspm intitialize
Takashi Iwai763f3562005-06-03 11:25:34 +02004962 ------------------------------------------------------------*/
4963
Takashi Iwai98274f02005-11-17 14:52:34 +01004964static int snd_hdspm_set_defaults(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004965{
Takashi Iwai763f3562005-06-03 11:25:34 +02004966 /* ASSUMPTION: hdspm->lock is either held, or there is no need to
Joe Perches561de312007-12-18 13:13:47 +01004967 hold it (e.g. during module initialization).
Adrian Knoth0dca1792011-01-26 19:32:14 +01004968 */
Takashi Iwai763f3562005-06-03 11:25:34 +02004969
4970 /* set defaults: */
4971
Adrian Knoth0dca1792011-01-26 19:32:14 +01004972 hdspm->settings_register = 0;
4973
4974 switch (hdspm->io_type) {
4975 case MADI:
4976 case MADIface:
4977 hdspm->control_register =
4978 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
4979 break;
4980
4981 case RayDAT:
4982 case AIO:
4983 hdspm->settings_register = 0x1 + 0x1000;
4984 /* Magic values are: LAT_0, LAT_2, Master, freq1, tx64ch, inp_0,
4985 * line_out */
4986 hdspm->control_register =
4987 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
4988 break;
4989
4990 case AES32:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004991 hdspm->control_register =
4992 HDSPM_ClockModeMaster | /* Master Cloack Mode on */
Adrian Knoth0dca1792011-01-26 19:32:14 +01004993 hdspm_encode_latency(7) | /* latency max=8192samples */
Remy Bruno3cee5a62006-10-16 12:46:32 +02004994 HDSPM_SyncRef0 | /* AES1 is syncclock */
4995 HDSPM_LineOut | /* Analog output in */
4996 HDSPM_Professional; /* Professional mode */
Adrian Knoth0dca1792011-01-26 19:32:14 +01004997 break;
4998 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004999
5000 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5001
Adrian Knoth0dca1792011-01-26 19:32:14 +01005002 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005003 /* No control2 register for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005004#ifdef SNDRV_BIG_ENDIAN
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005005 hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
Takashi Iwai763f3562005-06-03 11:25:34 +02005006#else
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005007 hdspm->control2_register = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005008#endif
5009
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005010 hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
5011 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005012 hdspm_compute_period_size(hdspm);
5013
5014 /* silence everything */
5015
5016 all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
5017
Adrian Knoth0dca1792011-01-26 19:32:14 +01005018 if (hdspm->io_type == AIO || hdspm->io_type == RayDAT) {
5019 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
Takashi Iwai763f3562005-06-03 11:25:34 +02005020 }
5021
5022 /* set a default rate so that the channel map is set up. */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005023 hdspm_set_rate(hdspm, 48000, 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02005024
5025 return 0;
5026}
5027
5028
5029/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005030 interrupt
Takashi Iwai763f3562005-06-03 11:25:34 +02005031 ------------------------------------------------------------*/
5032
David Howells7d12e782006-10-05 14:55:46 +01005033static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02005034{
Takashi Iwai98274f02005-11-17 14:52:34 +01005035 struct hdspm *hdspm = (struct hdspm *) dev_id;
Takashi Iwai763f3562005-06-03 11:25:34 +02005036 unsigned int status;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005037 int i, audio, midi, schedule = 0;
5038 /* cycles_t now; */
Takashi Iwai763f3562005-06-03 11:25:34 +02005039
5040 status = hdspm_read(hdspm, HDSPM_statusRegister);
5041
5042 audio = status & HDSPM_audioIRQPending;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005043 midi = status & (HDSPM_midi0IRQPending | HDSPM_midi1IRQPending |
5044 HDSPM_midi2IRQPending | HDSPM_midi3IRQPending);
Takashi Iwai763f3562005-06-03 11:25:34 +02005045
Adrian Knoth0dca1792011-01-26 19:32:14 +01005046 /* now = get_cycles(); */
5047 /**
5048 * LAT_2..LAT_0 period counter (win) counter (mac)
5049 * 6 4096 ~256053425 ~514672358
5050 * 5 2048 ~128024983 ~257373821
5051 * 4 1024 ~64023706 ~128718089
5052 * 3 512 ~32005945 ~64385999
5053 * 2 256 ~16003039 ~32260176
5054 * 1 128 ~7998738 ~16194507
5055 * 0 64 ~3998231 ~8191558
5056 **/
5057 /*
5058 snd_printk(KERN_INFO "snd_hdspm_interrupt %llu @ %llx\n",
5059 now-hdspm->last_interrupt, status & 0xFFC0);
5060 hdspm->last_interrupt = now;
5061 */
5062
5063 if (!audio && !midi)
Takashi Iwai763f3562005-06-03 11:25:34 +02005064 return IRQ_NONE;
5065
5066 hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
5067 hdspm->irq_count++;
5068
Takashi Iwai763f3562005-06-03 11:25:34 +02005069
5070 if (audio) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005071 if (hdspm->capture_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005072 snd_pcm_period_elapsed(hdspm->capture_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005073
5074 if (hdspm->playback_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005075 snd_pcm_period_elapsed(hdspm->playback_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005076 }
5077
Adrian Knoth0dca1792011-01-26 19:32:14 +01005078 if (midi) {
5079 i = 0;
5080 while (i < hdspm->midiPorts) {
5081 if ((hdspm_read(hdspm,
5082 hdspm->midi[i].statusIn) & 0xff) &&
5083 (status & hdspm->midi[i].irq)) {
5084 /* we disable interrupts for this input until
5085 * processing is done
5086 */
5087 hdspm->control_register &= ~hdspm->midi[i].ie;
5088 hdspm_write(hdspm, HDSPM_controlRegister,
5089 hdspm->control_register);
5090 hdspm->midi[i].pending = 1;
5091 schedule = 1;
5092 }
5093
5094 i++;
5095 }
5096
5097 if (schedule)
5098 tasklet_hi_schedule(&hdspm->midi_tasklet);
Takashi Iwai763f3562005-06-03 11:25:34 +02005099 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005100
Takashi Iwai763f3562005-06-03 11:25:34 +02005101 return IRQ_HANDLED;
5102}
5103
5104/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005105 pcm interface
Takashi Iwai763f3562005-06-03 11:25:34 +02005106 ------------------------------------------------------------*/
5107
5108
Adrian Knoth0dca1792011-01-26 19:32:14 +01005109static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream
5110 *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005111{
Takashi Iwai98274f02005-11-17 14:52:34 +01005112 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005113 return hdspm_hw_pointer(hdspm);
5114}
5115
Takashi Iwai763f3562005-06-03 11:25:34 +02005116
Takashi Iwai98274f02005-11-17 14:52:34 +01005117static int snd_hdspm_reset(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005118{
Takashi Iwai98274f02005-11-17 14:52:34 +01005119 struct snd_pcm_runtime *runtime = substream->runtime;
5120 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5121 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005122
5123 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5124 other = hdspm->capture_substream;
5125 else
5126 other = hdspm->playback_substream;
5127
5128 if (hdspm->running)
5129 runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
5130 else
5131 runtime->status->hw_ptr = 0;
5132 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005133 struct snd_pcm_substream *s;
5134 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01005135 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005136 if (s == other) {
5137 oruntime->status->hw_ptr =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005138 runtime->status->hw_ptr;
Takashi Iwai763f3562005-06-03 11:25:34 +02005139 break;
5140 }
5141 }
5142 }
5143 return 0;
5144}
5145
Takashi Iwai98274f02005-11-17 14:52:34 +01005146static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
5147 struct snd_pcm_hw_params *params)
Takashi Iwai763f3562005-06-03 11:25:34 +02005148{
Takashi Iwai98274f02005-11-17 14:52:34 +01005149 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005150 int err;
5151 int i;
5152 pid_t this_pid;
5153 pid_t other_pid;
Takashi Iwai763f3562005-06-03 11:25:34 +02005154
5155 spin_lock_irq(&hdspm->lock);
5156
5157 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5158 this_pid = hdspm->playback_pid;
5159 other_pid = hdspm->capture_pid;
5160 } else {
5161 this_pid = hdspm->capture_pid;
5162 other_pid = hdspm->playback_pid;
5163 }
5164
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005165 if (other_pid > 0 && this_pid != other_pid) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005166
5167 /* The other stream is open, and not by the same
5168 task as this one. Make sure that the parameters
5169 that matter are the same.
Adrian Knoth0dca1792011-01-26 19:32:14 +01005170 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005171
5172 if (params_rate(params) != hdspm->system_sample_rate) {
5173 spin_unlock_irq(&hdspm->lock);
5174 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005175 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005176 return -EBUSY;
5177 }
5178
5179 if (params_period_size(params) != hdspm->period_bytes / 4) {
5180 spin_unlock_irq(&hdspm->lock);
5181 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005182 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005183 return -EBUSY;
5184 }
5185
5186 }
5187 /* We're fine. */
5188 spin_unlock_irq(&hdspm->lock);
5189
5190 /* how to make sure that the rate matches an externally-set one ? */
5191
5192 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005193 err = hdspm_set_rate(hdspm, params_rate(params), 0);
5194 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005195 snd_printk(KERN_INFO "err on hdspm_set_rate: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005196 spin_unlock_irq(&hdspm->lock);
5197 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005198 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005199 return err;
5200 }
5201 spin_unlock_irq(&hdspm->lock);
5202
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005203 err = hdspm_set_interrupt_interval(hdspm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005204 params_period_size(params));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005205 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005206 snd_printk(KERN_INFO "err on hdspm_set_interrupt_interval: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005207 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005208 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005209 return err;
5210 }
5211
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005212 /* Memory allocation, takashi's method, dont know if we should
5213 * spinlock
5214 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005215 /* malloc all buffer even if not enabled to get sure */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005216 /* Update for MADI rev 204: we need to allocate for all channels,
5217 * otherwise it doesn't work at 96kHz */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005218
Takashi Iwai763f3562005-06-03 11:25:34 +02005219 err =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005220 snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
5221 if (err < 0) {
5222 snd_printk(KERN_INFO "err on snd_pcm_lib_malloc_pages: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005223 return err;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005224 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005225
Takashi Iwai763f3562005-06-03 11:25:34 +02005226 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5227
Takashi Iwai77a23f22008-08-21 13:00:13 +02005228 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferOut,
Takashi Iwai763f3562005-06-03 11:25:34 +02005229 params_channels(params));
5230
5231 for (i = 0; i < params_channels(params); ++i)
5232 snd_hdspm_enable_out(hdspm, i, 1);
5233
5234 hdspm->playback_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005235 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005236 snd_printdd("Allocated sample buffer for playback at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005237 hdspm->playback_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005238 } else {
Takashi Iwai77a23f22008-08-21 13:00:13 +02005239 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn,
Takashi Iwai763f3562005-06-03 11:25:34 +02005240 params_channels(params));
5241
5242 for (i = 0; i < params_channels(params); ++i)
5243 snd_hdspm_enable_in(hdspm, i, 1);
5244
5245 hdspm->capture_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005246 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005247 snd_printdd("Allocated sample buffer for capture at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005248 hdspm->capture_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005249 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005250
Remy Bruno3cee5a62006-10-16 12:46:32 +02005251 /*
5252 snd_printdd("Allocated sample buffer for %s at 0x%08X\n",
5253 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5254 "playback" : "capture",
Takashi Iwai77a23f22008-08-21 13:00:13 +02005255 snd_pcm_sgbuf_get_addr(substream, 0));
Adrian Knoth0dca1792011-01-26 19:32:14 +01005256 */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005257 /*
Adrian Knoth0dca1792011-01-26 19:32:14 +01005258 snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n",
5259 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5260 "playback" : "capture",
5261 params_rate(params), params_channels(params),
5262 params_buffer_size(params));
5263 */
5264
5265
5266 /* Switch to native float format if requested */
5267 if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) {
5268 if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT))
5269 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE float format.\n");
5270
5271 hdspm->control_register |= HDSPe_FLOAT_FORMAT;
5272 } else if (SNDRV_PCM_FORMAT_S32_LE == params_format(params)) {
5273 if (hdspm->control_register & HDSPe_FLOAT_FORMAT)
5274 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE integer format.\n");
5275
5276 hdspm->control_register &= ~HDSPe_FLOAT_FORMAT;
5277 }
5278 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5279
Takashi Iwai763f3562005-06-03 11:25:34 +02005280 return 0;
5281}
5282
Takashi Iwai98274f02005-11-17 14:52:34 +01005283static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005284{
5285 int i;
Takashi Iwai98274f02005-11-17 14:52:34 +01005286 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005287
5288 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5289
Adrian Knoth0dca1792011-01-26 19:32:14 +01005290 /* params_channels(params) should be enough,
Takashi Iwai763f3562005-06-03 11:25:34 +02005291 but to get sure in case of error */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005292 for (i = 0; i < hdspm->max_channels_out; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005293 snd_hdspm_enable_out(hdspm, i, 0);
5294
5295 hdspm->playback_buffer = NULL;
5296 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005297 for (i = 0; i < hdspm->max_channels_in; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005298 snd_hdspm_enable_in(hdspm, i, 0);
5299
5300 hdspm->capture_buffer = NULL;
5301
5302 }
5303
5304 snd_pcm_lib_free_pages(substream);
5305
5306 return 0;
5307}
5308
Adrian Knoth0dca1792011-01-26 19:32:14 +01005309
Takashi Iwai98274f02005-11-17 14:52:34 +01005310static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005311 struct snd_pcm_channel_info *info)
Takashi Iwai763f3562005-06-03 11:25:34 +02005312{
Takashi Iwai98274f02005-11-17 14:52:34 +01005313 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005314
Adrian Knoth0dca1792011-01-26 19:32:14 +01005315 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5316 if (snd_BUG_ON(info->channel >= hdspm->max_channels_out)) {
5317 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel out of range (%d)\n", info->channel);
5318 return -EINVAL;
5319 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005320
Adrian Knoth0dca1792011-01-26 19:32:14 +01005321 if (hdspm->channel_map_out[info->channel] < 0) {
5322 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel %d mapped out\n", info->channel);
5323 return -EINVAL;
5324 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005325
Adrian Knoth0dca1792011-01-26 19:32:14 +01005326 info->offset = hdspm->channel_map_out[info->channel] *
5327 HDSPM_CHANNEL_BUFFER_BYTES;
5328 } else {
5329 if (snd_BUG_ON(info->channel >= hdspm->max_channels_in)) {
5330 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel out of range (%d)\n", info->channel);
5331 return -EINVAL;
5332 }
5333
5334 if (hdspm->channel_map_in[info->channel] < 0) {
5335 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel %d mapped out\n", info->channel);
5336 return -EINVAL;
5337 }
5338
5339 info->offset = hdspm->channel_map_in[info->channel] *
5340 HDSPM_CHANNEL_BUFFER_BYTES;
5341 }
5342
Takashi Iwai763f3562005-06-03 11:25:34 +02005343 info->first = 0;
5344 info->step = 32;
5345 return 0;
5346}
5347
Adrian Knoth0dca1792011-01-26 19:32:14 +01005348
Takashi Iwai98274f02005-11-17 14:52:34 +01005349static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005350 unsigned int cmd, void *arg)
Takashi Iwai763f3562005-06-03 11:25:34 +02005351{
5352 switch (cmd) {
5353 case SNDRV_PCM_IOCTL1_RESET:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005354 return snd_hdspm_reset(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005355
5356 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Adrian Knoth0dca1792011-01-26 19:32:14 +01005357 {
5358 struct snd_pcm_channel_info *info = arg;
5359 return snd_hdspm_channel_info(substream, info);
5360 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005361 default:
5362 break;
5363 }
5364
5365 return snd_pcm_lib_ioctl(substream, cmd, arg);
5366}
5367
Takashi Iwai98274f02005-11-17 14:52:34 +01005368static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
Takashi Iwai763f3562005-06-03 11:25:34 +02005369{
Takashi Iwai98274f02005-11-17 14:52:34 +01005370 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5371 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005372 int running;
5373
5374 spin_lock(&hdspm->lock);
5375 running = hdspm->running;
5376 switch (cmd) {
5377 case SNDRV_PCM_TRIGGER_START:
5378 running |= 1 << substream->stream;
5379 break;
5380 case SNDRV_PCM_TRIGGER_STOP:
5381 running &= ~(1 << substream->stream);
5382 break;
5383 default:
5384 snd_BUG();
5385 spin_unlock(&hdspm->lock);
5386 return -EINVAL;
5387 }
5388 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5389 other = hdspm->capture_substream;
5390 else
5391 other = hdspm->playback_substream;
5392
5393 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005394 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01005395 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005396 if (s == other) {
5397 snd_pcm_trigger_done(s, substream);
5398 if (cmd == SNDRV_PCM_TRIGGER_START)
5399 running |= 1 << s->stream;
5400 else
5401 running &= ~(1 << s->stream);
5402 goto _ok;
5403 }
5404 }
5405 if (cmd == SNDRV_PCM_TRIGGER_START) {
5406 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005407 && substream->stream ==
5408 SNDRV_PCM_STREAM_CAPTURE)
Takashi Iwai763f3562005-06-03 11:25:34 +02005409 hdspm_silence_playback(hdspm);
5410 } else {
5411 if (running &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01005412 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Takashi Iwai763f3562005-06-03 11:25:34 +02005413 hdspm_silence_playback(hdspm);
5414 }
5415 } else {
5416 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
5417 hdspm_silence_playback(hdspm);
5418 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005419_ok:
Takashi Iwai763f3562005-06-03 11:25:34 +02005420 snd_pcm_trigger_done(substream, substream);
5421 if (!hdspm->running && running)
5422 hdspm_start_audio(hdspm);
5423 else if (hdspm->running && !running)
5424 hdspm_stop_audio(hdspm);
5425 hdspm->running = running;
5426 spin_unlock(&hdspm->lock);
5427
5428 return 0;
5429}
5430
Takashi Iwai98274f02005-11-17 14:52:34 +01005431static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005432{
5433 return 0;
5434}
5435
Takashi Iwai98274f02005-11-17 14:52:34 +01005436static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005437 .info = (SNDRV_PCM_INFO_MMAP |
5438 SNDRV_PCM_INFO_MMAP_VALID |
5439 SNDRV_PCM_INFO_NONINTERLEAVED |
5440 SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
5441 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5442 .rates = (SNDRV_PCM_RATE_32000 |
5443 SNDRV_PCM_RATE_44100 |
5444 SNDRV_PCM_RATE_48000 |
5445 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005446 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5447 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ),
Takashi Iwai763f3562005-06-03 11:25:34 +02005448 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005449 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005450 .channels_min = 1,
5451 .channels_max = HDSPM_MAX_CHANNELS,
5452 .buffer_bytes_max =
5453 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
Adrian Knoth1b6fa102011-08-15 00:22:51 +02005454 .period_bytes_min = (32 * 4),
Takashi Iwai52e6fb42011-08-15 10:40:59 +02005455 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005456 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005457 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005458 .fifo_size = 0
5459};
5460
Takashi Iwai98274f02005-11-17 14:52:34 +01005461static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005462 .info = (SNDRV_PCM_INFO_MMAP |
5463 SNDRV_PCM_INFO_MMAP_VALID |
5464 SNDRV_PCM_INFO_NONINTERLEAVED |
5465 SNDRV_PCM_INFO_SYNC_START),
5466 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5467 .rates = (SNDRV_PCM_RATE_32000 |
5468 SNDRV_PCM_RATE_44100 |
5469 SNDRV_PCM_RATE_48000 |
5470 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005471 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5472 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
Takashi Iwai763f3562005-06-03 11:25:34 +02005473 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005474 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005475 .channels_min = 1,
5476 .channels_max = HDSPM_MAX_CHANNELS,
5477 .buffer_bytes_max =
5478 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
Adrian Knoth1b6fa102011-08-15 00:22:51 +02005479 .period_bytes_min = (32 * 4),
Takashi Iwai52e6fb42011-08-15 10:40:59 +02005480 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005481 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005482 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005483 .fifo_size = 0
5484};
5485
Adrian Knoth0dca1792011-01-26 19:32:14 +01005486static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
5487 struct snd_pcm_hw_rule *rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005488{
Takashi Iwai98274f02005-11-17 14:52:34 +01005489 struct hdspm *hdspm = rule->private;
5490 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005491 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005492 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005493 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5494
Adrian Knoth0dca1792011-01-26 19:32:14 +01005495 if (r->min > 96000 && r->max <= 192000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005496 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005497 .min = hdspm->qs_in_channels,
5498 .max = hdspm->qs_in_channels,
5499 .integer = 1,
5500 };
5501 return snd_interval_refine(c, &t);
5502 } else if (r->min > 48000 && r->max <= 96000) {
5503 struct snd_interval t = {
5504 .min = hdspm->ds_in_channels,
5505 .max = hdspm->ds_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005506 .integer = 1,
5507 };
5508 return snd_interval_refine(c, &t);
5509 } else if (r->max < 64000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005510 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005511 .min = hdspm->ss_in_channels,
5512 .max = hdspm->ss_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005513 .integer = 1,
5514 };
5515 return snd_interval_refine(c, &t);
5516 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005517
Takashi Iwai763f3562005-06-03 11:25:34 +02005518 return 0;
5519}
5520
Adrian Knoth0dca1792011-01-26 19:32:14 +01005521static int snd_hdspm_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
Takashi Iwai98274f02005-11-17 14:52:34 +01005522 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005523{
Takashi Iwai98274f02005-11-17 14:52:34 +01005524 struct hdspm *hdspm = rule->private;
5525 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005526 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005527 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005528 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5529
Adrian Knoth0dca1792011-01-26 19:32:14 +01005530 if (r->min > 96000 && r->max <= 192000) {
5531 struct snd_interval t = {
5532 .min = hdspm->qs_out_channels,
5533 .max = hdspm->qs_out_channels,
5534 .integer = 1,
5535 };
5536 return snd_interval_refine(c, &t);
5537 } else if (r->min > 48000 && r->max <= 96000) {
5538 struct snd_interval t = {
5539 .min = hdspm->ds_out_channels,
5540 .max = hdspm->ds_out_channels,
5541 .integer = 1,
5542 };
5543 return snd_interval_refine(c, &t);
5544 } else if (r->max < 64000) {
5545 struct snd_interval t = {
5546 .min = hdspm->ss_out_channels,
5547 .max = hdspm->ss_out_channels,
5548 .integer = 1,
5549 };
5550 return snd_interval_refine(c, &t);
5551 } else {
5552 }
5553 return 0;
5554}
5555
5556static int snd_hdspm_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
5557 struct snd_pcm_hw_rule * rule)
5558{
5559 struct hdspm *hdspm = rule->private;
5560 struct snd_interval *c =
5561 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5562 struct snd_interval *r =
5563 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5564
5565 if (c->min >= hdspm->ss_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005566 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005567 .min = 32000,
5568 .max = 48000,
5569 .integer = 1,
5570 };
5571 return snd_interval_refine(r, &t);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005572 } else if (c->max <= hdspm->qs_in_channels) {
5573 struct snd_interval t = {
5574 .min = 128000,
5575 .max = 192000,
5576 .integer = 1,
5577 };
5578 return snd_interval_refine(r, &t);
5579 } else if (c->max <= hdspm->ds_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005580 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005581 .min = 64000,
5582 .max = 96000,
5583 .integer = 1,
5584 };
Takashi Iwai763f3562005-06-03 11:25:34 +02005585 return snd_interval_refine(r, &t);
5586 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005587
5588 return 0;
5589}
5590static int snd_hdspm_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
5591 struct snd_pcm_hw_rule *rule)
5592{
5593 struct hdspm *hdspm = rule->private;
5594 struct snd_interval *c =
5595 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5596 struct snd_interval *r =
5597 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5598
5599 if (c->min >= hdspm->ss_out_channels) {
5600 struct snd_interval t = {
5601 .min = 32000,
5602 .max = 48000,
5603 .integer = 1,
5604 };
5605 return snd_interval_refine(r, &t);
5606 } else if (c->max <= hdspm->qs_out_channels) {
5607 struct snd_interval t = {
5608 .min = 128000,
5609 .max = 192000,
5610 .integer = 1,
5611 };
5612 return snd_interval_refine(r, &t);
5613 } else if (c->max <= hdspm->ds_out_channels) {
5614 struct snd_interval t = {
5615 .min = 64000,
5616 .max = 96000,
5617 .integer = 1,
5618 };
5619 return snd_interval_refine(r, &t);
5620 }
5621
Takashi Iwai763f3562005-06-03 11:25:34 +02005622 return 0;
5623}
5624
Adrian Knoth0dca1792011-01-26 19:32:14 +01005625static int snd_hdspm_hw_rule_in_channels(struct snd_pcm_hw_params *params,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005626 struct snd_pcm_hw_rule *rule)
5627{
5628 unsigned int list[3];
5629 struct hdspm *hdspm = rule->private;
5630 struct snd_interval *c = hw_param_interval(params,
5631 SNDRV_PCM_HW_PARAM_CHANNELS);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005632
5633 list[0] = hdspm->qs_in_channels;
5634 list[1] = hdspm->ds_in_channels;
5635 list[2] = hdspm->ss_in_channels;
5636 return snd_interval_list(c, 3, list, 0);
5637}
5638
5639static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params,
5640 struct snd_pcm_hw_rule *rule)
5641{
5642 unsigned int list[3];
5643 struct hdspm *hdspm = rule->private;
5644 struct snd_interval *c = hw_param_interval(params,
5645 SNDRV_PCM_HW_PARAM_CHANNELS);
5646
5647 list[0] = hdspm->qs_out_channels;
5648 list[1] = hdspm->ds_out_channels;
5649 list[2] = hdspm->ss_out_channels;
5650 return snd_interval_list(c, 3, list, 0);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005651}
5652
5653
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005654static unsigned int hdspm_aes32_sample_rates[] = {
5655 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000
5656};
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005657
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005658static struct snd_pcm_hw_constraint_list
5659hdspm_hw_constraints_aes32_sample_rates = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005660 .count = ARRAY_SIZE(hdspm_aes32_sample_rates),
5661 .list = hdspm_aes32_sample_rates,
5662 .mask = 0
5663};
5664
Takashi Iwai98274f02005-11-17 14:52:34 +01005665static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005666{
Takashi Iwai98274f02005-11-17 14:52:34 +01005667 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5668 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02005669
Takashi Iwai763f3562005-06-03 11:25:34 +02005670 spin_lock_irq(&hdspm->lock);
5671
5672 snd_pcm_set_sync(substream);
5673
Adrian Knoth0dca1792011-01-26 19:32:14 +01005674
Takashi Iwai763f3562005-06-03 11:25:34 +02005675 runtime->hw = snd_hdspm_playback_subinfo;
5676
5677 if (hdspm->capture_substream == NULL)
5678 hdspm_stop_audio(hdspm);
5679
5680 hdspm->playback_pid = current->pid;
5681 hdspm->playback_substream = substream;
5682
5683 spin_unlock_irq(&hdspm->lock);
5684
5685 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Takashi Iwaid8776812011-08-15 10:45:42 +02005686 snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005687
Adrian Knoth0dca1792011-01-26 19:32:14 +01005688 switch (hdspm->io_type) {
5689 case AIO:
5690 case RayDAT:
Takashi Iwaid8776812011-08-15 10:45:42 +02005691 snd_pcm_hw_constraint_minmax(runtime,
5692 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5693 32, 4096);
5694 /* RayDAT & AIO have a fixed buffer of 16384 samples per channel */
5695 snd_pcm_hw_constraint_minmax(runtime,
5696 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
5697 16384, 16384);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005698 break;
5699
5700 default:
Takashi Iwaid8776812011-08-15 10:45:42 +02005701 snd_pcm_hw_constraint_minmax(runtime,
5702 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5703 64, 8192);
5704 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005705 }
5706
5707 if (AES32 == hdspm->io_type) {
Takashi Iwai3fa9e3d2011-08-15 10:42:23 +02005708 runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005709 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
5710 &hdspm_hw_constraints_aes32_sample_rates);
5711 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005712 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005713 snd_hdspm_hw_rule_rate_out_channels, hdspm,
5714 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005715 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01005716
5717 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5718 snd_hdspm_hw_rule_out_channels, hdspm,
5719 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
5720
5721 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5722 snd_hdspm_hw_rule_out_channels_rate, hdspm,
5723 SNDRV_PCM_HW_PARAM_RATE, -1);
5724
Takashi Iwai763f3562005-06-03 11:25:34 +02005725 return 0;
5726}
5727
Takashi Iwai98274f02005-11-17 14:52:34 +01005728static int snd_hdspm_playback_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005729{
Takashi Iwai98274f02005-11-17 14:52:34 +01005730 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005731
5732 spin_lock_irq(&hdspm->lock);
5733
5734 hdspm->playback_pid = -1;
5735 hdspm->playback_substream = NULL;
5736
5737 spin_unlock_irq(&hdspm->lock);
5738
5739 return 0;
5740}
5741
5742
Takashi Iwai98274f02005-11-17 14:52:34 +01005743static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005744{
Takashi Iwai98274f02005-11-17 14:52:34 +01005745 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5746 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02005747
5748 spin_lock_irq(&hdspm->lock);
5749 snd_pcm_set_sync(substream);
5750 runtime->hw = snd_hdspm_capture_subinfo;
5751
5752 if (hdspm->playback_substream == NULL)
5753 hdspm_stop_audio(hdspm);
5754
5755 hdspm->capture_pid = current->pid;
5756 hdspm->capture_substream = substream;
5757
5758 spin_unlock_irq(&hdspm->lock);
5759
5760 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Takashi Iwaid8776812011-08-15 10:45:42 +02005761 snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
5762
Adrian Knoth0dca1792011-01-26 19:32:14 +01005763 switch (hdspm->io_type) {
5764 case AIO:
5765 case RayDAT:
Takashi Iwaid8776812011-08-15 10:45:42 +02005766 snd_pcm_hw_constraint_minmax(runtime,
5767 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5768 32, 4096);
5769 snd_pcm_hw_constraint_minmax(runtime,
5770 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
5771 16384, 16384);
5772 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005773
5774 default:
Takashi Iwaid8776812011-08-15 10:45:42 +02005775 snd_pcm_hw_constraint_minmax(runtime,
5776 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5777 64, 8192);
5778 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005779 }
5780
5781 if (AES32 == hdspm->io_type) {
Takashi Iwai3fa9e3d2011-08-15 10:42:23 +02005782 runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005783 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
5784 &hdspm_hw_constraints_aes32_sample_rates);
5785 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005786 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth88fabbf2011-02-23 11:43:10 +01005787 snd_hdspm_hw_rule_rate_in_channels, hdspm,
5788 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005789 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01005790
5791 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5792 snd_hdspm_hw_rule_in_channels, hdspm,
5793 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
5794
5795 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5796 snd_hdspm_hw_rule_in_channels_rate, hdspm,
5797 SNDRV_PCM_HW_PARAM_RATE, -1);
5798
Takashi Iwai763f3562005-06-03 11:25:34 +02005799 return 0;
5800}
5801
Takashi Iwai98274f02005-11-17 14:52:34 +01005802static int snd_hdspm_capture_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005803{
Takashi Iwai98274f02005-11-17 14:52:34 +01005804 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005805
5806 spin_lock_irq(&hdspm->lock);
5807
5808 hdspm->capture_pid = -1;
5809 hdspm->capture_substream = NULL;
5810
5811 spin_unlock_irq(&hdspm->lock);
5812 return 0;
5813}
5814
Adrian Knoth0dca1792011-01-26 19:32:14 +01005815static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
Takashi Iwai763f3562005-06-03 11:25:34 +02005816{
Adrian Knoth0dca1792011-01-26 19:32:14 +01005817 /* we have nothing to initialize but the call is required */
5818 return 0;
5819}
5820
5821static inline int copy_u32_le(void __user *dest, void __iomem *src)
5822{
5823 u32 val = readl(src);
5824 return copy_to_user(dest, &val, 4);
5825}
5826
5827static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
Dan Carpenter2ca595a2011-09-23 09:25:05 +03005828 unsigned int cmd, unsigned long arg)
Adrian Knoth0dca1792011-01-26 19:32:14 +01005829{
5830 void __user *argp = (void __user *)arg;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005831 struct hdspm *hdspm = hw->private_data;
Takashi Iwai98274f02005-11-17 14:52:34 +01005832 struct hdspm_mixer_ioctl mixer;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005833 struct hdspm_config info;
5834 struct hdspm_status status;
Takashi Iwai98274f02005-11-17 14:52:34 +01005835 struct hdspm_version hdspm_version;
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005836 struct hdspm_peak_rms *levels;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005837 struct hdspm_ltc ltc;
5838 unsigned int statusregister;
5839 long unsigned int s;
5840 int i = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005841
5842 switch (cmd) {
5843
Takashi Iwai763f3562005-06-03 11:25:34 +02005844 case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005845 levels = &hdspm->peak_rms;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005846 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005847 levels->input_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005848 readl(hdspm->iobase +
5849 HDSPM_MADI_INPUT_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005850 levels->playback_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005851 readl(hdspm->iobase +
5852 HDSPM_MADI_PLAYBACK_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005853 levels->output_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005854 readl(hdspm->iobase +
5855 HDSPM_MADI_OUTPUT_PEAK + i*4);
5856
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005857 levels->input_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005858 ((uint64_t) readl(hdspm->iobase +
5859 HDSPM_MADI_INPUT_RMS_H + i*4) << 32) |
5860 (uint64_t) readl(hdspm->iobase +
5861 HDSPM_MADI_INPUT_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005862 levels->playback_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005863 ((uint64_t)readl(hdspm->iobase +
5864 HDSPM_MADI_PLAYBACK_RMS_H+i*4) << 32) |
5865 (uint64_t)readl(hdspm->iobase +
5866 HDSPM_MADI_PLAYBACK_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005867 levels->output_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005868 ((uint64_t)readl(hdspm->iobase +
5869 HDSPM_MADI_OUTPUT_RMS_H + i*4) << 32) |
5870 (uint64_t)readl(hdspm->iobase +
5871 HDSPM_MADI_OUTPUT_RMS_L + i*4);
5872 }
5873
5874 if (hdspm->system_sample_rate > 96000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005875 levels->speed = qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005876 } else if (hdspm->system_sample_rate > 48000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005877 levels->speed = ds;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005878 } else {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005879 levels->speed = ss;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005880 }
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005881 levels->status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005882
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005883 s = copy_to_user(argp, levels, sizeof(struct hdspm_peak_rms));
Adrian Knoth0dca1792011-01-26 19:32:14 +01005884 if (0 != s) {
5885 /* snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu
5886 [Levels]\n", sizeof(struct hdspm_peak_rms), s);
5887 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005888 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005889 }
5890 break;
5891
5892 case SNDRV_HDSPM_IOCTL_GET_LTC:
5893 ltc.ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
5894 i = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
5895 if (i & HDSPM_TCO1_LTC_Input_valid) {
5896 switch (i & (HDSPM_TCO1_LTC_Format_LSB |
5897 HDSPM_TCO1_LTC_Format_MSB)) {
5898 case 0:
5899 ltc.format = fps_24;
5900 break;
5901 case HDSPM_TCO1_LTC_Format_LSB:
5902 ltc.format = fps_25;
5903 break;
5904 case HDSPM_TCO1_LTC_Format_MSB:
5905 ltc.format = fps_2997;
5906 break;
5907 default:
5908 ltc.format = 30;
5909 break;
5910 }
5911 if (i & HDSPM_TCO1_set_drop_frame_flag) {
5912 ltc.frame = drop_frame;
5913 } else {
5914 ltc.frame = full_frame;
5915 }
5916 } else {
5917 ltc.format = format_invalid;
5918 ltc.frame = frame_invalid;
5919 }
5920 if (i & HDSPM_TCO1_Video_Input_Format_NTSC) {
5921 ltc.input_format = ntsc;
5922 } else if (i & HDSPM_TCO1_Video_Input_Format_PAL) {
5923 ltc.input_format = pal;
5924 } else {
5925 ltc.input_format = no_video;
5926 }
5927
5928 s = copy_to_user(argp, &ltc, sizeof(struct hdspm_ltc));
5929 if (0 != s) {
5930 /*
5931 snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */
Takashi Iwai763f3562005-06-03 11:25:34 +02005932 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005933 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005934
5935 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02005936
Adrian Knoth0dca1792011-01-26 19:32:14 +01005937 case SNDRV_HDSPM_IOCTL_GET_CONFIG:
Takashi Iwai763f3562005-06-03 11:25:34 +02005938
Adrian Knoth4ab69a22011-02-23 11:43:14 +01005939 memset(&info, 0, sizeof(info));
Takashi Iwai763f3562005-06-03 11:25:34 +02005940 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005941 info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
5942 info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02005943
5944 info.system_sample_rate = hdspm->system_sample_rate;
5945 info.autosync_sample_rate =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005946 hdspm_external_sample_rate(hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005947 info.system_clock_mode = hdspm_system_clock_mode(hdspm);
5948 info.clock_source = hdspm_clock_source(hdspm);
5949 info.autosync_ref = hdspm_autosync_ref(hdspm);
Adrian Knothc9e16682012-12-03 14:55:50 +01005950 info.line_out = hdspm_toggle_setting(hdspm, HDSPM_LineOut);
Takashi Iwai763f3562005-06-03 11:25:34 +02005951 info.passthru = 0;
5952 spin_unlock_irq(&hdspm->lock);
Dan Carpenter2ca595a2011-09-23 09:25:05 +03005953 if (copy_to_user(argp, &info, sizeof(info)))
Takashi Iwai763f3562005-06-03 11:25:34 +02005954 return -EFAULT;
5955 break;
5956
Adrian Knoth0dca1792011-01-26 19:32:14 +01005957 case SNDRV_HDSPM_IOCTL_GET_STATUS:
Dan Carpenter643d6bb2011-09-23 09:24:21 +03005958 memset(&status, 0, sizeof(status));
5959
Adrian Knoth0dca1792011-01-26 19:32:14 +01005960 status.card_type = hdspm->io_type;
5961
5962 status.autosync_source = hdspm_autosync_ref(hdspm);
5963
5964 status.card_clock = 110069313433624ULL;
5965 status.master_period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
5966
5967 switch (hdspm->io_type) {
5968 case MADI:
5969 case MADIface:
5970 status.card_specific.madi.sync_wc =
5971 hdspm_wc_sync_check(hdspm);
5972 status.card_specific.madi.sync_madi =
5973 hdspm_madi_sync_check(hdspm);
5974 status.card_specific.madi.sync_tco =
5975 hdspm_tco_sync_check(hdspm);
5976 status.card_specific.madi.sync_in =
5977 hdspm_sync_in_sync_check(hdspm);
5978
5979 statusregister =
5980 hdspm_read(hdspm, HDSPM_statusRegister);
5981 status.card_specific.madi.madi_input =
5982 (statusregister & HDSPM_AB_int) ? 1 : 0;
5983 status.card_specific.madi.channel_format =
Adrian Knoth9e6ff522011-10-27 21:57:52 +02005984 (statusregister & HDSPM_RX_64ch) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005985 /* TODO: Mac driver sets it when f_s>48kHz */
5986 status.card_specific.madi.frame_format = 0;
5987
5988 default:
5989 break;
5990 }
5991
Dan Carpenter2ca595a2011-09-23 09:25:05 +03005992 if (copy_to_user(argp, &status, sizeof(status)))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005993 return -EFAULT;
5994
5995
5996 break;
5997
Takashi Iwai763f3562005-06-03 11:25:34 +02005998 case SNDRV_HDSPM_IOCTL_GET_VERSION:
Dan Carpenter643d6bb2011-09-23 09:24:21 +03005999 memset(&hdspm_version, 0, sizeof(hdspm_version));
6000
Adrian Knoth0dca1792011-01-26 19:32:14 +01006001 hdspm_version.card_type = hdspm->io_type;
6002 strncpy(hdspm_version.cardname, hdspm->card_name,
6003 sizeof(hdspm_version.cardname));
Adrian Knoth7d53a632012-01-04 14:31:16 +01006004 hdspm_version.serial = hdspm->serial;
Takashi Iwai763f3562005-06-03 11:25:34 +02006005 hdspm_version.firmware_rev = hdspm->firmware_rev;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006006 hdspm_version.addons = 0;
6007 if (hdspm->tco)
6008 hdspm_version.addons |= HDSPM_ADDON_TCO;
6009
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006010 if (copy_to_user(argp, &hdspm_version,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006011 sizeof(hdspm_version)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006012 return -EFAULT;
6013 break;
6014
6015 case SNDRV_HDSPM_IOCTL_GET_MIXER:
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006016 if (copy_from_user(&mixer, argp, sizeof(mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006017 return -EFAULT;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006018 if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006019 sizeof(struct hdspm_mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006020 return -EFAULT;
6021 break;
6022
6023 default:
6024 return -EINVAL;
6025 }
6026 return 0;
6027}
6028
Takashi Iwai98274f02005-11-17 14:52:34 +01006029static struct snd_pcm_ops snd_hdspm_playback_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006030 .open = snd_hdspm_playback_open,
6031 .close = snd_hdspm_playback_release,
6032 .ioctl = snd_hdspm_ioctl,
6033 .hw_params = snd_hdspm_hw_params,
6034 .hw_free = snd_hdspm_hw_free,
6035 .prepare = snd_hdspm_prepare,
6036 .trigger = snd_hdspm_trigger,
6037 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006038 .page = snd_pcm_sgbuf_ops_page,
6039};
6040
Takashi Iwai98274f02005-11-17 14:52:34 +01006041static struct snd_pcm_ops snd_hdspm_capture_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006042 .open = snd_hdspm_capture_open,
6043 .close = snd_hdspm_capture_release,
6044 .ioctl = snd_hdspm_ioctl,
6045 .hw_params = snd_hdspm_hw_params,
6046 .hw_free = snd_hdspm_hw_free,
6047 .prepare = snd_hdspm_prepare,
6048 .trigger = snd_hdspm_trigger,
6049 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006050 .page = snd_pcm_sgbuf_ops_page,
6051};
6052
Bill Pembertone23e7a12012-12-06 12:35:10 -05006053static int snd_hdspm_create_hwdep(struct snd_card *card,
6054 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006055{
Takashi Iwai98274f02005-11-17 14:52:34 +01006056 struct snd_hwdep *hw;
Takashi Iwai763f3562005-06-03 11:25:34 +02006057 int err;
6058
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006059 err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw);
6060 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006061 return err;
6062
6063 hdspm->hwdep = hw;
6064 hw->private_data = hdspm;
6065 strcpy(hw->name, "HDSPM hwdep interface");
6066
Adrian Knoth0dca1792011-01-26 19:32:14 +01006067 hw->ops.open = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006068 hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
Adrian Knoth8de5d6f2012-03-08 15:38:04 +01006069 hw->ops.ioctl_compat = snd_hdspm_hwdep_ioctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006070 hw->ops.release = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006071
6072 return 0;
6073}
6074
6075
6076/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01006077 memory interface
Takashi Iwai763f3562005-06-03 11:25:34 +02006078 ------------------------------------------------------------*/
Bill Pembertone23e7a12012-12-06 12:35:10 -05006079static int snd_hdspm_preallocate_memory(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006080{
6081 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01006082 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006083 size_t wanted;
6084
6085 pcm = hdspm->pcm;
6086
Remy Bruno3cee5a62006-10-16 12:46:32 +02006087 wanted = HDSPM_DMA_AREA_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02006088
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006089 err =
Takashi Iwai763f3562005-06-03 11:25:34 +02006090 snd_pcm_lib_preallocate_pages_for_all(pcm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006091 SNDRV_DMA_TYPE_DEV_SG,
Takashi Iwai763f3562005-06-03 11:25:34 +02006092 snd_dma_pci_data(hdspm->pci),
6093 wanted,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006094 wanted);
6095 if (err < 0) {
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006096 snd_printdd("Could not preallocate %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006097
6098 return err;
6099 } else
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006100 snd_printdd(" Preallocated %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006101
6102 return 0;
6103}
6104
Adrian Knoth0dca1792011-01-26 19:32:14 +01006105
6106static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +02006107 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02006108 unsigned int reg, int channels)
6109{
6110 int i;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006111
6112 /* continuous memory segment */
Takashi Iwai763f3562005-06-03 11:25:34 +02006113 for (i = 0; i < (channels * 16); i++)
6114 hdspm_write(hdspm, reg + 4 * i,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006115 snd_pcm_sgbuf_get_addr(substream, 4096 * i));
Takashi Iwai763f3562005-06-03 11:25:34 +02006116}
6117
Adrian Knoth0dca1792011-01-26 19:32:14 +01006118
Takashi Iwai763f3562005-06-03 11:25:34 +02006119/* ------------- ALSA Devices ---------------------------- */
Bill Pembertone23e7a12012-12-06 12:35:10 -05006120static int snd_hdspm_create_pcm(struct snd_card *card,
6121 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006122{
Takashi Iwai98274f02005-11-17 14:52:34 +01006123 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006124 int err;
6125
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006126 err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm);
6127 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006128 return err;
6129
6130 hdspm->pcm = pcm;
6131 pcm->private_data = hdspm;
6132 strcpy(pcm->name, hdspm->card_name);
6133
6134 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
6135 &snd_hdspm_playback_ops);
6136 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
6137 &snd_hdspm_capture_ops);
6138
6139 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
6140
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006141 err = snd_hdspm_preallocate_memory(hdspm);
6142 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006143 return err;
6144
6145 return 0;
6146}
6147
Takashi Iwai98274f02005-11-17 14:52:34 +01006148static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006149{
Adrian Knoth7c7102b2011-02-28 15:14:50 +01006150 int i;
6151
6152 for (i = 0; i < hdspm->midiPorts; i++)
6153 snd_hdspm_flush_midi_input(hdspm, i);
Takashi Iwai763f3562005-06-03 11:25:34 +02006154}
6155
Bill Pembertone23e7a12012-12-06 12:35:10 -05006156static int snd_hdspm_create_alsa_devices(struct snd_card *card,
6157 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006158{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006159 int err, i;
Takashi Iwai763f3562005-06-03 11:25:34 +02006160
6161 snd_printdd("Create card...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006162 err = snd_hdspm_create_pcm(card, hdspm);
6163 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006164 return err;
6165
Adrian Knoth0dca1792011-01-26 19:32:14 +01006166 i = 0;
6167 while (i < hdspm->midiPorts) {
6168 err = snd_hdspm_create_midi(card, hdspm, i);
6169 if (err < 0) {
6170 return err;
6171 }
6172 i++;
6173 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006174
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006175 err = snd_hdspm_create_controls(card, hdspm);
6176 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006177 return err;
6178
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006179 err = snd_hdspm_create_hwdep(card, hdspm);
6180 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006181 return err;
6182
6183 snd_printdd("proc init...\n");
6184 snd_hdspm_proc_init(hdspm);
6185
6186 hdspm->system_sample_rate = -1;
6187 hdspm->last_external_sample_rate = -1;
6188 hdspm->last_internal_sample_rate = -1;
6189 hdspm->playback_pid = -1;
6190 hdspm->capture_pid = -1;
6191 hdspm->capture_substream = NULL;
6192 hdspm->playback_substream = NULL;
6193
6194 snd_printdd("Set defaults...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006195 err = snd_hdspm_set_defaults(hdspm);
6196 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006197 return err;
6198
6199 snd_printdd("Update mixer controls...\n");
6200 hdspm_update_simple_mixer_controls(hdspm);
6201
6202 snd_printdd("Initializeing complete ???\n");
6203
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006204 err = snd_card_register(card);
6205 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006206 snd_printk(KERN_ERR "HDSPM: error registering card\n");
6207 return err;
6208 }
6209
6210 snd_printdd("... yes now\n");
6211
6212 return 0;
6213}
6214
Bill Pembertone23e7a12012-12-06 12:35:10 -05006215static int snd_hdspm_create(struct snd_card *card,
6216 struct hdspm *hdspm)
6217{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006218
Takashi Iwai763f3562005-06-03 11:25:34 +02006219 struct pci_dev *pci = hdspm->pci;
6220 int err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006221 unsigned long io_extent;
6222
6223 hdspm->irq = -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02006224 hdspm->card = card;
6225
6226 spin_lock_init(&hdspm->lock);
6227
Takashi Iwai763f3562005-06-03 11:25:34 +02006228 pci_read_config_word(hdspm->pci,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006229 PCI_CLASS_REVISION, &hdspm->firmware_rev);
Remy Bruno3cee5a62006-10-16 12:46:32 +02006230
Takashi Iwai763f3562005-06-03 11:25:34 +02006231 strcpy(card->mixername, "Xilinx FPGA");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006232 strcpy(card->driver, "HDSPM");
6233
6234 switch (hdspm->firmware_rev) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01006235 case HDSPM_RAYDAT_REV:
6236 hdspm->io_type = RayDAT;
6237 hdspm->card_name = "RME RayDAT";
6238 hdspm->midiPorts = 2;
6239 break;
6240 case HDSPM_AIO_REV:
6241 hdspm->io_type = AIO;
6242 hdspm->card_name = "RME AIO";
6243 hdspm->midiPorts = 1;
6244 break;
6245 case HDSPM_MADIFACE_REV:
6246 hdspm->io_type = MADIface;
6247 hdspm->card_name = "RME MADIface";
6248 hdspm->midiPorts = 1;
6249 break;
Adrian Knoth5027f342011-02-28 15:14:49 +01006250 default:
Adrian Knothc09403d2011-10-27 21:57:54 +02006251 if ((hdspm->firmware_rev == 0xf0) ||
6252 ((hdspm->firmware_rev >= 0xe6) &&
6253 (hdspm->firmware_rev <= 0xea))) {
6254 hdspm->io_type = AES32;
6255 hdspm->card_name = "RME AES32";
6256 hdspm->midiPorts = 2;
Adrian Knoth05c7cc92011-11-21 16:15:36 +01006257 } else if ((hdspm->firmware_rev == 0xd2) ||
Adrian Knothc09403d2011-10-27 21:57:54 +02006258 ((hdspm->firmware_rev >= 0xc8) &&
6259 (hdspm->firmware_rev <= 0xcf))) {
6260 hdspm->io_type = MADI;
6261 hdspm->card_name = "RME MADI";
6262 hdspm->midiPorts = 3;
6263 } else {
6264 snd_printk(KERN_ERR
6265 "HDSPM: unknown firmware revision %x\n",
Adrian Knoth5027f342011-02-28 15:14:49 +01006266 hdspm->firmware_rev);
Adrian Knothc09403d2011-10-27 21:57:54 +02006267 return -ENODEV;
6268 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02006269 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006270
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006271 err = pci_enable_device(pci);
6272 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006273 return err;
6274
6275 pci_set_master(hdspm->pci);
6276
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006277 err = pci_request_regions(pci, "hdspm");
6278 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006279 return err;
6280
6281 hdspm->port = pci_resource_start(pci, 0);
6282 io_extent = pci_resource_len(pci, 0);
6283
6284 snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006285 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006286
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006287 hdspm->iobase = ioremap_nocache(hdspm->port, io_extent);
6288 if (!hdspm->iobase) {
6289 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006290 "unable to remap region 0x%lx-0x%lx\n",
6291 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006292 return -EBUSY;
6293 }
6294 snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006295 (unsigned long)hdspm->iobase, hdspm->port,
6296 hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006297
6298 if (request_irq(pci->irq, snd_hdspm_interrupt,
Takashi Iwai934c2b62011-06-10 16:36:37 +02006299 IRQF_SHARED, KBUILD_MODNAME, hdspm)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006300 snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
6301 return -EBUSY;
6302 }
6303
6304 snd_printdd("use IRQ %d\n", pci->irq);
6305
6306 hdspm->irq = pci->irq;
Takashi Iwai763f3562005-06-03 11:25:34 +02006307
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006308 snd_printdd("kmalloc Mixer memory of %zd Bytes\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006309 sizeof(struct hdspm_mixer));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006310 hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL);
6311 if (!hdspm->mixer) {
6312 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006313 "unable to kmalloc Mixer memory of %d Bytes\n",
6314 (int)sizeof(struct hdspm_mixer));
Julia Lawallb17cbdd2012-08-19 09:02:54 +02006315 return -ENOMEM;
Takashi Iwai763f3562005-06-03 11:25:34 +02006316 }
6317
Adrian Knoth0dca1792011-01-26 19:32:14 +01006318 hdspm->port_names_in = NULL;
6319 hdspm->port_names_out = NULL;
6320
6321 switch (hdspm->io_type) {
6322 case AES32:
Adrian Knothd2d10a22011-02-28 15:14:47 +01006323 hdspm->ss_in_channels = hdspm->ss_out_channels = AES32_CHANNELS;
6324 hdspm->ds_in_channels = hdspm->ds_out_channels = AES32_CHANNELS;
6325 hdspm->qs_in_channels = hdspm->qs_out_channels = AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006326
6327 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6328 channel_map_aes32;
6329 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6330 channel_map_aes32;
6331 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6332 channel_map_aes32;
6333 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6334 texts_ports_aes32;
6335 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6336 texts_ports_aes32;
6337 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6338 texts_ports_aes32;
6339
Adrian Knothd2d10a22011-02-28 15:14:47 +01006340 hdspm->max_channels_out = hdspm->max_channels_in =
6341 AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006342 hdspm->port_names_in = hdspm->port_names_out =
6343 texts_ports_aes32;
6344 hdspm->channel_map_in = hdspm->channel_map_out =
6345 channel_map_aes32;
6346
Adrian Knoth0dca1792011-01-26 19:32:14 +01006347 break;
6348
6349 case MADI:
6350 case MADIface:
6351 hdspm->ss_in_channels = hdspm->ss_out_channels =
6352 MADI_SS_CHANNELS;
6353 hdspm->ds_in_channels = hdspm->ds_out_channels =
6354 MADI_DS_CHANNELS;
6355 hdspm->qs_in_channels = hdspm->qs_out_channels =
6356 MADI_QS_CHANNELS;
6357
6358 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6359 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006360 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006361 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006362 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006363 channel_map_unity_ss;
6364
6365 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6366 texts_ports_madi;
6367 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6368 texts_ports_madi;
6369 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6370 texts_ports_madi;
6371 break;
6372
6373 case AIO:
6374 if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) {
6375 snd_printk(KERN_INFO "HDSPM: AEB input board found, but not supported\n");
6376 }
6377
6378 hdspm->ss_in_channels = AIO_IN_SS_CHANNELS;
6379 hdspm->ds_in_channels = AIO_IN_DS_CHANNELS;
6380 hdspm->qs_in_channels = AIO_IN_QS_CHANNELS;
6381 hdspm->ss_out_channels = AIO_OUT_SS_CHANNELS;
6382 hdspm->ds_out_channels = AIO_OUT_DS_CHANNELS;
6383 hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS;
6384
6385 hdspm->channel_map_out_ss = channel_map_aio_out_ss;
6386 hdspm->channel_map_out_ds = channel_map_aio_out_ds;
6387 hdspm->channel_map_out_qs = channel_map_aio_out_qs;
6388
6389 hdspm->channel_map_in_ss = channel_map_aio_in_ss;
6390 hdspm->channel_map_in_ds = channel_map_aio_in_ds;
6391 hdspm->channel_map_in_qs = channel_map_aio_in_qs;
6392
6393 hdspm->port_names_in_ss = texts_ports_aio_in_ss;
6394 hdspm->port_names_out_ss = texts_ports_aio_out_ss;
6395 hdspm->port_names_in_ds = texts_ports_aio_in_ds;
6396 hdspm->port_names_out_ds = texts_ports_aio_out_ds;
6397 hdspm->port_names_in_qs = texts_ports_aio_in_qs;
6398 hdspm->port_names_out_qs = texts_ports_aio_out_qs;
6399
6400 break;
6401
6402 case RayDAT:
6403 hdspm->ss_in_channels = hdspm->ss_out_channels =
6404 RAYDAT_SS_CHANNELS;
6405 hdspm->ds_in_channels = hdspm->ds_out_channels =
6406 RAYDAT_DS_CHANNELS;
6407 hdspm->qs_in_channels = hdspm->qs_out_channels =
6408 RAYDAT_QS_CHANNELS;
6409
6410 hdspm->max_channels_in = RAYDAT_SS_CHANNELS;
6411 hdspm->max_channels_out = RAYDAT_SS_CHANNELS;
6412
6413 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6414 channel_map_raydat_ss;
6415 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6416 channel_map_raydat_ds;
6417 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6418 channel_map_raydat_qs;
6419 hdspm->channel_map_in = hdspm->channel_map_out =
6420 channel_map_raydat_ss;
6421
6422 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6423 texts_ports_raydat_ss;
6424 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6425 texts_ports_raydat_ds;
6426 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6427 texts_ports_raydat_qs;
6428
6429
6430 break;
6431
6432 }
6433
6434 /* TCO detection */
6435 switch (hdspm->io_type) {
6436 case AIO:
6437 case RayDAT:
6438 if (hdspm_read(hdspm, HDSPM_statusRegister2) &
6439 HDSPM_s2_tco_detect) {
6440 hdspm->midiPorts++;
6441 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6442 GFP_KERNEL);
6443 if (NULL != hdspm->tco) {
6444 hdspm_tco_write(hdspm);
6445 }
6446 snd_printk(KERN_INFO "HDSPM: AIO/RayDAT TCO module found\n");
6447 } else {
6448 hdspm->tco = NULL;
6449 }
6450 break;
6451
6452 case MADI:
6453 if (hdspm_read(hdspm, HDSPM_statusRegister) & HDSPM_tco_detect) {
6454 hdspm->midiPorts++;
6455 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6456 GFP_KERNEL);
6457 if (NULL != hdspm->tco) {
6458 hdspm_tco_write(hdspm);
6459 }
6460 snd_printk(KERN_INFO "HDSPM: MADI TCO module found\n");
6461 } else {
6462 hdspm->tco = NULL;
6463 }
6464 break;
6465
6466 default:
6467 hdspm->tco = NULL;
6468 }
6469
6470 /* texts */
6471 switch (hdspm->io_type) {
6472 case AES32:
6473 if (hdspm->tco) {
6474 hdspm->texts_autosync = texts_autosync_aes_tco;
6475 hdspm->texts_autosync_items = 10;
6476 } else {
6477 hdspm->texts_autosync = texts_autosync_aes;
6478 hdspm->texts_autosync_items = 9;
6479 }
6480 break;
6481
6482 case MADI:
6483 if (hdspm->tco) {
6484 hdspm->texts_autosync = texts_autosync_madi_tco;
6485 hdspm->texts_autosync_items = 4;
6486 } else {
6487 hdspm->texts_autosync = texts_autosync_madi;
6488 hdspm->texts_autosync_items = 3;
6489 }
6490 break;
6491
6492 case MADIface:
6493
6494 break;
6495
6496 case RayDAT:
6497 if (hdspm->tco) {
6498 hdspm->texts_autosync = texts_autosync_raydat_tco;
6499 hdspm->texts_autosync_items = 9;
6500 } else {
6501 hdspm->texts_autosync = texts_autosync_raydat;
6502 hdspm->texts_autosync_items = 8;
6503 }
6504 break;
6505
6506 case AIO:
6507 if (hdspm->tco) {
6508 hdspm->texts_autosync = texts_autosync_aio_tco;
6509 hdspm->texts_autosync_items = 6;
6510 } else {
6511 hdspm->texts_autosync = texts_autosync_aio;
6512 hdspm->texts_autosync_items = 5;
6513 }
6514 break;
6515
6516 }
6517
6518 tasklet_init(&hdspm->midi_tasklet,
6519 hdspm_midi_tasklet, (unsigned long) hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006520
Adrian Knothf7de8ba2012-01-10 20:58:40 +01006521
6522 if (hdspm->io_type != MADIface) {
6523 hdspm->serial = (hdspm_read(hdspm,
6524 HDSPM_midiStatusIn0)>>8) & 0xFFFFFF;
6525 /* id contains either a user-provided value or the default
6526 * NULL. If it's the default, we're safe to
6527 * fill card->id with the serial number.
6528 *
6529 * If the serial number is 0xFFFFFF, then we're dealing with
6530 * an old PCI revision that comes without a sane number. In
6531 * this case, we don't set card->id to avoid collisions
6532 * when running with multiple cards.
6533 */
6534 if (NULL == id[hdspm->dev] && hdspm->serial != 0xFFFFFF) {
6535 sprintf(card->id, "HDSPMx%06x", hdspm->serial);
6536 snd_card_set_id(card, card->id);
6537 }
6538 }
6539
Takashi Iwai763f3562005-06-03 11:25:34 +02006540 snd_printdd("create alsa devices.\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006541 err = snd_hdspm_create_alsa_devices(card, hdspm);
6542 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006543 return err;
6544
6545 snd_hdspm_initialize_midi_flush(hdspm);
6546
6547 return 0;
6548}
6549
Adrian Knoth0dca1792011-01-26 19:32:14 +01006550
Takashi Iwai98274f02005-11-17 14:52:34 +01006551static int snd_hdspm_free(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006552{
6553
6554 if (hdspm->port) {
6555
6556 /* stop th audio, and cancel all interrupts */
6557 hdspm->control_register &=
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006558 ~(HDSPM_Start | HDSPM_AudioInterruptEnable |
Adrian Knoth0dca1792011-01-26 19:32:14 +01006559 HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable |
6560 HDSPM_Midi2InterruptEnable | HDSPM_Midi3InterruptEnable);
Takashi Iwai763f3562005-06-03 11:25:34 +02006561 hdspm_write(hdspm, HDSPM_controlRegister,
6562 hdspm->control_register);
6563 }
6564
6565 if (hdspm->irq >= 0)
6566 free_irq(hdspm->irq, (void *) hdspm);
6567
Jesper Juhlfc584222005-10-24 15:11:28 +02006568 kfree(hdspm->mixer);
Takashi Iwai763f3562005-06-03 11:25:34 +02006569
6570 if (hdspm->iobase)
6571 iounmap(hdspm->iobase);
6572
Takashi Iwai763f3562005-06-03 11:25:34 +02006573 if (hdspm->port)
6574 pci_release_regions(hdspm->pci);
6575
6576 pci_disable_device(hdspm->pci);
6577 return 0;
6578}
6579
Adrian Knoth0dca1792011-01-26 19:32:14 +01006580
Takashi Iwai98274f02005-11-17 14:52:34 +01006581static void snd_hdspm_card_free(struct snd_card *card)
Takashi Iwai763f3562005-06-03 11:25:34 +02006582{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006583 struct hdspm *hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006584
6585 if (hdspm)
6586 snd_hdspm_free(hdspm);
6587}
6588
Adrian Knoth0dca1792011-01-26 19:32:14 +01006589
Bill Pembertone23e7a12012-12-06 12:35:10 -05006590static int snd_hdspm_probe(struct pci_dev *pci,
6591 const struct pci_device_id *pci_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02006592{
6593 static int dev;
Takashi Iwai98274f02005-11-17 14:52:34 +01006594 struct hdspm *hdspm;
6595 struct snd_card *card;
Takashi Iwai763f3562005-06-03 11:25:34 +02006596 int err;
6597
6598 if (dev >= SNDRV_CARDS)
6599 return -ENODEV;
6600 if (!enable[dev]) {
6601 dev++;
6602 return -ENOENT;
6603 }
6604
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006605 err = snd_card_create(index[dev], id[dev],
Adrian Knoth0dca1792011-01-26 19:32:14 +01006606 THIS_MODULE, sizeof(struct hdspm), &card);
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006607 if (err < 0)
6608 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006609
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006610 hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006611 card->private_free = snd_hdspm_card_free;
6612 hdspm->dev = dev;
6613 hdspm->pci = pci;
6614
Takashi Iwaic187c042007-02-19 15:27:33 +01006615 snd_card_set_dev(card, &pci->dev);
6616
Adrian Knoth0dca1792011-01-26 19:32:14 +01006617 err = snd_hdspm_create(card, hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006618 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006619 snd_card_free(card);
6620 return err;
6621 }
6622
Adrian Knoth0dca1792011-01-26 19:32:14 +01006623 if (hdspm->io_type != MADIface) {
6624 sprintf(card->shortname, "%s_%x",
6625 hdspm->card_name,
Adrian Knoth7d53a632012-01-04 14:31:16 +01006626 hdspm->serial);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006627 sprintf(card->longname, "%s S/N 0x%x at 0x%lx, irq %d",
6628 hdspm->card_name,
Adrian Knoth7d53a632012-01-04 14:31:16 +01006629 hdspm->serial,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006630 hdspm->port, hdspm->irq);
6631 } else {
6632 sprintf(card->shortname, "%s", hdspm->card_name);
6633 sprintf(card->longname, "%s at 0x%lx, irq %d",
6634 hdspm->card_name, hdspm->port, hdspm->irq);
6635 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006636
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006637 err = snd_card_register(card);
6638 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006639 snd_card_free(card);
6640 return err;
6641 }
6642
6643 pci_set_drvdata(pci, card);
6644
6645 dev++;
6646 return 0;
6647}
6648
Bill Pembertone23e7a12012-12-06 12:35:10 -05006649static void snd_hdspm_remove(struct pci_dev *pci)
Takashi Iwai763f3562005-06-03 11:25:34 +02006650{
6651 snd_card_free(pci_get_drvdata(pci));
6652 pci_set_drvdata(pci, NULL);
6653}
6654
Takashi Iwaie9f66d92012-04-24 12:25:00 +02006655static struct pci_driver hdspm_driver = {
Takashi Iwai3733e422011-06-10 16:20:20 +02006656 .name = KBUILD_MODNAME,
Takashi Iwai763f3562005-06-03 11:25:34 +02006657 .id_table = snd_hdspm_ids,
6658 .probe = snd_hdspm_probe,
Bill Pembertone23e7a12012-12-06 12:35:10 -05006659 .remove = snd_hdspm_remove,
Takashi Iwai763f3562005-06-03 11:25:34 +02006660};
6661
Takashi Iwaie9f66d92012-04-24 12:25:00 +02006662module_pci_driver(hdspm_driver);