blob: 742bd5e430abf239ad61d00f6171463d90e40727 [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
444#define HDSPM_AES32_wcFreq_bit 22
Adrian Knoth0dca1792011-01-26 19:32:14 +0100445/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function
Remy Bruno3cee5a62006-10-16 12:46:32 +0200446 HDSPM_bit2freq */
447#define HDSPM_AES32_syncref_bit 16
448/* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */
449
450#define HDSPM_AES32_AUTOSYNC_FROM_WORD 0
451#define HDSPM_AES32_AUTOSYNC_FROM_AES1 1
452#define HDSPM_AES32_AUTOSYNC_FROM_AES2 2
453#define HDSPM_AES32_AUTOSYNC_FROM_AES3 3
454#define HDSPM_AES32_AUTOSYNC_FROM_AES4 4
455#define HDSPM_AES32_AUTOSYNC_FROM_AES5 5
456#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6
457#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7
458#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8
Remy Bruno65345992007-08-31 12:21:08 +0200459#define HDSPM_AES32_AUTOSYNC_FROM_NONE 9
Remy Bruno3cee5a62006-10-16 12:46:32 +0200460
461/* status2 */
462/* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */
463#define HDSPM_LockAES 0x80
464#define HDSPM_LockAES1 0x80
465#define HDSPM_LockAES2 0x40
466#define HDSPM_LockAES3 0x20
467#define HDSPM_LockAES4 0x10
468#define HDSPM_LockAES5 0x8
469#define HDSPM_LockAES6 0x4
470#define HDSPM_LockAES7 0x2
471#define HDSPM_LockAES8 0x1
472/*
473 Timecode
474 After windows driver sources, bits 4*i to 4*i+3 give the input frequency on
475 AES i+1
476 bits 3210
477 0001 32kHz
478 0010 44.1kHz
479 0011 48kHz
480 0100 64kHz
481 0101 88.2kHz
482 0110 96kHz
483 0111 128kHz
484 1000 176.4kHz
485 1001 192kHz
486 NB: Timecode register doesn't seem to work on AES32 card revision 230
487*/
488
Takashi Iwai763f3562005-06-03 11:25:34 +0200489/* Mixer Values */
490#define UNITY_GAIN 32768 /* = 65536/2 */
491#define MINUS_INFINITY_GAIN 0
492
Takashi Iwai763f3562005-06-03 11:25:34 +0200493/* Number of channels for different Speed Modes */
494#define MADI_SS_CHANNELS 64
495#define MADI_DS_CHANNELS 32
496#define MADI_QS_CHANNELS 16
497
Adrian Knoth0dca1792011-01-26 19:32:14 +0100498#define RAYDAT_SS_CHANNELS 36
499#define RAYDAT_DS_CHANNELS 20
500#define RAYDAT_QS_CHANNELS 12
501
502#define AIO_IN_SS_CHANNELS 14
503#define AIO_IN_DS_CHANNELS 10
504#define AIO_IN_QS_CHANNELS 8
505#define AIO_OUT_SS_CHANNELS 16
506#define AIO_OUT_DS_CHANNELS 12
507#define AIO_OUT_QS_CHANNELS 10
508
Adrian Knothd2d10a22011-02-28 15:14:47 +0100509#define AES32_CHANNELS 16
510
Takashi Iwai763f3562005-06-03 11:25:34 +0200511/* the size of a substream (1 mono data stream) */
512#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024)
513#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
514
515/* the size of the area we need to allocate for DMA transfers. the
516 size is the same regardless of the number of channels, and
Adrian Knoth0dca1792011-01-26 19:32:14 +0100517 also the latency to use.
Takashi Iwai763f3562005-06-03 11:25:34 +0200518 for one direction !!!
519*/
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100520#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
Takashi Iwai763f3562005-06-03 11:25:34 +0200521#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
522
Adrian Knoth0dca1792011-01-26 19:32:14 +0100523#define HDSPM_RAYDAT_REV 211
524#define HDSPM_AIO_REV 212
525#define HDSPM_MADIFACE_REV 213
Remy Bruno3cee5a62006-10-16 12:46:32 +0200526
Remy Bruno65345992007-08-31 12:21:08 +0200527/* speed factor modes */
528#define HDSPM_SPEED_SINGLE 0
529#define HDSPM_SPEED_DOUBLE 1
530#define HDSPM_SPEED_QUAD 2
Adrian Knoth0dca1792011-01-26 19:32:14 +0100531
Remy Bruno65345992007-08-31 12:21:08 +0200532/* names for speed modes */
533static char *hdspm_speed_names[] = { "single", "double", "quad" };
534
Adrian Knoth0dca1792011-01-26 19:32:14 +0100535static char *texts_autosync_aes_tco[] = { "Word Clock",
536 "AES1", "AES2", "AES3", "AES4",
537 "AES5", "AES6", "AES7", "AES8",
538 "TCO" };
539static char *texts_autosync_aes[] = { "Word Clock",
540 "AES1", "AES2", "AES3", "AES4",
541 "AES5", "AES6", "AES7", "AES8" };
542static char *texts_autosync_madi_tco[] = { "Word Clock",
543 "MADI", "TCO", "Sync In" };
544static char *texts_autosync_madi[] = { "Word Clock",
545 "MADI", "Sync In" };
546
547static char *texts_autosync_raydat_tco[] = {
548 "Word Clock",
549 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
550 "AES", "SPDIF", "TCO", "Sync In"
551};
552static char *texts_autosync_raydat[] = {
553 "Word Clock",
554 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
555 "AES", "SPDIF", "Sync In"
556};
557static char *texts_autosync_aio_tco[] = {
558 "Word Clock",
559 "ADAT", "AES", "SPDIF", "TCO", "Sync In"
560};
561static char *texts_autosync_aio[] = { "Word Clock",
562 "ADAT", "AES", "SPDIF", "Sync In" };
563
564static char *texts_freq[] = {
565 "No Lock",
566 "32 kHz",
567 "44.1 kHz",
568 "48 kHz",
569 "64 kHz",
570 "88.2 kHz",
571 "96 kHz",
572 "128 kHz",
573 "176.4 kHz",
574 "192 kHz"
575};
576
Adrian Knoth0dca1792011-01-26 19:32:14 +0100577static char *texts_ports_madi[] = {
578 "MADI.1", "MADI.2", "MADI.3", "MADI.4", "MADI.5", "MADI.6",
579 "MADI.7", "MADI.8", "MADI.9", "MADI.10", "MADI.11", "MADI.12",
580 "MADI.13", "MADI.14", "MADI.15", "MADI.16", "MADI.17", "MADI.18",
581 "MADI.19", "MADI.20", "MADI.21", "MADI.22", "MADI.23", "MADI.24",
582 "MADI.25", "MADI.26", "MADI.27", "MADI.28", "MADI.29", "MADI.30",
583 "MADI.31", "MADI.32", "MADI.33", "MADI.34", "MADI.35", "MADI.36",
584 "MADI.37", "MADI.38", "MADI.39", "MADI.40", "MADI.41", "MADI.42",
585 "MADI.43", "MADI.44", "MADI.45", "MADI.46", "MADI.47", "MADI.48",
586 "MADI.49", "MADI.50", "MADI.51", "MADI.52", "MADI.53", "MADI.54",
587 "MADI.55", "MADI.56", "MADI.57", "MADI.58", "MADI.59", "MADI.60",
588 "MADI.61", "MADI.62", "MADI.63", "MADI.64",
589};
590
591
592static char *texts_ports_raydat_ss[] = {
593 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT1.5", "ADAT1.6",
594 "ADAT1.7", "ADAT1.8", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
595 "ADAT2.5", "ADAT2.6", "ADAT2.7", "ADAT2.8", "ADAT3.1", "ADAT3.2",
596 "ADAT3.3", "ADAT3.4", "ADAT3.5", "ADAT3.6", "ADAT3.7", "ADAT3.8",
597 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4", "ADAT4.5", "ADAT4.6",
598 "ADAT4.7", "ADAT4.8",
599 "AES.L", "AES.R",
600 "SPDIF.L", "SPDIF.R"
601};
602
603static char *texts_ports_raydat_ds[] = {
604 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4",
605 "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
606 "ADAT3.1", "ADAT3.2", "ADAT3.3", "ADAT3.4",
607 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4",
608 "AES.L", "AES.R",
609 "SPDIF.L", "SPDIF.R"
610};
611
612static char *texts_ports_raydat_qs[] = {
613 "ADAT1.1", "ADAT1.2",
614 "ADAT2.1", "ADAT2.2",
615 "ADAT3.1", "ADAT3.2",
616 "ADAT4.1", "ADAT4.2",
617 "AES.L", "AES.R",
618 "SPDIF.L", "SPDIF.R"
619};
620
621
622static char *texts_ports_aio_in_ss[] = {
623 "Analogue.L", "Analogue.R",
624 "AES.L", "AES.R",
625 "SPDIF.L", "SPDIF.R",
626 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
627 "ADAT.7", "ADAT.8"
628};
629
630static char *texts_ports_aio_out_ss[] = {
631 "Analogue.L", "Analogue.R",
632 "AES.L", "AES.R",
633 "SPDIF.L", "SPDIF.R",
634 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
635 "ADAT.7", "ADAT.8",
636 "Phone.L", "Phone.R"
637};
638
639static char *texts_ports_aio_in_ds[] = {
640 "Analogue.L", "Analogue.R",
641 "AES.L", "AES.R",
642 "SPDIF.L", "SPDIF.R",
643 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
644};
645
646static char *texts_ports_aio_out_ds[] = {
647 "Analogue.L", "Analogue.R",
648 "AES.L", "AES.R",
649 "SPDIF.L", "SPDIF.R",
650 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
651 "Phone.L", "Phone.R"
652};
653
654static char *texts_ports_aio_in_qs[] = {
655 "Analogue.L", "Analogue.R",
656 "AES.L", "AES.R",
657 "SPDIF.L", "SPDIF.R",
658 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
659};
660
661static char *texts_ports_aio_out_qs[] = {
662 "Analogue.L", "Analogue.R",
663 "AES.L", "AES.R",
664 "SPDIF.L", "SPDIF.R",
665 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
666 "Phone.L", "Phone.R"
667};
668
Adrian Knoth432d2502011-02-23 11:43:08 +0100669static char *texts_ports_aes32[] = {
670 "AES.1", "AES.2", "AES.3", "AES.4", "AES.5", "AES.6", "AES.7",
671 "AES.8", "AES.9.", "AES.10", "AES.11", "AES.12", "AES.13", "AES.14",
672 "AES.15", "AES.16"
673};
674
Adrian Knoth55a57602011-01-27 11:23:15 +0100675/* These tables map the ALSA channels 1..N to the channels that we
676 need to use in order to find the relevant channel buffer. RME
677 refers to this kind of mapping as between "the ADAT channel and
678 the DMA channel." We index it using the logical audio channel,
679 and the value is the DMA channel (i.e. channel buffer number)
680 where the data for that channel can be read/written from/to.
681*/
682
683static char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = {
684 0, 1, 2, 3, 4, 5, 6, 7,
685 8, 9, 10, 11, 12, 13, 14, 15,
686 16, 17, 18, 19, 20, 21, 22, 23,
687 24, 25, 26, 27, 28, 29, 30, 31,
688 32, 33, 34, 35, 36, 37, 38, 39,
689 40, 41, 42, 43, 44, 45, 46, 47,
690 48, 49, 50, 51, 52, 53, 54, 55,
691 56, 57, 58, 59, 60, 61, 62, 63
692};
693
Adrian Knoth55a57602011-01-27 11:23:15 +0100694static char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = {
695 4, 5, 6, 7, 8, 9, 10, 11, /* ADAT 1 */
696 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT 2 */
697 20, 21, 22, 23, 24, 25, 26, 27, /* ADAT 3 */
698 28, 29, 30, 31, 32, 33, 34, 35, /* ADAT 4 */
699 0, 1, /* AES */
700 2, 3, /* SPDIF */
701 -1, -1, -1, -1,
702 -1, -1, -1, -1, -1, -1, -1, -1,
703 -1, -1, -1, -1, -1, -1, -1, -1,
704 -1, -1, -1, -1, -1, -1, -1, -1,
705};
706
707static char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = {
708 4, 5, 6, 7, /* ADAT 1 */
709 8, 9, 10, 11, /* ADAT 2 */
710 12, 13, 14, 15, /* ADAT 3 */
711 16, 17, 18, 19, /* ADAT 4 */
712 0, 1, /* AES */
713 2, 3, /* SPDIF */
714 -1, -1, -1, -1,
715 -1, -1, -1, -1, -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};
721
722static char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = {
723 4, 5, /* ADAT 1 */
724 6, 7, /* ADAT 2 */
725 8, 9, /* ADAT 3 */
726 10, 11, /* ADAT 4 */
727 0, 1, /* AES */
728 2, 3, /* SPDIF */
729 -1, -1, -1, -1,
730 -1, -1, -1, -1, -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};
737
738static char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = {
739 0, 1, /* line in */
740 8, 9, /* aes in, */
741 10, 11, /* spdif in */
742 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT in */
743 -1, -1,
744 -1, -1, -1, -1, -1, -1, -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};
751
752static char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = {
753 0, 1, /* line out */
754 8, 9, /* aes out */
755 10, 11, /* spdif out */
756 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT out */
757 6, 7, /* phone out */
758 -1, -1, -1, -1, -1, -1, -1, -1,
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};
765
766static char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = {
767 0, 1, /* line in */
768 8, 9, /* aes in */
769 10, 11, /* spdif in */
770 12, 14, 16, 18, /* adat in */
771 -1, -1, -1, -1, -1, -1,
772 -1, -1, -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};
779
780static char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = {
781 0, 1, /* line out */
782 8, 9, /* aes out */
783 10, 11, /* spdif out */
784 12, 14, 16, 18, /* adat out */
785 6, 7, /* phone out */
786 -1, -1, -1, -1,
787 -1, -1, -1, -1, -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};
794
795static char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = {
796 0, 1, /* line in */
797 8, 9, /* aes in */
798 10, 11, /* spdif in */
799 12, 16, /* adat in */
800 -1, -1, -1, -1, -1, -1, -1, -1,
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};
808
809static char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = {
810 0, 1, /* line out */
811 8, 9, /* aes out */
812 10, 11, /* spdif out */
813 12, 16, /* adat out */
814 6, 7, /* phone out */
815 -1, -1, -1, -1, -1, -1,
816 -1, -1, -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};
823
Adrian Knoth432d2502011-02-23 11:43:08 +0100824static char channel_map_aes32[HDSPM_MAX_CHANNELS] = {
825 0, 1, 2, 3, 4, 5, 6, 7,
826 8, 9, 10, 11, 12, 13, 14, 15,
827 -1, -1, -1, -1, -1, -1, -1, -1,
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};
834
Takashi Iwai98274f02005-11-17 14:52:34 +0100835struct hdspm_midi {
836 struct hdspm *hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +0200837 int id;
Takashi Iwai98274f02005-11-17 14:52:34 +0100838 struct snd_rawmidi *rmidi;
839 struct snd_rawmidi_substream *input;
840 struct snd_rawmidi_substream *output;
Takashi Iwai763f3562005-06-03 11:25:34 +0200841 char istimer; /* timer in use */
842 struct timer_list timer;
843 spinlock_t lock;
844 int pending;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100845 int dataIn;
846 int statusIn;
847 int dataOut;
848 int statusOut;
849 int ie;
850 int irq;
851};
852
853struct hdspm_tco {
854 int input;
855 int framerate;
856 int wordclock;
857 int samplerate;
858 int pull;
859 int term; /* 0 = off, 1 = on */
Takashi Iwai763f3562005-06-03 11:25:34 +0200860};
861
Takashi Iwai98274f02005-11-17 14:52:34 +0100862struct hdspm {
Takashi Iwai763f3562005-06-03 11:25:34 +0200863 spinlock_t lock;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200864 /* only one playback and/or capture stream */
865 struct snd_pcm_substream *capture_substream;
866 struct snd_pcm_substream *playback_substream;
Takashi Iwai763f3562005-06-03 11:25:34 +0200867
868 char *card_name; /* for procinfo */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200869 unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
870
Adrian Knoth0dca1792011-01-26 19:32:14 +0100871 uint8_t io_type;
Takashi Iwai763f3562005-06-03 11:25:34 +0200872
Takashi Iwai763f3562005-06-03 11:25:34 +0200873 int monitor_outs; /* set up monitoring outs init flag */
874
875 u32 control_register; /* cached value */
876 u32 control2_register; /* cached value */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100877 u32 settings_register;
Takashi Iwai763f3562005-06-03 11:25:34 +0200878
Adrian Knoth0dca1792011-01-26 19:32:14 +0100879 struct hdspm_midi midi[4];
Takashi Iwai763f3562005-06-03 11:25:34 +0200880 struct tasklet_struct midi_tasklet;
881
882 size_t period_bytes;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100883 unsigned char ss_in_channels;
884 unsigned char ds_in_channels;
885 unsigned char qs_in_channels;
886 unsigned char ss_out_channels;
887 unsigned char ds_out_channels;
888 unsigned char qs_out_channels;
889
890 unsigned char max_channels_in;
891 unsigned char max_channels_out;
892
Takashi Iwai286bed02011-06-30 12:45:36 +0200893 signed char *channel_map_in;
894 signed char *channel_map_out;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100895
Takashi Iwai286bed02011-06-30 12:45:36 +0200896 signed char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs;
897 signed char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100898
899 char **port_names_in;
900 char **port_names_out;
901
902 char **port_names_in_ss, **port_names_in_ds, **port_names_in_qs;
903 char **port_names_out_ss, **port_names_out_ds, **port_names_out_qs;
Takashi Iwai763f3562005-06-03 11:25:34 +0200904
905 unsigned char *playback_buffer; /* suitably aligned address */
906 unsigned char *capture_buffer; /* suitably aligned address */
907
908 pid_t capture_pid; /* process id which uses capture */
909 pid_t playback_pid; /* process id which uses capture */
910 int running; /* running status */
911
912 int last_external_sample_rate; /* samplerate mystic ... */
913 int last_internal_sample_rate;
914 int system_sample_rate;
915
Takashi Iwai763f3562005-06-03 11:25:34 +0200916 int dev; /* Hardware vars... */
917 int irq;
918 unsigned long port;
919 void __iomem *iobase;
920
921 int irq_count; /* for debug */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100922 int midiPorts;
Takashi Iwai763f3562005-06-03 11:25:34 +0200923
Takashi Iwai98274f02005-11-17 14:52:34 +0100924 struct snd_card *card; /* one card */
925 struct snd_pcm *pcm; /* has one pcm */
926 struct snd_hwdep *hwdep; /* and a hwdep for additional ioctl */
Takashi Iwai763f3562005-06-03 11:25:34 +0200927 struct pci_dev *pci; /* and an pci info */
928
929 /* Mixer vars */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200930 /* fast alsa mixer */
931 struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS];
932 /* but input to much, so not used */
933 struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS];
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300934 /* full mixer accessible over mixer ioctl or hwdep-device */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200935 struct hdspm_mixer *mixer;
Takashi Iwai763f3562005-06-03 11:25:34 +0200936
Adrian Knoth0dca1792011-01-26 19:32:14 +0100937 struct hdspm_tco *tco; /* NULL if no TCO detected */
Takashi Iwai763f3562005-06-03 11:25:34 +0200938
Adrian Knoth0dca1792011-01-26 19:32:14 +0100939 char **texts_autosync;
940 int texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +0200941
Adrian Knoth0dca1792011-01-26 19:32:14 +0100942 cycles_t last_interrupt;
Jaroslav Kysela730a5862011-01-27 13:03:15 +0100943
Adrian Knoth7d53a632012-01-04 14:31:16 +0100944 unsigned int serial;
945
Jaroslav Kysela730a5862011-01-27 13:03:15 +0100946 struct hdspm_peak_rms peak_rms;
Takashi Iwai763f3562005-06-03 11:25:34 +0200947};
948
Takashi Iwai763f3562005-06-03 11:25:34 +0200949
Alexey Dobriyancebe41d2010-02-06 00:21:03 +0200950static DEFINE_PCI_DEVICE_TABLE(snd_hdspm_ids) = {
Takashi Iwai763f3562005-06-03 11:25:34 +0200951 {
952 .vendor = PCI_VENDOR_ID_XILINX,
953 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
954 .subvendor = PCI_ANY_ID,
955 .subdevice = PCI_ANY_ID,
956 .class = 0,
957 .class_mask = 0,
958 .driver_data = 0},
959 {0,}
960};
961
962MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
963
964/* prototypes */
Takashi Iwai98274f02005-11-17 14:52:34 +0100965static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
966 struct hdspm * hdspm);
967static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
968 struct hdspm * hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +0200969
Adrian Knoth0dca1792011-01-26 19:32:14 +0100970static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
971static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
972static int hdspm_autosync_ref(struct hdspm *hdspm);
973static int snd_hdspm_set_defaults(struct hdspm *hdspm);
974static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +0200975 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +0200976 unsigned int reg, int channels);
977
Remy Bruno3cee5a62006-10-16 12:46:32 +0200978static inline int HDSPM_bit2freq(int n)
979{
Denys Vlasenko62cef822008-04-14 13:04:18 +0200980 static const int bit2freq_tab[] = {
981 0, 32000, 44100, 48000, 64000, 88200,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200982 96000, 128000, 176400, 192000 };
983 if (n < 1 || n > 9)
984 return 0;
985 return bit2freq_tab[n];
986}
987
Adrian Knoth0dca1792011-01-26 19:32:14 +0100988/* Write/read to/from HDSPM with Adresses in Bytes
Takashi Iwai763f3562005-06-03 11:25:34 +0200989 not words but only 32Bit writes are allowed */
990
Takashi Iwai98274f02005-11-17 14:52:34 +0100991static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
Takashi Iwai763f3562005-06-03 11:25:34 +0200992 unsigned int val)
993{
994 writel(val, hdspm->iobase + reg);
995}
996
Takashi Iwai98274f02005-11-17 14:52:34 +0100997static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
Takashi Iwai763f3562005-06-03 11:25:34 +0200998{
999 return readl(hdspm->iobase + reg);
1000}
1001
Adrian Knoth0dca1792011-01-26 19:32:14 +01001002/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
1003 mixer is write only on hardware so we have to cache him for read
Takashi Iwai763f3562005-06-03 11:25:34 +02001004 each fader is a u32, but uses only the first 16 bit */
1005
Takashi Iwai98274f02005-11-17 14:52:34 +01001006static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001007 unsigned int in)
1008{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001009 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001010 return 0;
1011
1012 return hdspm->mixer->ch[chan].in[in];
1013}
1014
Takashi Iwai98274f02005-11-17 14:52:34 +01001015static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001016 unsigned int pb)
1017{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001018 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001019 return 0;
1020 return hdspm->mixer->ch[chan].pb[pb];
1021}
1022
Denys Vlasenko62cef822008-04-14 13:04:18 +02001023static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001024 unsigned int in, unsigned short data)
1025{
1026 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
1027 return -1;
1028
1029 hdspm_write(hdspm,
1030 HDSPM_MADI_mixerBase +
1031 ((in + 128 * chan) * sizeof(u32)),
1032 (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
1033 return 0;
1034}
1035
Denys Vlasenko62cef822008-04-14 13:04:18 +02001036static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001037 unsigned int pb, unsigned short data)
1038{
1039 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
1040 return -1;
1041
1042 hdspm_write(hdspm,
1043 HDSPM_MADI_mixerBase +
1044 ((64 + pb + 128 * chan) * sizeof(u32)),
1045 (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
1046 return 0;
1047}
1048
1049
1050/* enable DMA for specific channels, now available for DSP-MADI */
Takashi Iwai98274f02005-11-17 14:52:34 +01001051static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001052{
1053 hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
1054}
1055
Takashi Iwai98274f02005-11-17 14:52:34 +01001056static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001057{
1058 hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
1059}
1060
1061/* check if same process is writing and reading */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001062static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001063{
1064 unsigned long flags;
1065 int ret = 1;
1066
1067 spin_lock_irqsave(&hdspm->lock, flags);
1068 if ((hdspm->playback_pid != hdspm->capture_pid) &&
1069 (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
1070 ret = 0;
1071 }
1072 spin_unlock_irqrestore(&hdspm->lock, flags);
1073 return ret;
1074}
1075
1076/* check for external sample rate */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001077static int hdspm_external_sample_rate(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001078{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001079 unsigned int status, status2, timecode;
1080 int syncref, rate = 0, rate_bits;
Takashi Iwai763f3562005-06-03 11:25:34 +02001081
Adrian Knoth0dca1792011-01-26 19:32:14 +01001082 switch (hdspm->io_type) {
1083 case AES32:
1084 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1085 status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01001086 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001087
1088 syncref = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001089
Remy Bruno3cee5a62006-10-16 12:46:32 +02001090 if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD &&
1091 status & HDSPM_AES32_wcLock)
Adrian Knoth0dca1792011-01-26 19:32:14 +01001092 return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF);
1093
Remy Bruno3cee5a62006-10-16 12:46:32 +02001094 if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001095 syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
1096 status2 & (HDSPM_LockAES >>
1097 (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1)))
1098 return HDSPM_bit2freq((timecode >> (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF);
Remy Bruno3cee5a62006-10-16 12:46:32 +02001099 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001100 break;
1101
1102 case MADIface:
1103 status = hdspm_read(hdspm, HDSPM_statusRegister);
1104
1105 if (!(status & HDSPM_madiLock)) {
1106 rate = 0; /* no lock */
1107 } else {
1108 switch (status & (HDSPM_status1_freqMask)) {
1109 case HDSPM_status1_F_0*1:
1110 rate = 32000; break;
1111 case HDSPM_status1_F_0*2:
1112 rate = 44100; break;
1113 case HDSPM_status1_F_0*3:
1114 rate = 48000; break;
1115 case HDSPM_status1_F_0*4:
1116 rate = 64000; break;
1117 case HDSPM_status1_F_0*5:
1118 rate = 88200; break;
1119 case HDSPM_status1_F_0*6:
1120 rate = 96000; break;
1121 case HDSPM_status1_F_0*7:
1122 rate = 128000; break;
1123 case HDSPM_status1_F_0*8:
1124 rate = 176400; break;
1125 case HDSPM_status1_F_0*9:
1126 rate = 192000; break;
1127 default:
1128 rate = 0; break;
1129 }
1130 }
1131
1132 break;
1133
1134 case MADI:
1135 case AIO:
1136 case RayDAT:
1137 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1138 status = hdspm_read(hdspm, HDSPM_statusRegister);
1139 rate = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02001140
Remy Bruno3cee5a62006-10-16 12:46:32 +02001141 /* if wordclock has synced freq and wordclock is valid */
1142 if ((status2 & HDSPM_wcLock) != 0 &&
Adrian Knothfedf1532011-06-12 17:26:18 +02001143 (status2 & HDSPM_SelSyncRef0) == 0) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02001144
1145 rate_bits = status2 & HDSPM_wcFreqMask;
1146
Adrian Knoth0dca1792011-01-26 19:32:14 +01001147
Remy Bruno3cee5a62006-10-16 12:46:32 +02001148 switch (rate_bits) {
1149 case HDSPM_wcFreq32:
1150 rate = 32000;
1151 break;
1152 case HDSPM_wcFreq44_1:
1153 rate = 44100;
1154 break;
1155 case HDSPM_wcFreq48:
1156 rate = 48000;
1157 break;
1158 case HDSPM_wcFreq64:
1159 rate = 64000;
1160 break;
1161 case HDSPM_wcFreq88_2:
1162 rate = 88200;
1163 break;
1164 case HDSPM_wcFreq96:
1165 rate = 96000;
1166 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001167 default:
1168 rate = 0;
1169 break;
1170 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001171 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001172
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001173 /* if rate detected and Syncref is Word than have it,
1174 * word has priority to MADI
1175 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001176 if (rate != 0 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001177 (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
Remy Bruno3cee5a62006-10-16 12:46:32 +02001178 return rate;
1179
Adrian Knoth0dca1792011-01-26 19:32:14 +01001180 /* maybe a madi input (which is taken if sel sync is madi) */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001181 if (status & HDSPM_madiLock) {
1182 rate_bits = status & HDSPM_madiFreqMask;
1183
1184 switch (rate_bits) {
1185 case HDSPM_madiFreq32:
1186 rate = 32000;
1187 break;
1188 case HDSPM_madiFreq44_1:
1189 rate = 44100;
1190 break;
1191 case HDSPM_madiFreq48:
1192 rate = 48000;
1193 break;
1194 case HDSPM_madiFreq64:
1195 rate = 64000;
1196 break;
1197 case HDSPM_madiFreq88_2:
1198 rate = 88200;
1199 break;
1200 case HDSPM_madiFreq96:
1201 rate = 96000;
1202 break;
1203 case HDSPM_madiFreq128:
1204 rate = 128000;
1205 break;
1206 case HDSPM_madiFreq176_4:
1207 rate = 176400;
1208 break;
1209 case HDSPM_madiFreq192:
1210 rate = 192000;
1211 break;
1212 default:
1213 rate = 0;
1214 break;
1215 }
Adrian Knothd12c51d2011-07-29 03:11:03 +02001216
1217 /* QS and DS rates normally can not be detected
1218 * automatically by the card. Only exception is MADI
1219 * in 96k frame mode.
1220 *
1221 * So if we read SS values (32 .. 48k), check for
1222 * user-provided DS/QS bits in the control register
1223 * and multiply the base frequency accordingly.
1224 */
1225 if (rate <= 48000) {
1226 if (hdspm->control_register & HDSPM_QuadSpeed)
1227 rate *= 4;
1228 else if (hdspm->control_register &
1229 HDSPM_DoubleSpeed)
1230 rate *= 2;
1231 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02001232 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001233 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001234 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001235
1236 return rate;
Takashi Iwai763f3562005-06-03 11:25:34 +02001237}
1238
Adrian Knoth7cb155f2011-08-15 00:22:53 +02001239/* return latency in samples per period */
1240static int hdspm_get_latency(struct hdspm *hdspm)
1241{
1242 int n;
1243
1244 n = hdspm_decode_latency(hdspm->control_register);
1245
1246 /* Special case for new RME cards with 32 samples period size.
1247 * The three latency bits in the control register
1248 * (HDSP_LatencyMask) encode latency values of 64 samples as
1249 * 0, 128 samples as 1 ... 4096 samples as 6. For old cards, 7
1250 * denotes 8192 samples, but on new cards like RayDAT or AIO,
1251 * it corresponds to 32 samples.
1252 */
1253 if ((7 == n) && (RayDAT == hdspm->io_type || AIO == hdspm->io_type))
1254 n = -1;
1255
1256 return 1 << (n + 6);
1257}
1258
Takashi Iwai763f3562005-06-03 11:25:34 +02001259/* Latency function */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001260static inline void hdspm_compute_period_size(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001261{
Adrian Knoth7cb155f2011-08-15 00:22:53 +02001262 hdspm->period_bytes = 4 * hdspm_get_latency(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001263}
1264
Adrian Knoth0dca1792011-01-26 19:32:14 +01001265
1266static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001267{
1268 int position;
1269
1270 position = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth483cee72011-02-23 11:43:09 +01001271
1272 switch (hdspm->io_type) {
1273 case RayDAT:
1274 case AIO:
1275 position &= HDSPM_BufferPositionMask;
1276 position /= 4; /* Bytes per sample */
1277 break;
1278 default:
1279 position = (position & HDSPM_BufferID) ?
1280 (hdspm->period_bytes / 4) : 0;
1281 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001282
1283 return position;
1284}
1285
1286
Takashi Iwai98274f02005-11-17 14:52:34 +01001287static inline void hdspm_start_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001288{
1289 s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
1290 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1291}
1292
Takashi Iwai98274f02005-11-17 14:52:34 +01001293static inline void hdspm_stop_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001294{
1295 s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
1296 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1297}
1298
1299/* should I silence all or only opened ones ? doit all for first even is 4MB*/
Denys Vlasenko62cef822008-04-14 13:04:18 +02001300static void hdspm_silence_playback(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001301{
1302 int i;
1303 int n = hdspm->period_bytes;
1304 void *buf = hdspm->playback_buffer;
1305
Remy Bruno3cee5a62006-10-16 12:46:32 +02001306 if (buf == NULL)
1307 return;
Takashi Iwai763f3562005-06-03 11:25:34 +02001308
1309 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
1310 memset(buf, 0, n);
1311 buf += HDSPM_CHANNEL_BUFFER_BYTES;
1312 }
1313}
1314
Adrian Knoth0dca1792011-01-26 19:32:14 +01001315static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames)
Takashi Iwai763f3562005-06-03 11:25:34 +02001316{
1317 int n;
1318
1319 spin_lock_irq(&s->lock);
1320
Adrian Knoth2e610272011-08-15 00:22:54 +02001321 if (32 == frames) {
1322 /* Special case for new RME cards like RayDAT/AIO which
1323 * support period sizes of 32 samples. Since latency is
1324 * encoded in the three bits of HDSP_LatencyMask, we can only
1325 * have values from 0 .. 7. While 0 still means 64 samples and
1326 * 6 represents 4096 samples on all cards, 7 represents 8192
1327 * on older cards and 32 samples on new cards.
1328 *
1329 * In other words, period size in samples is calculated by
1330 * 2^(n+6) with n ranging from 0 .. 7.
1331 */
1332 n = 7;
1333 } else {
1334 frames >>= 7;
1335 n = 0;
1336 while (frames) {
1337 n++;
1338 frames >>= 1;
1339 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001340 }
Adrian Knoth2e610272011-08-15 00:22:54 +02001341
Takashi Iwai763f3562005-06-03 11:25:34 +02001342 s->control_register &= ~HDSPM_LatencyMask;
1343 s->control_register |= hdspm_encode_latency(n);
1344
1345 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1346
1347 hdspm_compute_period_size(s);
1348
1349 spin_unlock_irq(&s->lock);
1350
1351 return 0;
1352}
1353
Adrian Knoth0dca1792011-01-26 19:32:14 +01001354static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period)
1355{
1356 u64 freq_const;
1357
1358 if (period == 0)
1359 return 0;
1360
1361 switch (hdspm->io_type) {
1362 case MADI:
1363 case AES32:
1364 freq_const = 110069313433624ULL;
1365 break;
1366 case RayDAT:
1367 case AIO:
1368 freq_const = 104857600000000ULL;
1369 break;
1370 case MADIface:
1371 freq_const = 131072000000000ULL;
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001372 break;
1373 default:
1374 snd_BUG();
1375 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001376 }
1377
1378 return div_u64(freq_const, period);
1379}
1380
1381
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001382static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
1383{
1384 u64 n;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001385
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001386 if (rate >= 112000)
1387 rate /= 4;
1388 else if (rate >= 56000)
1389 rate /= 2;
1390
Adrian Knoth0dca1792011-01-26 19:32:14 +01001391 switch (hdspm->io_type) {
1392 case MADIface:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001393 n = 131072000000000ULL; /* 125 MHz */
1394 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001395 case MADI:
1396 case AES32:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001397 n = 110069313433624ULL; /* 105 MHz */
1398 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001399 case RayDAT:
1400 case AIO:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001401 n = 104857600000000ULL; /* 100 MHz */
1402 break;
1403 default:
1404 snd_BUG();
1405 return;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001406 }
1407
Takashi Iwai3f7440a2009-06-05 17:40:04 +02001408 n = div_u64(n, rate);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001409 /* n should be less than 2^32 for being written to FREQ register */
Takashi Iwaida3cec32008-08-08 17:12:14 +02001410 snd_BUG_ON(n >> 32);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001411 hdspm_write(hdspm, HDSPM_freqReg, (u32)n);
1412}
Takashi Iwai763f3562005-06-03 11:25:34 +02001413
1414/* dummy set rate lets see what happens */
Takashi Iwai98274f02005-11-17 14:52:34 +01001415static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
Takashi Iwai763f3562005-06-03 11:25:34 +02001416{
Takashi Iwai763f3562005-06-03 11:25:34 +02001417 int current_rate;
1418 int rate_bits;
1419 int not_set = 0;
Remy Bruno65345992007-08-31 12:21:08 +02001420 int current_speed, target_speed;
Takashi Iwai763f3562005-06-03 11:25:34 +02001421
1422 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
1423 it (e.g. during module initialization).
1424 */
1425
1426 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
1427
Adrian Knoth0dca1792011-01-26 19:32:14 +01001428 /* SLAVE --- */
Takashi Iwai763f3562005-06-03 11:25:34 +02001429 if (called_internally) {
1430
Adrian Knoth0dca1792011-01-26 19:32:14 +01001431 /* request from ctl or card initialization
1432 just make a warning an remember setting
1433 for future master mode switching */
1434
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001435 snd_printk(KERN_WARNING "HDSPM: "
1436 "Warning: device is not running "
1437 "as a clock master.\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001438 not_set = 1;
1439 } else {
1440
1441 /* hw_param request while in AutoSync mode */
1442 int external_freq =
1443 hdspm_external_sample_rate(hdspm);
1444
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001445 if (hdspm_autosync_ref(hdspm) ==
1446 HDSPM_AUTOSYNC_FROM_NONE) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001447
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001448 snd_printk(KERN_WARNING "HDSPM: "
1449 "Detected no Externel Sync \n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001450 not_set = 1;
1451
1452 } else if (rate != external_freq) {
1453
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001454 snd_printk(KERN_WARNING "HDSPM: "
1455 "Warning: No AutoSync source for "
1456 "requested rate\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001457 not_set = 1;
1458 }
1459 }
1460 }
1461
1462 current_rate = hdspm->system_sample_rate;
1463
1464 /* Changing between Singe, Double and Quad speed is not
1465 allowed if any substreams are open. This is because such a change
1466 causes a shift in the location of the DMA buffers and a reduction
1467 in the number of available buffers.
1468
1469 Note that a similar but essentially insoluble problem exists for
1470 externally-driven rate changes. All we can do is to flag rate
Adrian Knoth0dca1792011-01-26 19:32:14 +01001471 changes in the read/write routines.
Takashi Iwai763f3562005-06-03 11:25:34 +02001472 */
1473
Remy Bruno65345992007-08-31 12:21:08 +02001474 if (current_rate <= 48000)
1475 current_speed = HDSPM_SPEED_SINGLE;
1476 else if (current_rate <= 96000)
1477 current_speed = HDSPM_SPEED_DOUBLE;
1478 else
1479 current_speed = HDSPM_SPEED_QUAD;
1480
1481 if (rate <= 48000)
1482 target_speed = HDSPM_SPEED_SINGLE;
1483 else if (rate <= 96000)
1484 target_speed = HDSPM_SPEED_DOUBLE;
1485 else
1486 target_speed = HDSPM_SPEED_QUAD;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001487
Takashi Iwai763f3562005-06-03 11:25:34 +02001488 switch (rate) {
1489 case 32000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001490 rate_bits = HDSPM_Frequency32KHz;
1491 break;
1492 case 44100:
Takashi Iwai763f3562005-06-03 11:25:34 +02001493 rate_bits = HDSPM_Frequency44_1KHz;
1494 break;
1495 case 48000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001496 rate_bits = HDSPM_Frequency48KHz;
1497 break;
1498 case 64000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001499 rate_bits = HDSPM_Frequency64KHz;
1500 break;
1501 case 88200:
Takashi Iwai763f3562005-06-03 11:25:34 +02001502 rate_bits = HDSPM_Frequency88_2KHz;
1503 break;
1504 case 96000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001505 rate_bits = HDSPM_Frequency96KHz;
1506 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001507 case 128000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001508 rate_bits = HDSPM_Frequency128KHz;
1509 break;
1510 case 176400:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001511 rate_bits = HDSPM_Frequency176_4KHz;
1512 break;
1513 case 192000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001514 rate_bits = HDSPM_Frequency192KHz;
1515 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001516 default:
1517 return -EINVAL;
1518 }
1519
Remy Bruno65345992007-08-31 12:21:08 +02001520 if (current_speed != target_speed
Takashi Iwai763f3562005-06-03 11:25:34 +02001521 && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
1522 snd_printk
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001523 (KERN_ERR "HDSPM: "
Remy Bruno65345992007-08-31 12:21:08 +02001524 "cannot change from %s speed to %s speed mode "
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001525 "(capture PID = %d, playback PID = %d)\n",
Remy Bruno65345992007-08-31 12:21:08 +02001526 hdspm_speed_names[current_speed],
1527 hdspm_speed_names[target_speed],
Takashi Iwai763f3562005-06-03 11:25:34 +02001528 hdspm->capture_pid, hdspm->playback_pid);
1529 return -EBUSY;
1530 }
1531
1532 hdspm->control_register &= ~HDSPM_FrequencyMask;
1533 hdspm->control_register |= rate_bits;
1534 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1535
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001536 /* For AES32, need to set DDS value in FREQ register
1537 For MADI, also apparently */
1538 hdspm_set_dds_value(hdspm, rate);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001539
1540 if (AES32 == hdspm->io_type && rate != current_rate)
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001541 hdspm_write(hdspm, HDSPM_eeprom_wr, 0);
Takashi Iwai763f3562005-06-03 11:25:34 +02001542
1543 hdspm->system_sample_rate = rate;
1544
Adrian Knoth0dca1792011-01-26 19:32:14 +01001545 if (rate <= 48000) {
1546 hdspm->channel_map_in = hdspm->channel_map_in_ss;
1547 hdspm->channel_map_out = hdspm->channel_map_out_ss;
1548 hdspm->max_channels_in = hdspm->ss_in_channels;
1549 hdspm->max_channels_out = hdspm->ss_out_channels;
1550 hdspm->port_names_in = hdspm->port_names_in_ss;
1551 hdspm->port_names_out = hdspm->port_names_out_ss;
1552 } else if (rate <= 96000) {
1553 hdspm->channel_map_in = hdspm->channel_map_in_ds;
1554 hdspm->channel_map_out = hdspm->channel_map_out_ds;
1555 hdspm->max_channels_in = hdspm->ds_in_channels;
1556 hdspm->max_channels_out = hdspm->ds_out_channels;
1557 hdspm->port_names_in = hdspm->port_names_in_ds;
1558 hdspm->port_names_out = hdspm->port_names_out_ds;
1559 } else {
1560 hdspm->channel_map_in = hdspm->channel_map_in_qs;
1561 hdspm->channel_map_out = hdspm->channel_map_out_qs;
1562 hdspm->max_channels_in = hdspm->qs_in_channels;
1563 hdspm->max_channels_out = hdspm->qs_out_channels;
1564 hdspm->port_names_in = hdspm->port_names_in_qs;
1565 hdspm->port_names_out = hdspm->port_names_out_qs;
1566 }
1567
Takashi Iwai763f3562005-06-03 11:25:34 +02001568 if (not_set != 0)
1569 return -1;
1570
1571 return 0;
1572}
1573
1574/* mainly for init to 0 on load */
Takashi Iwai98274f02005-11-17 14:52:34 +01001575static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
Takashi Iwai763f3562005-06-03 11:25:34 +02001576{
1577 int i, j;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001578 unsigned int gain;
1579
1580 if (sgain > UNITY_GAIN)
1581 gain = UNITY_GAIN;
1582 else if (sgain < 0)
1583 gain = 0;
1584 else
1585 gain = sgain;
Takashi Iwai763f3562005-06-03 11:25:34 +02001586
1587 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
1588 for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
1589 hdspm_write_in_gain(hdspm, i, j, gain);
1590 hdspm_write_pb_gain(hdspm, i, j, gain);
1591 }
1592}
1593
1594/*----------------------------------------------------------------------------
1595 MIDI
1596 ----------------------------------------------------------------------------*/
1597
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001598static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm,
1599 int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001600{
1601 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001602 return hdspm_read(hdspm, hdspm->midi[id].dataIn);
Takashi Iwai763f3562005-06-03 11:25:34 +02001603}
1604
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001605static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
1606 int val)
Takashi Iwai763f3562005-06-03 11:25:34 +02001607{
1608 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001609 return hdspm_write(hdspm, hdspm->midi[id].dataOut, val);
Takashi Iwai763f3562005-06-03 11:25:34 +02001610}
1611
Takashi Iwai98274f02005-11-17 14:52:34 +01001612static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001613{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001614 return hdspm_read(hdspm, hdspm->midi[id].statusIn) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001615}
1616
Takashi Iwai98274f02005-11-17 14:52:34 +01001617static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001618{
1619 int fifo_bytes_used;
1620
Adrian Knoth0dca1792011-01-26 19:32:14 +01001621 fifo_bytes_used = hdspm_read(hdspm, hdspm->midi[id].statusOut) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001622
1623 if (fifo_bytes_used < 128)
1624 return 128 - fifo_bytes_used;
1625 else
1626 return 0;
1627}
1628
Denys Vlasenko62cef822008-04-14 13:04:18 +02001629static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001630{
1631 while (snd_hdspm_midi_input_available (hdspm, id))
1632 snd_hdspm_midi_read_byte (hdspm, id);
1633}
1634
Takashi Iwai98274f02005-11-17 14:52:34 +01001635static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001636{
1637 unsigned long flags;
1638 int n_pending;
1639 int to_write;
1640 int i;
1641 unsigned char buf[128];
1642
1643 /* Output is not interrupt driven */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001644
Takashi Iwai763f3562005-06-03 11:25:34 +02001645 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001646 if (hmidi->output &&
1647 !snd_rawmidi_transmit_empty (hmidi->output)) {
1648 n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm,
1649 hmidi->id);
1650 if (n_pending > 0) {
1651 if (n_pending > (int)sizeof (buf))
1652 n_pending = sizeof (buf);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001653
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001654 to_write = snd_rawmidi_transmit (hmidi->output, buf,
1655 n_pending);
1656 if (to_write > 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001657 for (i = 0; i < to_write; ++i)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001658 snd_hdspm_midi_write_byte (hmidi->hdspm,
1659 hmidi->id,
1660 buf[i]);
Takashi Iwai763f3562005-06-03 11:25:34 +02001661 }
1662 }
1663 }
1664 spin_unlock_irqrestore (&hmidi->lock, flags);
1665 return 0;
1666}
1667
Takashi Iwai98274f02005-11-17 14:52:34 +01001668static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001669{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001670 unsigned char buf[128]; /* this buffer is designed to match the MIDI
1671 * input FIFO size
1672 */
Takashi Iwai763f3562005-06-03 11:25:34 +02001673 unsigned long flags;
1674 int n_pending;
1675 int i;
1676
1677 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001678 n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id);
1679 if (n_pending > 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001680 if (hmidi->input) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001681 if (n_pending > (int)sizeof (buf))
Takashi Iwai763f3562005-06-03 11:25:34 +02001682 n_pending = sizeof (buf);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001683 for (i = 0; i < n_pending; ++i)
1684 buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm,
1685 hmidi->id);
1686 if (n_pending)
1687 snd_rawmidi_receive (hmidi->input, buf,
1688 n_pending);
Takashi Iwai763f3562005-06-03 11:25:34 +02001689 } else {
1690 /* flush the MIDI input FIFO */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001691 while (n_pending--)
1692 snd_hdspm_midi_read_byte (hmidi->hdspm,
1693 hmidi->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02001694 }
1695 }
1696 hmidi->pending = 0;
Adrian Knothc0da0012011-06-12 17:26:17 +02001697 spin_unlock_irqrestore(&hmidi->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001698
Adrian Knothc0da0012011-06-12 17:26:17 +02001699 spin_lock_irqsave(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001700 hmidi->hdspm->control_register |= hmidi->ie;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001701 hdspm_write(hmidi->hdspm, HDSPM_controlRegister,
1702 hmidi->hdspm->control_register);
Adrian Knothc0da0012011-06-12 17:26:17 +02001703 spin_unlock_irqrestore(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001704
Takashi Iwai763f3562005-06-03 11:25:34 +02001705 return snd_hdspm_midi_output_write (hmidi);
1706}
1707
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001708static void
1709snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001710{
Takashi Iwai98274f02005-11-17 14:52:34 +01001711 struct hdspm *hdspm;
1712 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001713 unsigned long flags;
Takashi Iwai763f3562005-06-03 11:25:34 +02001714
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001715 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001716 hdspm = hmidi->hdspm;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001717
Takashi Iwai763f3562005-06-03 11:25:34 +02001718 spin_lock_irqsave (&hdspm->lock, flags);
1719 if (up) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001720 if (!(hdspm->control_register & hmidi->ie)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001721 snd_hdspm_flush_midi_input (hdspm, hmidi->id);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001722 hdspm->control_register |= hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001723 }
1724 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001725 hdspm->control_register &= ~hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001726 }
1727
1728 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1729 spin_unlock_irqrestore (&hdspm->lock, flags);
1730}
1731
1732static void snd_hdspm_midi_output_timer(unsigned long data)
1733{
Takashi Iwai98274f02005-11-17 14:52:34 +01001734 struct hdspm_midi *hmidi = (struct hdspm_midi *) data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001735 unsigned long flags;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001736
Takashi Iwai763f3562005-06-03 11:25:34 +02001737 snd_hdspm_midi_output_write(hmidi);
1738 spin_lock_irqsave (&hmidi->lock, flags);
1739
1740 /* this does not bump hmidi->istimer, because the
1741 kernel automatically removed the timer when it
1742 expired, and we are now adding it back, thus
Adrian Knoth0dca1792011-01-26 19:32:14 +01001743 leaving istimer wherever it was set before.
Takashi Iwai763f3562005-06-03 11:25:34 +02001744 */
1745
1746 if (hmidi->istimer) {
1747 hmidi->timer.expires = 1 + jiffies;
1748 add_timer(&hmidi->timer);
1749 }
1750
1751 spin_unlock_irqrestore (&hmidi->lock, flags);
1752}
1753
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001754static void
1755snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001756{
Takashi Iwai98274f02005-11-17 14:52:34 +01001757 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001758 unsigned long flags;
1759
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001760 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001761 spin_lock_irqsave (&hmidi->lock, flags);
1762 if (up) {
1763 if (!hmidi->istimer) {
1764 init_timer(&hmidi->timer);
1765 hmidi->timer.function = snd_hdspm_midi_output_timer;
1766 hmidi->timer.data = (unsigned long) hmidi;
1767 hmidi->timer.expires = 1 + jiffies;
1768 add_timer(&hmidi->timer);
1769 hmidi->istimer++;
1770 }
1771 } else {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001772 if (hmidi->istimer && --hmidi->istimer <= 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02001773 del_timer (&hmidi->timer);
Takashi Iwai763f3562005-06-03 11:25:34 +02001774 }
1775 spin_unlock_irqrestore (&hmidi->lock, flags);
1776 if (up)
1777 snd_hdspm_midi_output_write(hmidi);
1778}
1779
Takashi Iwai98274f02005-11-17 14:52:34 +01001780static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001781{
Takashi Iwai98274f02005-11-17 14:52:34 +01001782 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001783
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001784 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001785 spin_lock_irq (&hmidi->lock);
1786 snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
1787 hmidi->input = substream;
1788 spin_unlock_irq (&hmidi->lock);
1789
1790 return 0;
1791}
1792
Takashi Iwai98274f02005-11-17 14:52:34 +01001793static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001794{
Takashi Iwai98274f02005-11-17 14:52:34 +01001795 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001796
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001797 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001798 spin_lock_irq (&hmidi->lock);
1799 hmidi->output = substream;
1800 spin_unlock_irq (&hmidi->lock);
1801
1802 return 0;
1803}
1804
Takashi Iwai98274f02005-11-17 14:52:34 +01001805static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001806{
Takashi Iwai98274f02005-11-17 14:52:34 +01001807 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001808
1809 snd_hdspm_midi_input_trigger (substream, 0);
1810
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001811 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001812 spin_lock_irq (&hmidi->lock);
1813 hmidi->input = NULL;
1814 spin_unlock_irq (&hmidi->lock);
1815
1816 return 0;
1817}
1818
Takashi Iwai98274f02005-11-17 14:52:34 +01001819static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001820{
Takashi Iwai98274f02005-11-17 14:52:34 +01001821 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001822
1823 snd_hdspm_midi_output_trigger (substream, 0);
1824
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001825 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001826 spin_lock_irq (&hmidi->lock);
1827 hmidi->output = NULL;
1828 spin_unlock_irq (&hmidi->lock);
1829
1830 return 0;
1831}
1832
Takashi Iwai98274f02005-11-17 14:52:34 +01001833static struct snd_rawmidi_ops snd_hdspm_midi_output =
Takashi Iwai763f3562005-06-03 11:25:34 +02001834{
1835 .open = snd_hdspm_midi_output_open,
1836 .close = snd_hdspm_midi_output_close,
1837 .trigger = snd_hdspm_midi_output_trigger,
1838};
1839
Takashi Iwai98274f02005-11-17 14:52:34 +01001840static struct snd_rawmidi_ops snd_hdspm_midi_input =
Takashi Iwai763f3562005-06-03 11:25:34 +02001841{
1842 .open = snd_hdspm_midi_input_open,
1843 .close = snd_hdspm_midi_input_close,
1844 .trigger = snd_hdspm_midi_input_trigger,
1845};
1846
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001847static int __devinit snd_hdspm_create_midi (struct snd_card *card,
1848 struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001849{
1850 int err;
1851 char buf[32];
1852
1853 hdspm->midi[id].id = id;
Takashi Iwai763f3562005-06-03 11:25:34 +02001854 hdspm->midi[id].hdspm = hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +02001855 spin_lock_init (&hdspm->midi[id].lock);
1856
Adrian Knoth0dca1792011-01-26 19:32:14 +01001857 if (0 == id) {
1858 if (MADIface == hdspm->io_type) {
1859 /* MIDI-over-MADI on HDSPe MADIface */
1860 hdspm->midi[0].dataIn = HDSPM_midiDataIn2;
1861 hdspm->midi[0].statusIn = HDSPM_midiStatusIn2;
1862 hdspm->midi[0].dataOut = HDSPM_midiDataOut2;
1863 hdspm->midi[0].statusOut = HDSPM_midiStatusOut2;
1864 hdspm->midi[0].ie = HDSPM_Midi2InterruptEnable;
1865 hdspm->midi[0].irq = HDSPM_midi2IRQPending;
1866 } else {
1867 hdspm->midi[0].dataIn = HDSPM_midiDataIn0;
1868 hdspm->midi[0].statusIn = HDSPM_midiStatusIn0;
1869 hdspm->midi[0].dataOut = HDSPM_midiDataOut0;
1870 hdspm->midi[0].statusOut = HDSPM_midiStatusOut0;
1871 hdspm->midi[0].ie = HDSPM_Midi0InterruptEnable;
1872 hdspm->midi[0].irq = HDSPM_midi0IRQPending;
1873 }
1874 } else if (1 == id) {
1875 hdspm->midi[1].dataIn = HDSPM_midiDataIn1;
1876 hdspm->midi[1].statusIn = HDSPM_midiStatusIn1;
1877 hdspm->midi[1].dataOut = HDSPM_midiDataOut1;
1878 hdspm->midi[1].statusOut = HDSPM_midiStatusOut1;
1879 hdspm->midi[1].ie = HDSPM_Midi1InterruptEnable;
1880 hdspm->midi[1].irq = HDSPM_midi1IRQPending;
1881 } else if ((2 == id) && (MADI == hdspm->io_type)) {
1882 /* MIDI-over-MADI on HDSPe MADI */
1883 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1884 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1885 hdspm->midi[2].dataOut = HDSPM_midiDataOut2;
1886 hdspm->midi[2].statusOut = HDSPM_midiStatusOut2;
1887 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1888 hdspm->midi[2].irq = HDSPM_midi2IRQPending;
1889 } else if (2 == id) {
1890 /* TCO MTC, read only */
1891 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1892 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1893 hdspm->midi[2].dataOut = -1;
1894 hdspm->midi[2].statusOut = -1;
1895 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1896 hdspm->midi[2].irq = HDSPM_midi2IRQPendingAES;
1897 } else if (3 == id) {
1898 /* TCO MTC on HDSPe MADI */
1899 hdspm->midi[3].dataIn = HDSPM_midiDataIn3;
1900 hdspm->midi[3].statusIn = HDSPM_midiStatusIn3;
1901 hdspm->midi[3].dataOut = -1;
1902 hdspm->midi[3].statusOut = -1;
1903 hdspm->midi[3].ie = HDSPM_Midi3InterruptEnable;
1904 hdspm->midi[3].irq = HDSPM_midi3IRQPending;
1905 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001906
Adrian Knoth0dca1792011-01-26 19:32:14 +01001907 if ((id < 2) || ((2 == id) && ((MADI == hdspm->io_type) ||
1908 (MADIface == hdspm->io_type)))) {
1909 if ((id == 0) && (MADIface == hdspm->io_type)) {
1910 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1911 } else if ((id == 2) && (MADI == hdspm->io_type)) {
1912 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1913 } else {
1914 sprintf(buf, "%s MIDI %d", card->shortname, id+1);
1915 }
1916 err = snd_rawmidi_new(card, buf, id, 1, 1,
1917 &hdspm->midi[id].rmidi);
1918 if (err < 0)
1919 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02001920
Adrian Knoth0dca1792011-01-26 19:32:14 +01001921 sprintf(hdspm->midi[id].rmidi->name, "%s MIDI %d",
1922 card->id, id+1);
1923 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
Takashi Iwai763f3562005-06-03 11:25:34 +02001924
Adrian Knoth0dca1792011-01-26 19:32:14 +01001925 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1926 SNDRV_RAWMIDI_STREAM_OUTPUT,
1927 &snd_hdspm_midi_output);
1928 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1929 SNDRV_RAWMIDI_STREAM_INPUT,
1930 &snd_hdspm_midi_input);
1931
1932 hdspm->midi[id].rmidi->info_flags |=
1933 SNDRV_RAWMIDI_INFO_OUTPUT |
1934 SNDRV_RAWMIDI_INFO_INPUT |
1935 SNDRV_RAWMIDI_INFO_DUPLEX;
1936 } else {
1937 /* TCO MTC, read only */
1938 sprintf(buf, "%s MTC %d", card->shortname, id+1);
1939 err = snd_rawmidi_new(card, buf, id, 1, 1,
1940 &hdspm->midi[id].rmidi);
1941 if (err < 0)
1942 return err;
1943
1944 sprintf(hdspm->midi[id].rmidi->name,
1945 "%s MTC %d", card->id, id+1);
1946 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
1947
1948 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1949 SNDRV_RAWMIDI_STREAM_INPUT,
1950 &snd_hdspm_midi_input);
1951
1952 hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
1953 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001954
1955 return 0;
1956}
1957
1958
1959static void hdspm_midi_tasklet(unsigned long arg)
1960{
Takashi Iwai98274f02005-11-17 14:52:34 +01001961 struct hdspm *hdspm = (struct hdspm *)arg;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001962 int i = 0;
1963
1964 while (i < hdspm->midiPorts) {
1965 if (hdspm->midi[i].pending)
1966 snd_hdspm_midi_input_read(&hdspm->midi[i]);
1967
1968 i++;
1969 }
1970}
Takashi Iwai763f3562005-06-03 11:25:34 +02001971
1972
1973/*-----------------------------------------------------------------------------
1974 Status Interface
1975 ----------------------------------------------------------------------------*/
1976
1977/* get the system sample rate which is set */
1978
Adrian Knoth0dca1792011-01-26 19:32:14 +01001979
1980/**
1981 * Calculate the real sample rate from the
1982 * current DDS value.
1983 **/
1984static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
1985{
1986 unsigned int period, rate;
1987
1988 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
1989 rate = hdspm_calc_dds_value(hdspm, period);
1990
Adrian Knotha97bda72012-05-30 14:23:18 +02001991 if (rate > 207000) {
1992 /* Unreasonable high sample rate as seen on PCI MADI cards.
1993 * Use the cached value instead.
1994 */
1995 rate = hdspm->system_sample_rate;
1996 }
1997
Adrian Knoth0dca1792011-01-26 19:32:14 +01001998 return rate;
1999}
2000
2001
Takashi Iwai763f3562005-06-03 11:25:34 +02002002#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002003{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002004 .name = xname, \
2005 .index = xindex, \
Adrian Knoth41285a92012-10-19 17:42:22 +02002006 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2007 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002008 .info = snd_hdspm_info_system_sample_rate, \
Adrian Knoth41285a92012-10-19 17:42:22 +02002009 .put = snd_hdspm_put_system_sample_rate, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002010 .get = snd_hdspm_get_system_sample_rate \
2011}
2012
Takashi Iwai98274f02005-11-17 14:52:34 +01002013static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
2014 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002015{
2016 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2017 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002018 uinfo->value.integer.min = 27000;
2019 uinfo->value.integer.max = 207000;
2020 uinfo->value.integer.step = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002021 return 0;
2022}
2023
Adrian Knoth0dca1792011-01-26 19:32:14 +01002024
Takashi Iwai98274f02005-11-17 14:52:34 +01002025static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
2026 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002027 ucontrol)
2028{
Takashi Iwai98274f02005-11-17 14:52:34 +01002029 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002030
Adrian Knoth0dca1792011-01-26 19:32:14 +01002031 ucontrol->value.integer.value[0] = hdspm_get_system_sample_rate(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002032 return 0;
2033}
2034
Adrian Knoth41285a92012-10-19 17:42:22 +02002035static int snd_hdspm_put_system_sample_rate(struct snd_kcontrol *kcontrol,
2036 struct snd_ctl_elem_value *
2037 ucontrol)
2038{
2039 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2040
2041 hdspm_set_dds_value(hdspm, ucontrol->value.enumerated.item[0]);
2042 return 0;
2043}
2044
Adrian Knoth0dca1792011-01-26 19:32:14 +01002045
2046/**
2047 * Returns the WordClock sample rate class for the given card.
2048 **/
2049static int hdspm_get_wc_sample_rate(struct hdspm *hdspm)
2050{
2051 int status;
2052
2053 switch (hdspm->io_type) {
2054 case RayDAT:
2055 case AIO:
2056 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2057 return (status >> 16) & 0xF;
2058 break;
2059 default:
2060 break;
2061 }
2062
2063
2064 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002065}
2066
Adrian Knoth0dca1792011-01-26 19:32:14 +01002067
2068/**
2069 * Returns the TCO sample rate class for the given card.
2070 **/
2071static int hdspm_get_tco_sample_rate(struct hdspm *hdspm)
2072{
2073 int status;
2074
2075 if (hdspm->tco) {
2076 switch (hdspm->io_type) {
2077 case RayDAT:
2078 case AIO:
2079 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2080 return (status >> 20) & 0xF;
2081 break;
2082 default:
2083 break;
2084 }
2085 }
2086
2087 return 0;
2088}
2089
2090
2091/**
2092 * Returns the SYNC_IN sample rate class for the given card.
2093 **/
2094static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm)
2095{
2096 int status;
2097
2098 if (hdspm->tco) {
2099 switch (hdspm->io_type) {
2100 case RayDAT:
2101 case AIO:
2102 status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2103 return (status >> 12) & 0xF;
2104 break;
2105 default:
2106 break;
2107 }
2108 }
2109
2110 return 0;
2111}
2112
2113
2114/**
2115 * Returns the sample rate class for input source <idx> for
2116 * 'new style' cards like the AIO and RayDAT.
2117 **/
2118static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
2119{
2120 int status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2121
2122 return (status >> (idx*4)) & 0xF;
2123}
2124
2125
2126
2127#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
2128{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2129 .name = xname, \
2130 .private_value = xindex, \
2131 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2132 .info = snd_hdspm_info_autosync_sample_rate, \
2133 .get = snd_hdspm_get_autosync_sample_rate \
2134}
2135
2136
Takashi Iwai98274f02005-11-17 14:52:34 +01002137static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2138 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002139{
Takashi Iwai763f3562005-06-03 11:25:34 +02002140 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2141 uinfo->count = 1;
2142 uinfo->value.enumerated.items = 10;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002143
Takashi Iwai763f3562005-06-03 11:25:34 +02002144 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
Adrian Knoth0dca1792011-01-26 19:32:14 +01002145 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002146 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002147 texts_freq[uinfo->value.enumerated.item]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002148 return 0;
2149}
2150
Adrian Knoth0dca1792011-01-26 19:32:14 +01002151
Takashi Iwai98274f02005-11-17 14:52:34 +01002152static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2153 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002154 ucontrol)
2155{
Takashi Iwai98274f02005-11-17 14:52:34 +01002156 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002157
Adrian Knoth0dca1792011-01-26 19:32:14 +01002158 switch (hdspm->io_type) {
2159 case RayDAT:
2160 switch (kcontrol->private_value) {
2161 case 0:
2162 ucontrol->value.enumerated.item[0] =
2163 hdspm_get_wc_sample_rate(hdspm);
2164 break;
2165 case 7:
2166 ucontrol->value.enumerated.item[0] =
2167 hdspm_get_tco_sample_rate(hdspm);
2168 break;
2169 case 8:
2170 ucontrol->value.enumerated.item[0] =
2171 hdspm_get_sync_in_sample_rate(hdspm);
2172 break;
2173 default:
2174 ucontrol->value.enumerated.item[0] =
2175 hdspm_get_s1_sample_rate(hdspm,
2176 kcontrol->private_value-1);
2177 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002178
Adrian Knoth0dca1792011-01-26 19:32:14 +01002179 case AIO:
2180 switch (kcontrol->private_value) {
2181 case 0: /* WC */
2182 ucontrol->value.enumerated.item[0] =
2183 hdspm_get_wc_sample_rate(hdspm);
2184 break;
2185 case 4: /* TCO */
2186 ucontrol->value.enumerated.item[0] =
2187 hdspm_get_tco_sample_rate(hdspm);
2188 break;
2189 case 5: /* SYNC_IN */
2190 ucontrol->value.enumerated.item[0] =
2191 hdspm_get_sync_in_sample_rate(hdspm);
2192 break;
2193 default:
2194 ucontrol->value.enumerated.item[0] =
2195 hdspm_get_s1_sample_rate(hdspm,
2196 ucontrol->id.index-1);
2197 }
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002198
2199 case AES32:
2200
2201 switch (kcontrol->private_value) {
2202 case 0: /* WC */
2203 ucontrol->value.enumerated.item[0] =
2204 hdspm_get_wc_sample_rate(hdspm);
2205 break;
2206 case 9: /* TCO */
2207 ucontrol->value.enumerated.item[0] =
2208 hdspm_get_tco_sample_rate(hdspm);
2209 break;
2210 case 10: /* SYNC_IN */
2211 ucontrol->value.enumerated.item[0] =
2212 hdspm_get_sync_in_sample_rate(hdspm);
2213 break;
2214 default: /* AES1 to AES8 */
2215 ucontrol->value.enumerated.item[0] =
2216 hdspm_get_s1_sample_rate(hdspm,
2217 kcontrol->private_value-1);
2218 break;
2219
2220 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002221 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002222 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002223 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002224
Takashi Iwai763f3562005-06-03 11:25:34 +02002225 return 0;
2226}
2227
Adrian Knoth0dca1792011-01-26 19:32:14 +01002228
Takashi Iwai763f3562005-06-03 11:25:34 +02002229#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002230{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2231 .name = xname, \
2232 .index = xindex, \
2233 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2234 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2235 .info = snd_hdspm_info_system_clock_mode, \
2236 .get = snd_hdspm_get_system_clock_mode, \
2237 .put = snd_hdspm_put_system_clock_mode, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002238}
2239
2240
Adrian Knoth0dca1792011-01-26 19:32:14 +01002241/**
2242 * Returns the system clock mode for the given card.
2243 * @returns 0 - master, 1 - slave
2244 **/
2245static int hdspm_system_clock_mode(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002246{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002247 switch (hdspm->io_type) {
2248 case AIO:
2249 case RayDAT:
2250 if (hdspm->settings_register & HDSPM_c0Master)
2251 return 0;
2252 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002253
Adrian Knoth0dca1792011-01-26 19:32:14 +01002254 default:
2255 if (hdspm->control_register & HDSPM_ClockModeMaster)
2256 return 0;
2257 }
2258
Takashi Iwai763f3562005-06-03 11:25:34 +02002259 return 1;
2260}
2261
Adrian Knoth0dca1792011-01-26 19:32:14 +01002262
2263/**
2264 * Sets the system clock mode.
2265 * @param mode 0 - master, 1 - slave
2266 **/
2267static void hdspm_set_system_clock_mode(struct hdspm *hdspm, int mode)
2268{
2269 switch (hdspm->io_type) {
2270 case AIO:
2271 case RayDAT:
2272 if (0 == mode)
2273 hdspm->settings_register |= HDSPM_c0Master;
2274 else
2275 hdspm->settings_register &= ~HDSPM_c0Master;
2276
2277 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2278 break;
2279
2280 default:
2281 if (0 == mode)
2282 hdspm->control_register |= HDSPM_ClockModeMaster;
2283 else
2284 hdspm->control_register &= ~HDSPM_ClockModeMaster;
2285
2286 hdspm_write(hdspm, HDSPM_controlRegister,
2287 hdspm->control_register);
2288 }
2289}
2290
2291
Takashi Iwai98274f02005-11-17 14:52:34 +01002292static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
2293 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002294{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002295 static char *texts[] = { "Master", "AutoSync" };
Takashi Iwai763f3562005-06-03 11:25:34 +02002296
2297 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2298 uinfo->count = 1;
2299 uinfo->value.enumerated.items = 2;
2300 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2301 uinfo->value.enumerated.item =
2302 uinfo->value.enumerated.items - 1;
2303 strcpy(uinfo->value.enumerated.name,
2304 texts[uinfo->value.enumerated.item]);
2305 return 0;
2306}
2307
Takashi Iwai98274f02005-11-17 14:52:34 +01002308static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
2309 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002310{
Takashi Iwai98274f02005-11-17 14:52:34 +01002311 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002312
Adrian Knoth0dca1792011-01-26 19:32:14 +01002313 ucontrol->value.enumerated.item[0] = hdspm_system_clock_mode(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002314 return 0;
2315}
2316
Adrian Knoth0dca1792011-01-26 19:32:14 +01002317static int snd_hdspm_put_system_clock_mode(struct snd_kcontrol *kcontrol,
2318 struct snd_ctl_elem_value *ucontrol)
2319{
2320 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2321 int val;
2322
2323 if (!snd_hdspm_use_is_exclusive(hdspm))
2324 return -EBUSY;
2325
2326 val = ucontrol->value.enumerated.item[0];
2327 if (val < 0)
2328 val = 0;
2329 else if (val > 1)
2330 val = 1;
2331
2332 hdspm_set_system_clock_mode(hdspm, val);
2333
2334 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002335}
2336
Adrian Knoth0dca1792011-01-26 19:32:14 +01002337
2338#define HDSPM_INTERNAL_CLOCK(xname, xindex) \
2339{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2340 .name = xname, \
2341 .index = xindex, \
2342 .info = snd_hdspm_info_clock_source, \
2343 .get = snd_hdspm_get_clock_source, \
2344 .put = snd_hdspm_put_clock_source \
2345}
2346
2347
Takashi Iwai98274f02005-11-17 14:52:34 +01002348static int hdspm_clock_source(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002349{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002350 switch (hdspm->system_sample_rate) {
2351 case 32000: return 0;
2352 case 44100: return 1;
2353 case 48000: return 2;
2354 case 64000: return 3;
2355 case 88200: return 4;
2356 case 96000: return 5;
2357 case 128000: return 6;
2358 case 176400: return 7;
2359 case 192000: return 8;
Takashi Iwai763f3562005-06-03 11:25:34 +02002360 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002361
2362 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002363}
2364
Takashi Iwai98274f02005-11-17 14:52:34 +01002365static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
Takashi Iwai763f3562005-06-03 11:25:34 +02002366{
2367 int rate;
2368 switch (mode) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002369 case 0:
2370 rate = 32000; break;
2371 case 1:
2372 rate = 44100; break;
2373 case 2:
2374 rate = 48000; break;
2375 case 3:
2376 rate = 64000; break;
2377 case 4:
2378 rate = 88200; break;
2379 case 5:
2380 rate = 96000; break;
2381 case 6:
2382 rate = 128000; break;
2383 case 7:
2384 rate = 176400; break;
2385 case 8:
2386 rate = 192000; break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002387 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002388 rate = 48000;
Takashi Iwai763f3562005-06-03 11:25:34 +02002389 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002390 hdspm_set_rate(hdspm, rate, 1);
2391 return 0;
2392}
2393
Takashi Iwai98274f02005-11-17 14:52:34 +01002394static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
2395 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002396{
Takashi Iwai763f3562005-06-03 11:25:34 +02002397 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2398 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002399 uinfo->value.enumerated.items = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002400
2401 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2402 uinfo->value.enumerated.item =
2403 uinfo->value.enumerated.items - 1;
2404
2405 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002406 texts_freq[uinfo->value.enumerated.item+1]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002407
2408 return 0;
2409}
2410
Takashi Iwai98274f02005-11-17 14:52:34 +01002411static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
2412 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002413{
Takashi Iwai98274f02005-11-17 14:52:34 +01002414 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002415
2416 ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
2417 return 0;
2418}
2419
Takashi Iwai98274f02005-11-17 14:52:34 +01002420static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
2421 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002422{
Takashi Iwai98274f02005-11-17 14:52:34 +01002423 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002424 int change;
2425 int val;
2426
2427 if (!snd_hdspm_use_is_exclusive(hdspm))
2428 return -EBUSY;
2429 val = ucontrol->value.enumerated.item[0];
2430 if (val < 0)
2431 val = 0;
Remy Bruno65345992007-08-31 12:21:08 +02002432 if (val > 9)
2433 val = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002434 spin_lock_irq(&hdspm->lock);
2435 if (val != hdspm_clock_source(hdspm))
2436 change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
2437 else
2438 change = 0;
2439 spin_unlock_irq(&hdspm->lock);
2440 return change;
2441}
2442
Adrian Knoth0dca1792011-01-26 19:32:14 +01002443
Takashi Iwai763f3562005-06-03 11:25:34 +02002444#define HDSPM_PREF_SYNC_REF(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002445{.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2446 .name = xname, \
2447 .index = xindex, \
2448 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2449 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2450 .info = snd_hdspm_info_pref_sync_ref, \
2451 .get = snd_hdspm_get_pref_sync_ref, \
2452 .put = snd_hdspm_put_pref_sync_ref \
Takashi Iwai763f3562005-06-03 11:25:34 +02002453}
2454
Adrian Knoth0dca1792011-01-26 19:32:14 +01002455
2456/**
2457 * Returns the current preferred sync reference setting.
2458 * The semantics of the return value are depending on the
2459 * card, please see the comments for clarification.
2460 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002461static int hdspm_pref_sync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002462{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002463 switch (hdspm->io_type) {
2464 case AES32:
Remy Bruno3cee5a62006-10-16 12:46:32 +02002465 switch (hdspm->control_register & HDSPM_SyncRefMask) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002466 case 0: return 0; /* WC */
2467 case HDSPM_SyncRef0: return 1; /* AES 1 */
2468 case HDSPM_SyncRef1: return 2; /* AES 2 */
2469 case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; /* AES 3 */
2470 case HDSPM_SyncRef2: return 4; /* AES 4 */
2471 case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; /* AES 5 */
2472 case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; /* AES 6 */
2473 case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0:
2474 return 7; /* AES 7 */
2475 case HDSPM_SyncRef3: return 8; /* AES 8 */
2476 case HDSPM_SyncRef3+HDSPM_SyncRef0: return 9; /* TCO */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002477 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002478 break;
2479
2480 case MADI:
2481 case MADIface:
2482 if (hdspm->tco) {
2483 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2484 case 0: return 0; /* WC */
2485 case HDSPM_SyncRef0: return 1; /* MADI */
2486 case HDSPM_SyncRef1: return 2; /* TCO */
2487 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2488 return 3; /* SYNC_IN */
2489 }
2490 } else {
2491 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2492 case 0: return 0; /* WC */
2493 case HDSPM_SyncRef0: return 1; /* MADI */
2494 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2495 return 2; /* SYNC_IN */
2496 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02002497 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002498 break;
2499
2500 case RayDAT:
2501 if (hdspm->tco) {
2502 switch ((hdspm->settings_register &
2503 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2504 case 0: return 0; /* WC */
2505 case 3: return 1; /* ADAT 1 */
2506 case 4: return 2; /* ADAT 2 */
2507 case 5: return 3; /* ADAT 3 */
2508 case 6: return 4; /* ADAT 4 */
2509 case 1: return 5; /* AES */
2510 case 2: return 6; /* SPDIF */
2511 case 9: return 7; /* TCO */
2512 case 10: return 8; /* SYNC_IN */
2513 }
2514 } else {
2515 switch ((hdspm->settings_register &
2516 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2517 case 0: return 0; /* WC */
2518 case 3: return 1; /* ADAT 1 */
2519 case 4: return 2; /* ADAT 2 */
2520 case 5: return 3; /* ADAT 3 */
2521 case 6: return 4; /* ADAT 4 */
2522 case 1: return 5; /* AES */
2523 case 2: return 6; /* SPDIF */
2524 case 10: return 7; /* SYNC_IN */
2525 }
2526 }
2527
2528 break;
2529
2530 case AIO:
2531 if (hdspm->tco) {
2532 switch ((hdspm->settings_register &
2533 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2534 case 0: return 0; /* WC */
2535 case 3: return 1; /* ADAT */
2536 case 1: return 2; /* AES */
2537 case 2: return 3; /* SPDIF */
2538 case 9: return 4; /* TCO */
2539 case 10: return 5; /* SYNC_IN */
2540 }
2541 } else {
2542 switch ((hdspm->settings_register &
2543 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2544 case 0: return 0; /* WC */
2545 case 3: return 1; /* ADAT */
2546 case 1: return 2; /* AES */
2547 case 2: return 3; /* SPDIF */
2548 case 10: return 4; /* SYNC_IN */
2549 }
2550 }
2551
2552 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002553 }
2554
Adrian Knoth0dca1792011-01-26 19:32:14 +01002555 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002556}
2557
Adrian Knoth0dca1792011-01-26 19:32:14 +01002558
2559/**
2560 * Set the preferred sync reference to <pref>. The semantics
2561 * of <pref> are depending on the card type, see the comments
2562 * for clarification.
2563 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002564static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
Takashi Iwai763f3562005-06-03 11:25:34 +02002565{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002566 int p = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002567
Adrian Knoth0dca1792011-01-26 19:32:14 +01002568 switch (hdspm->io_type) {
2569 case AES32:
2570 hdspm->control_register &= ~HDSPM_SyncRefMask;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002571 switch (pref) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002572 case 0: /* WC */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002573 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002574 case 1: /* AES 1 */
2575 hdspm->control_register |= HDSPM_SyncRef0;
2576 break;
2577 case 2: /* AES 2 */
2578 hdspm->control_register |= HDSPM_SyncRef1;
2579 break;
2580 case 3: /* AES 3 */
2581 hdspm->control_register |=
2582 HDSPM_SyncRef1+HDSPM_SyncRef0;
2583 break;
2584 case 4: /* AES 4 */
2585 hdspm->control_register |= HDSPM_SyncRef2;
2586 break;
2587 case 5: /* AES 5 */
2588 hdspm->control_register |=
2589 HDSPM_SyncRef2+HDSPM_SyncRef0;
2590 break;
2591 case 6: /* AES 6 */
2592 hdspm->control_register |=
2593 HDSPM_SyncRef2+HDSPM_SyncRef1;
2594 break;
2595 case 7: /* AES 7 */
2596 hdspm->control_register |=
2597 HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
2598 break;
2599 case 8: /* AES 8 */
2600 hdspm->control_register |= HDSPM_SyncRef3;
2601 break;
2602 case 9: /* TCO */
2603 hdspm->control_register |=
2604 HDSPM_SyncRef3+HDSPM_SyncRef0;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002605 break;
2606 default:
2607 return -1;
2608 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002609
2610 break;
2611
2612 case MADI:
2613 case MADIface:
2614 hdspm->control_register &= ~HDSPM_SyncRefMask;
2615 if (hdspm->tco) {
2616 switch (pref) {
2617 case 0: /* WC */
2618 break;
2619 case 1: /* MADI */
2620 hdspm->control_register |= HDSPM_SyncRef0;
2621 break;
2622 case 2: /* TCO */
2623 hdspm->control_register |= HDSPM_SyncRef1;
2624 break;
2625 case 3: /* SYNC_IN */
2626 hdspm->control_register |=
2627 HDSPM_SyncRef0+HDSPM_SyncRef1;
2628 break;
2629 default:
2630 return -1;
2631 }
2632 } else {
2633 switch (pref) {
2634 case 0: /* WC */
2635 break;
2636 case 1: /* MADI */
2637 hdspm->control_register |= HDSPM_SyncRef0;
2638 break;
2639 case 2: /* SYNC_IN */
2640 hdspm->control_register |=
2641 HDSPM_SyncRef0+HDSPM_SyncRef1;
2642 break;
2643 default:
2644 return -1;
2645 }
2646 }
2647
2648 break;
2649
2650 case RayDAT:
2651 if (hdspm->tco) {
2652 switch (pref) {
2653 case 0: p = 0; break; /* WC */
2654 case 1: p = 3; break; /* ADAT 1 */
2655 case 2: p = 4; break; /* ADAT 2 */
2656 case 3: p = 5; break; /* ADAT 3 */
2657 case 4: p = 6; break; /* ADAT 4 */
2658 case 5: p = 1; break; /* AES */
2659 case 6: p = 2; break; /* SPDIF */
2660 case 7: p = 9; break; /* TCO */
2661 case 8: p = 10; break; /* SYNC_IN */
2662 default: return -1;
2663 }
2664 } else {
2665 switch (pref) {
2666 case 0: p = 0; break; /* WC */
2667 case 1: p = 3; break; /* ADAT 1 */
2668 case 2: p = 4; break; /* ADAT 2 */
2669 case 3: p = 5; break; /* ADAT 3 */
2670 case 4: p = 6; break; /* ADAT 4 */
2671 case 5: p = 1; break; /* AES */
2672 case 6: p = 2; break; /* SPDIF */
2673 case 7: p = 10; break; /* SYNC_IN */
2674 default: return -1;
2675 }
2676 }
2677 break;
2678
2679 case AIO:
2680 if (hdspm->tco) {
2681 switch (pref) {
2682 case 0: p = 0; break; /* WC */
2683 case 1: p = 3; break; /* ADAT */
2684 case 2: p = 1; break; /* AES */
2685 case 3: p = 2; break; /* SPDIF */
2686 case 4: p = 9; break; /* TCO */
2687 case 5: p = 10; break; /* SYNC_IN */
2688 default: return -1;
2689 }
2690 } else {
2691 switch (pref) {
2692 case 0: p = 0; break; /* WC */
2693 case 1: p = 3; break; /* ADAT */
2694 case 2: p = 1; break; /* AES */
2695 case 3: p = 2; break; /* SPDIF */
2696 case 4: p = 10; break; /* SYNC_IN */
2697 default: return -1;
2698 }
2699 }
2700 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002701 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002702
2703 switch (hdspm->io_type) {
2704 case RayDAT:
2705 case AIO:
2706 hdspm->settings_register &= ~HDSPM_c0_SyncRefMask;
2707 hdspm->settings_register |= HDSPM_c0_SyncRef0 * p;
2708 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2709 break;
2710
2711 case MADI:
2712 case MADIface:
2713 case AES32:
2714 hdspm_write(hdspm, HDSPM_controlRegister,
2715 hdspm->control_register);
2716 }
2717
Takashi Iwai763f3562005-06-03 11:25:34 +02002718 return 0;
2719}
2720
Adrian Knoth0dca1792011-01-26 19:32:14 +01002721
Takashi Iwai98274f02005-11-17 14:52:34 +01002722static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
2723 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002724{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002725 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002726
Adrian Knoth0dca1792011-01-26 19:32:14 +01002727 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2728 uinfo->count = 1;
2729 uinfo->value.enumerated.items = hdspm->texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +02002730
Adrian Knoth0dca1792011-01-26 19:32:14 +01002731 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2732 uinfo->value.enumerated.item =
2733 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002734
Adrian Knoth0dca1792011-01-26 19:32:14 +01002735 strcpy(uinfo->value.enumerated.name,
2736 hdspm->texts_autosync[uinfo->value.enumerated.item]);
Remy Bruno3cee5a62006-10-16 12:46:32 +02002737
Takashi Iwai763f3562005-06-03 11:25:34 +02002738 return 0;
2739}
2740
Takashi Iwai98274f02005-11-17 14:52:34 +01002741static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
2742 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002743{
Takashi Iwai98274f02005-11-17 14:52:34 +01002744 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002745 int psf = hdspm_pref_sync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002746
Adrian Knoth0dca1792011-01-26 19:32:14 +01002747 if (psf >= 0) {
2748 ucontrol->value.enumerated.item[0] = psf;
2749 return 0;
2750 }
2751
2752 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002753}
2754
Takashi Iwai98274f02005-11-17 14:52:34 +01002755static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
2756 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002757{
Takashi Iwai98274f02005-11-17 14:52:34 +01002758 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002759 int val, change = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002760
2761 if (!snd_hdspm_use_is_exclusive(hdspm))
2762 return -EBUSY;
2763
Adrian Knoth0dca1792011-01-26 19:32:14 +01002764 val = ucontrol->value.enumerated.item[0];
2765
2766 if (val < 0)
2767 val = 0;
2768 else if (val >= hdspm->texts_autosync_items)
2769 val = hdspm->texts_autosync_items-1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002770
2771 spin_lock_irq(&hdspm->lock);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002772 if (val != hdspm_pref_sync_ref(hdspm))
2773 change = (0 == hdspm_set_pref_sync_ref(hdspm, val)) ? 1 : 0;
2774
Takashi Iwai763f3562005-06-03 11:25:34 +02002775 spin_unlock_irq(&hdspm->lock);
2776 return change;
2777}
2778
Adrian Knoth0dca1792011-01-26 19:32:14 +01002779
Takashi Iwai763f3562005-06-03 11:25:34 +02002780#define HDSPM_AUTOSYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002781{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002782 .name = xname, \
2783 .index = xindex, \
2784 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2785 .info = snd_hdspm_info_autosync_ref, \
2786 .get = snd_hdspm_get_autosync_ref, \
2787}
2788
Adrian Knoth0dca1792011-01-26 19:32:14 +01002789static int hdspm_autosync_ref(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002790{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002791 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002792 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002793 unsigned int syncref =
2794 (status >> HDSPM_AES32_syncref_bit) & 0xF;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002795 if (syncref == 0)
2796 return HDSPM_AES32_AUTOSYNC_FROM_WORD;
2797 if (syncref <= 8)
2798 return syncref;
2799 return HDSPM_AES32_AUTOSYNC_FROM_NONE;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002800 } else if (MADI == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002801 /* This looks at the autosync selected sync reference */
2802 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Takashi Iwai763f3562005-06-03 11:25:34 +02002803
Remy Bruno3cee5a62006-10-16 12:46:32 +02002804 switch (status2 & HDSPM_SelSyncRefMask) {
2805 case HDSPM_SelSyncRef_WORD:
2806 return HDSPM_AUTOSYNC_FROM_WORD;
2807 case HDSPM_SelSyncRef_MADI:
2808 return HDSPM_AUTOSYNC_FROM_MADI;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002809 case HDSPM_SelSyncRef_TCO:
2810 return HDSPM_AUTOSYNC_FROM_TCO;
2811 case HDSPM_SelSyncRef_SyncIn:
2812 return HDSPM_AUTOSYNC_FROM_SYNC_IN;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002813 case HDSPM_SelSyncRef_NVALID:
2814 return HDSPM_AUTOSYNC_FROM_NONE;
2815 default:
2816 return 0;
2817 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002818
Takashi Iwai763f3562005-06-03 11:25:34 +02002819 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002820 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002821}
2822
Adrian Knoth0dca1792011-01-26 19:32:14 +01002823
Takashi Iwai98274f02005-11-17 14:52:34 +01002824static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
2825 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002826{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002827 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002828
Adrian Knoth0dca1792011-01-26 19:32:14 +01002829 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002830 static char *texts[] = { "WordClock", "AES1", "AES2", "AES3",
2831 "AES4", "AES5", "AES6", "AES7", "AES8", "None"};
2832
2833 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2834 uinfo->count = 1;
2835 uinfo->value.enumerated.items = 10;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002836 if (uinfo->value.enumerated.item >=
2837 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002838 uinfo->value.enumerated.item =
2839 uinfo->value.enumerated.items - 1;
2840 strcpy(uinfo->value.enumerated.name,
2841 texts[uinfo->value.enumerated.item]);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002842 } else if (MADI == hdspm->io_type) {
2843 static char *texts[] = {"Word Clock", "MADI", "TCO",
2844 "Sync In", "None" };
Remy Bruno3cee5a62006-10-16 12:46:32 +02002845
2846 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2847 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002848 uinfo->value.enumerated.items = 5;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002849 if (uinfo->value.enumerated.item >=
Adrian Knoth0dca1792011-01-26 19:32:14 +01002850 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002851 uinfo->value.enumerated.item =
2852 uinfo->value.enumerated.items - 1;
2853 strcpy(uinfo->value.enumerated.name,
2854 texts[uinfo->value.enumerated.item]);
2855 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002856 return 0;
2857}
2858
Takashi Iwai98274f02005-11-17 14:52:34 +01002859static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
2860 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002861{
Takashi Iwai98274f02005-11-17 14:52:34 +01002862 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002863
Remy Bruno65345992007-08-31 12:21:08 +02002864 ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002865 return 0;
2866}
2867
Adrian Knoth0dca1792011-01-26 19:32:14 +01002868
Takashi Iwai763f3562005-06-03 11:25:34 +02002869#define HDSPM_LINE_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002870{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002871 .name = xname, \
2872 .index = xindex, \
2873 .info = snd_hdspm_info_line_out, \
2874 .get = snd_hdspm_get_line_out, \
2875 .put = snd_hdspm_put_line_out \
2876}
2877
Takashi Iwai98274f02005-11-17 14:52:34 +01002878static int hdspm_line_out(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002879{
2880 return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0;
2881}
2882
2883
Takashi Iwai98274f02005-11-17 14:52:34 +01002884static int hdspm_set_line_output(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002885{
2886 if (out)
2887 hdspm->control_register |= HDSPM_LineOut;
2888 else
2889 hdspm->control_register &= ~HDSPM_LineOut;
2890 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2891
2892 return 0;
2893}
2894
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002895#define snd_hdspm_info_line_out snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002896
Takashi Iwai98274f02005-11-17 14:52:34 +01002897static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol,
2898 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002899{
Takashi Iwai98274f02005-11-17 14:52:34 +01002900 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002901
2902 spin_lock_irq(&hdspm->lock);
2903 ucontrol->value.integer.value[0] = hdspm_line_out(hdspm);
2904 spin_unlock_irq(&hdspm->lock);
2905 return 0;
2906}
2907
Takashi Iwai98274f02005-11-17 14:52:34 +01002908static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
2909 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002910{
Takashi Iwai98274f02005-11-17 14:52:34 +01002911 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002912 int change;
2913 unsigned int val;
2914
2915 if (!snd_hdspm_use_is_exclusive(hdspm))
2916 return -EBUSY;
2917 val = ucontrol->value.integer.value[0] & 1;
2918 spin_lock_irq(&hdspm->lock);
2919 change = (int) val != hdspm_line_out(hdspm);
2920 hdspm_set_line_output(hdspm, val);
2921 spin_unlock_irq(&hdspm->lock);
2922 return change;
2923}
2924
Adrian Knoth0dca1792011-01-26 19:32:14 +01002925
Takashi Iwai763f3562005-06-03 11:25:34 +02002926#define HDSPM_TX_64(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002927{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002928 .name = xname, \
2929 .index = xindex, \
2930 .info = snd_hdspm_info_tx_64, \
2931 .get = snd_hdspm_get_tx_64, \
2932 .put = snd_hdspm_put_tx_64 \
2933}
2934
Takashi Iwai98274f02005-11-17 14:52:34 +01002935static int hdspm_tx_64(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002936{
2937 return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0;
2938}
2939
Takashi Iwai98274f02005-11-17 14:52:34 +01002940static int hdspm_set_tx_64(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002941{
2942 if (out)
2943 hdspm->control_register |= HDSPM_TX_64ch;
2944 else
2945 hdspm->control_register &= ~HDSPM_TX_64ch;
2946 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2947
2948 return 0;
2949}
2950
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002951#define snd_hdspm_info_tx_64 snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002952
Takashi Iwai98274f02005-11-17 14:52:34 +01002953static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol,
2954 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002955{
Takashi Iwai98274f02005-11-17 14:52:34 +01002956 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002957
2958 spin_lock_irq(&hdspm->lock);
2959 ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm);
2960 spin_unlock_irq(&hdspm->lock);
2961 return 0;
2962}
2963
Takashi Iwai98274f02005-11-17 14:52:34 +01002964static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
2965 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002966{
Takashi Iwai98274f02005-11-17 14:52:34 +01002967 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002968 int change;
2969 unsigned int val;
2970
2971 if (!snd_hdspm_use_is_exclusive(hdspm))
2972 return -EBUSY;
2973 val = ucontrol->value.integer.value[0] & 1;
2974 spin_lock_irq(&hdspm->lock);
2975 change = (int) val != hdspm_tx_64(hdspm);
2976 hdspm_set_tx_64(hdspm, val);
2977 spin_unlock_irq(&hdspm->lock);
2978 return change;
2979}
2980
Adrian Knoth0dca1792011-01-26 19:32:14 +01002981
Takashi Iwai763f3562005-06-03 11:25:34 +02002982#define HDSPM_C_TMS(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002983{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002984 .name = xname, \
2985 .index = xindex, \
2986 .info = snd_hdspm_info_c_tms, \
2987 .get = snd_hdspm_get_c_tms, \
2988 .put = snd_hdspm_put_c_tms \
2989}
2990
Takashi Iwai98274f02005-11-17 14:52:34 +01002991static int hdspm_c_tms(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002992{
2993 return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0;
2994}
2995
Takashi Iwai98274f02005-11-17 14:52:34 +01002996static int hdspm_set_c_tms(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002997{
2998 if (out)
2999 hdspm->control_register |= HDSPM_clr_tms;
3000 else
3001 hdspm->control_register &= ~HDSPM_clr_tms;
3002 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3003
3004 return 0;
3005}
3006
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003007#define snd_hdspm_info_c_tms snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02003008
Takashi Iwai98274f02005-11-17 14:52:34 +01003009static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol,
3010 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003011{
Takashi Iwai98274f02005-11-17 14:52:34 +01003012 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003013
3014 spin_lock_irq(&hdspm->lock);
3015 ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm);
3016 spin_unlock_irq(&hdspm->lock);
3017 return 0;
3018}
3019
Takashi Iwai98274f02005-11-17 14:52:34 +01003020static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,
3021 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003022{
Takashi Iwai98274f02005-11-17 14:52:34 +01003023 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003024 int change;
3025 unsigned int val;
3026
3027 if (!snd_hdspm_use_is_exclusive(hdspm))
3028 return -EBUSY;
3029 val = ucontrol->value.integer.value[0] & 1;
3030 spin_lock_irq(&hdspm->lock);
3031 change = (int) val != hdspm_c_tms(hdspm);
3032 hdspm_set_c_tms(hdspm, val);
3033 spin_unlock_irq(&hdspm->lock);
3034 return change;
3035}
3036
Adrian Knoth0dca1792011-01-26 19:32:14 +01003037
Takashi Iwai763f3562005-06-03 11:25:34 +02003038#define HDSPM_SAFE_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003039{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003040 .name = xname, \
3041 .index = xindex, \
3042 .info = snd_hdspm_info_safe_mode, \
3043 .get = snd_hdspm_get_safe_mode, \
3044 .put = snd_hdspm_put_safe_mode \
3045}
3046
Takashi Iwai98274f02005-11-17 14:52:34 +01003047static int hdspm_safe_mode(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003048{
3049 return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0;
3050}
3051
Takashi Iwai98274f02005-11-17 14:52:34 +01003052static int hdspm_set_safe_mode(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02003053{
3054 if (out)
3055 hdspm->control_register |= HDSPM_AutoInp;
3056 else
3057 hdspm->control_register &= ~HDSPM_AutoInp;
3058 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3059
3060 return 0;
3061}
3062
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003063#define snd_hdspm_info_safe_mode snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02003064
Takashi Iwai98274f02005-11-17 14:52:34 +01003065static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol,
3066 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003067{
Takashi Iwai98274f02005-11-17 14:52:34 +01003068 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003069
3070 spin_lock_irq(&hdspm->lock);
3071 ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm);
3072 spin_unlock_irq(&hdspm->lock);
3073 return 0;
3074}
3075
Takashi Iwai98274f02005-11-17 14:52:34 +01003076static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
3077 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003078{
Takashi Iwai98274f02005-11-17 14:52:34 +01003079 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003080 int change;
3081 unsigned int val;
3082
3083 if (!snd_hdspm_use_is_exclusive(hdspm))
3084 return -EBUSY;
3085 val = ucontrol->value.integer.value[0] & 1;
3086 spin_lock_irq(&hdspm->lock);
3087 change = (int) val != hdspm_safe_mode(hdspm);
3088 hdspm_set_safe_mode(hdspm, val);
3089 spin_unlock_irq(&hdspm->lock);
3090 return change;
3091}
3092
Adrian Knoth0dca1792011-01-26 19:32:14 +01003093
Remy Bruno3cee5a62006-10-16 12:46:32 +02003094#define HDSPM_EMPHASIS(xname, xindex) \
3095{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3096 .name = xname, \
3097 .index = xindex, \
3098 .info = snd_hdspm_info_emphasis, \
3099 .get = snd_hdspm_get_emphasis, \
3100 .put = snd_hdspm_put_emphasis \
3101}
3102
3103static int hdspm_emphasis(struct hdspm * hdspm)
3104{
3105 return (hdspm->control_register & HDSPM_Emphasis) ? 1 : 0;
3106}
3107
3108static int hdspm_set_emphasis(struct hdspm * hdspm, int emp)
3109{
3110 if (emp)
3111 hdspm->control_register |= HDSPM_Emphasis;
3112 else
3113 hdspm->control_register &= ~HDSPM_Emphasis;
3114 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3115
3116 return 0;
3117}
3118
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003119#define snd_hdspm_info_emphasis snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02003120
3121static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol,
3122 struct snd_ctl_elem_value *ucontrol)
3123{
3124 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3125
3126 spin_lock_irq(&hdspm->lock);
3127 ucontrol->value.enumerated.item[0] = hdspm_emphasis(hdspm);
3128 spin_unlock_irq(&hdspm->lock);
3129 return 0;
3130}
3131
3132static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
3133 struct snd_ctl_elem_value *ucontrol)
3134{
3135 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3136 int change;
3137 unsigned int val;
3138
3139 if (!snd_hdspm_use_is_exclusive(hdspm))
3140 return -EBUSY;
3141 val = ucontrol->value.integer.value[0] & 1;
3142 spin_lock_irq(&hdspm->lock);
3143 change = (int) val != hdspm_emphasis(hdspm);
3144 hdspm_set_emphasis(hdspm, val);
3145 spin_unlock_irq(&hdspm->lock);
3146 return change;
3147}
3148
Adrian Knoth0dca1792011-01-26 19:32:14 +01003149
Remy Bruno3cee5a62006-10-16 12:46:32 +02003150#define HDSPM_DOLBY(xname, xindex) \
3151{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3152 .name = xname, \
3153 .index = xindex, \
3154 .info = snd_hdspm_info_dolby, \
3155 .get = snd_hdspm_get_dolby, \
3156 .put = snd_hdspm_put_dolby \
3157}
3158
3159static int hdspm_dolby(struct hdspm * hdspm)
3160{
3161 return (hdspm->control_register & HDSPM_Dolby) ? 1 : 0;
3162}
3163
3164static int hdspm_set_dolby(struct hdspm * hdspm, int dol)
3165{
3166 if (dol)
3167 hdspm->control_register |= HDSPM_Dolby;
3168 else
3169 hdspm->control_register &= ~HDSPM_Dolby;
3170 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3171
3172 return 0;
3173}
3174
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003175#define snd_hdspm_info_dolby snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02003176
3177static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol,
3178 struct snd_ctl_elem_value *ucontrol)
3179{
3180 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3181
3182 spin_lock_irq(&hdspm->lock);
3183 ucontrol->value.enumerated.item[0] = hdspm_dolby(hdspm);
3184 spin_unlock_irq(&hdspm->lock);
3185 return 0;
3186}
3187
3188static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
3189 struct snd_ctl_elem_value *ucontrol)
3190{
3191 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3192 int change;
3193 unsigned int val;
3194
3195 if (!snd_hdspm_use_is_exclusive(hdspm))
3196 return -EBUSY;
3197 val = ucontrol->value.integer.value[0] & 1;
3198 spin_lock_irq(&hdspm->lock);
3199 change = (int) val != hdspm_dolby(hdspm);
3200 hdspm_set_dolby(hdspm, val);
3201 spin_unlock_irq(&hdspm->lock);
3202 return change;
3203}
3204
Adrian Knoth0dca1792011-01-26 19:32:14 +01003205
Remy Bruno3cee5a62006-10-16 12:46:32 +02003206#define HDSPM_PROFESSIONAL(xname, xindex) \
3207{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3208 .name = xname, \
3209 .index = xindex, \
3210 .info = snd_hdspm_info_professional, \
3211 .get = snd_hdspm_get_professional, \
3212 .put = snd_hdspm_put_professional \
3213}
3214
3215static int hdspm_professional(struct hdspm * hdspm)
3216{
3217 return (hdspm->control_register & HDSPM_Professional) ? 1 : 0;
3218}
3219
3220static int hdspm_set_professional(struct hdspm * hdspm, int dol)
3221{
3222 if (dol)
3223 hdspm->control_register |= HDSPM_Professional;
3224 else
3225 hdspm->control_register &= ~HDSPM_Professional;
3226 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3227
3228 return 0;
3229}
3230
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003231#define snd_hdspm_info_professional snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02003232
3233static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol,
3234 struct snd_ctl_elem_value *ucontrol)
3235{
3236 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3237
3238 spin_lock_irq(&hdspm->lock);
3239 ucontrol->value.enumerated.item[0] = hdspm_professional(hdspm);
3240 spin_unlock_irq(&hdspm->lock);
3241 return 0;
3242}
3243
3244static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,
3245 struct snd_ctl_elem_value *ucontrol)
3246{
3247 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3248 int change;
3249 unsigned int val;
3250
3251 if (!snd_hdspm_use_is_exclusive(hdspm))
3252 return -EBUSY;
3253 val = ucontrol->value.integer.value[0] & 1;
3254 spin_lock_irq(&hdspm->lock);
3255 change = (int) val != hdspm_professional(hdspm);
3256 hdspm_set_professional(hdspm, val);
3257 spin_unlock_irq(&hdspm->lock);
3258 return change;
3259}
3260
Takashi Iwai763f3562005-06-03 11:25:34 +02003261#define HDSPM_INPUT_SELECT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003262{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003263 .name = xname, \
3264 .index = xindex, \
3265 .info = snd_hdspm_info_input_select, \
3266 .get = snd_hdspm_get_input_select, \
3267 .put = snd_hdspm_put_input_select \
3268}
3269
Takashi Iwai98274f02005-11-17 14:52:34 +01003270static int hdspm_input_select(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003271{
3272 return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
3273}
3274
Takashi Iwai98274f02005-11-17 14:52:34 +01003275static int hdspm_set_input_select(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02003276{
3277 if (out)
3278 hdspm->control_register |= HDSPM_InputSelect0;
3279 else
3280 hdspm->control_register &= ~HDSPM_InputSelect0;
3281 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3282
3283 return 0;
3284}
3285
Takashi Iwai98274f02005-11-17 14:52:34 +01003286static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
3287 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003288{
3289 static char *texts[] = { "optical", "coaxial" };
3290
3291 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3292 uinfo->count = 1;
3293 uinfo->value.enumerated.items = 2;
3294
3295 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3296 uinfo->value.enumerated.item =
3297 uinfo->value.enumerated.items - 1;
3298 strcpy(uinfo->value.enumerated.name,
3299 texts[uinfo->value.enumerated.item]);
3300
3301 return 0;
3302}
3303
Takashi Iwai98274f02005-11-17 14:52:34 +01003304static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
3305 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003306{
Takashi Iwai98274f02005-11-17 14:52:34 +01003307 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003308
3309 spin_lock_irq(&hdspm->lock);
3310 ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
3311 spin_unlock_irq(&hdspm->lock);
3312 return 0;
3313}
3314
Takashi Iwai98274f02005-11-17 14:52:34 +01003315static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
3316 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003317{
Takashi Iwai98274f02005-11-17 14:52:34 +01003318 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003319 int change;
3320 unsigned int val;
3321
3322 if (!snd_hdspm_use_is_exclusive(hdspm))
3323 return -EBUSY;
3324 val = ucontrol->value.integer.value[0] & 1;
3325 spin_lock_irq(&hdspm->lock);
3326 change = (int) val != hdspm_input_select(hdspm);
3327 hdspm_set_input_select(hdspm, val);
3328 spin_unlock_irq(&hdspm->lock);
3329 return change;
3330}
3331
Adrian Knoth0dca1792011-01-26 19:32:14 +01003332
Remy Bruno3cee5a62006-10-16 12:46:32 +02003333#define HDSPM_DS_WIRE(xname, xindex) \
3334{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3335 .name = xname, \
3336 .index = xindex, \
3337 .info = snd_hdspm_info_ds_wire, \
3338 .get = snd_hdspm_get_ds_wire, \
3339 .put = snd_hdspm_put_ds_wire \
3340}
3341
3342static int hdspm_ds_wire(struct hdspm * hdspm)
3343{
3344 return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
3345}
3346
3347static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
3348{
3349 if (ds)
3350 hdspm->control_register |= HDSPM_DS_DoubleWire;
3351 else
3352 hdspm->control_register &= ~HDSPM_DS_DoubleWire;
3353 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3354
3355 return 0;
3356}
3357
3358static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
3359 struct snd_ctl_elem_info *uinfo)
3360{
3361 static char *texts[] = { "Single", "Double" };
3362
3363 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3364 uinfo->count = 1;
3365 uinfo->value.enumerated.items = 2;
3366
3367 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3368 uinfo->value.enumerated.item =
3369 uinfo->value.enumerated.items - 1;
3370 strcpy(uinfo->value.enumerated.name,
3371 texts[uinfo->value.enumerated.item]);
3372
3373 return 0;
3374}
3375
3376static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
3377 struct snd_ctl_elem_value *ucontrol)
3378{
3379 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3380
3381 spin_lock_irq(&hdspm->lock);
3382 ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
3383 spin_unlock_irq(&hdspm->lock);
3384 return 0;
3385}
3386
3387static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
3388 struct snd_ctl_elem_value *ucontrol)
3389{
3390 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3391 int change;
3392 unsigned int val;
3393
3394 if (!snd_hdspm_use_is_exclusive(hdspm))
3395 return -EBUSY;
3396 val = ucontrol->value.integer.value[0] & 1;
3397 spin_lock_irq(&hdspm->lock);
3398 change = (int) val != hdspm_ds_wire(hdspm);
3399 hdspm_set_ds_wire(hdspm, val);
3400 spin_unlock_irq(&hdspm->lock);
3401 return change;
3402}
3403
Adrian Knoth0dca1792011-01-26 19:32:14 +01003404
Remy Bruno3cee5a62006-10-16 12:46:32 +02003405#define HDSPM_QS_WIRE(xname, xindex) \
3406{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3407 .name = xname, \
3408 .index = xindex, \
3409 .info = snd_hdspm_info_qs_wire, \
3410 .get = snd_hdspm_get_qs_wire, \
3411 .put = snd_hdspm_put_qs_wire \
3412}
3413
3414static int hdspm_qs_wire(struct hdspm * hdspm)
3415{
3416 if (hdspm->control_register & HDSPM_QS_DoubleWire)
3417 return 1;
3418 if (hdspm->control_register & HDSPM_QS_QuadWire)
3419 return 2;
3420 return 0;
3421}
3422
3423static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
3424{
3425 hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
3426 switch (mode) {
3427 case 0:
3428 break;
3429 case 1:
3430 hdspm->control_register |= HDSPM_QS_DoubleWire;
3431 break;
3432 case 2:
3433 hdspm->control_register |= HDSPM_QS_QuadWire;
3434 break;
3435 }
3436 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3437
3438 return 0;
3439}
3440
3441static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
3442 struct snd_ctl_elem_info *uinfo)
3443{
3444 static char *texts[] = { "Single", "Double", "Quad" };
3445
3446 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3447 uinfo->count = 1;
3448 uinfo->value.enumerated.items = 3;
3449
3450 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3451 uinfo->value.enumerated.item =
3452 uinfo->value.enumerated.items - 1;
3453 strcpy(uinfo->value.enumerated.name,
3454 texts[uinfo->value.enumerated.item]);
3455
3456 return 0;
3457}
3458
3459static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
3460 struct snd_ctl_elem_value *ucontrol)
3461{
3462 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3463
3464 spin_lock_irq(&hdspm->lock);
3465 ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
3466 spin_unlock_irq(&hdspm->lock);
3467 return 0;
3468}
3469
3470static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
3471 struct snd_ctl_elem_value *ucontrol)
3472{
3473 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3474 int change;
3475 int val;
3476
3477 if (!snd_hdspm_use_is_exclusive(hdspm))
3478 return -EBUSY;
3479 val = ucontrol->value.integer.value[0];
3480 if (val < 0)
3481 val = 0;
3482 if (val > 2)
3483 val = 2;
3484 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003485 change = val != hdspm_qs_wire(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003486 hdspm_set_qs_wire(hdspm, val);
3487 spin_unlock_irq(&hdspm->lock);
3488 return change;
3489}
3490
Adrian Knoth700d1ef2011-07-29 03:11:02 +02003491#define HDSPM_MADI_SPEEDMODE(xname, xindex) \
3492{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3493 .name = xname, \
3494 .index = xindex, \
3495 .info = snd_hdspm_info_madi_speedmode, \
3496 .get = snd_hdspm_get_madi_speedmode, \
3497 .put = snd_hdspm_put_madi_speedmode \
3498}
3499
3500static int hdspm_madi_speedmode(struct hdspm *hdspm)
3501{
3502 if (hdspm->control_register & HDSPM_QuadSpeed)
3503 return 2;
3504 if (hdspm->control_register & HDSPM_DoubleSpeed)
3505 return 1;
3506 return 0;
3507}
3508
3509static int hdspm_set_madi_speedmode(struct hdspm *hdspm, int mode)
3510{
3511 hdspm->control_register &= ~(HDSPM_DoubleSpeed | HDSPM_QuadSpeed);
3512 switch (mode) {
3513 case 0:
3514 break;
3515 case 1:
3516 hdspm->control_register |= HDSPM_DoubleSpeed;
3517 break;
3518 case 2:
3519 hdspm->control_register |= HDSPM_QuadSpeed;
3520 break;
3521 }
3522 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3523
3524 return 0;
3525}
3526
3527static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol,
3528 struct snd_ctl_elem_info *uinfo)
3529{
3530 static char *texts[] = { "Single", "Double", "Quad" };
3531
3532 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3533 uinfo->count = 1;
3534 uinfo->value.enumerated.items = 3;
3535
3536 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3537 uinfo->value.enumerated.item =
3538 uinfo->value.enumerated.items - 1;
3539 strcpy(uinfo->value.enumerated.name,
3540 texts[uinfo->value.enumerated.item]);
3541
3542 return 0;
3543}
3544
3545static int snd_hdspm_get_madi_speedmode(struct snd_kcontrol *kcontrol,
3546 struct snd_ctl_elem_value *ucontrol)
3547{
3548 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3549
3550 spin_lock_irq(&hdspm->lock);
3551 ucontrol->value.enumerated.item[0] = hdspm_madi_speedmode(hdspm);
3552 spin_unlock_irq(&hdspm->lock);
3553 return 0;
3554}
3555
3556static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol,
3557 struct snd_ctl_elem_value *ucontrol)
3558{
3559 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3560 int change;
3561 int val;
3562
3563 if (!snd_hdspm_use_is_exclusive(hdspm))
3564 return -EBUSY;
3565 val = ucontrol->value.integer.value[0];
3566 if (val < 0)
3567 val = 0;
3568 if (val > 2)
3569 val = 2;
3570 spin_lock_irq(&hdspm->lock);
3571 change = val != hdspm_madi_speedmode(hdspm);
3572 hdspm_set_madi_speedmode(hdspm, val);
3573 spin_unlock_irq(&hdspm->lock);
3574 return change;
3575}
Takashi Iwai763f3562005-06-03 11:25:34 +02003576
3577#define HDSPM_MIXER(xname, xindex) \
3578{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
3579 .name = xname, \
3580 .index = xindex, \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003581 .device = 0, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003582 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
3583 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3584 .info = snd_hdspm_info_mixer, \
3585 .get = snd_hdspm_get_mixer, \
3586 .put = snd_hdspm_put_mixer \
3587}
3588
Takashi Iwai98274f02005-11-17 14:52:34 +01003589static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
3590 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003591{
3592 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3593 uinfo->count = 3;
3594 uinfo->value.integer.min = 0;
3595 uinfo->value.integer.max = 65535;
3596 uinfo->value.integer.step = 1;
3597 return 0;
3598}
3599
Takashi Iwai98274f02005-11-17 14:52:34 +01003600static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
3601 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003602{
Takashi Iwai98274f02005-11-17 14:52:34 +01003603 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003604 int source;
3605 int destination;
3606
3607 source = ucontrol->value.integer.value[0];
3608 if (source < 0)
3609 source = 0;
3610 else if (source >= 2 * HDSPM_MAX_CHANNELS)
3611 source = 2 * HDSPM_MAX_CHANNELS - 1;
3612
3613 destination = ucontrol->value.integer.value[1];
3614 if (destination < 0)
3615 destination = 0;
3616 else if (destination >= HDSPM_MAX_CHANNELS)
3617 destination = HDSPM_MAX_CHANNELS - 1;
3618
3619 spin_lock_irq(&hdspm->lock);
3620 if (source >= HDSPM_MAX_CHANNELS)
3621 ucontrol->value.integer.value[2] =
3622 hdspm_read_pb_gain(hdspm, destination,
3623 source - HDSPM_MAX_CHANNELS);
3624 else
3625 ucontrol->value.integer.value[2] =
3626 hdspm_read_in_gain(hdspm, destination, source);
3627
3628 spin_unlock_irq(&hdspm->lock);
3629
3630 return 0;
3631}
3632
Takashi Iwai98274f02005-11-17 14:52:34 +01003633static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
3634 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003635{
Takashi Iwai98274f02005-11-17 14:52:34 +01003636 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003637 int change;
3638 int source;
3639 int destination;
3640 int gain;
3641
3642 if (!snd_hdspm_use_is_exclusive(hdspm))
3643 return -EBUSY;
3644
3645 source = ucontrol->value.integer.value[0];
3646 destination = ucontrol->value.integer.value[1];
3647
3648 if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
3649 return -1;
3650 if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
3651 return -1;
3652
3653 gain = ucontrol->value.integer.value[2];
3654
3655 spin_lock_irq(&hdspm->lock);
3656
3657 if (source >= HDSPM_MAX_CHANNELS)
3658 change = gain != hdspm_read_pb_gain(hdspm, destination,
3659 source -
3660 HDSPM_MAX_CHANNELS);
3661 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003662 change = gain != hdspm_read_in_gain(hdspm, destination,
3663 source);
Takashi Iwai763f3562005-06-03 11:25:34 +02003664
3665 if (change) {
3666 if (source >= HDSPM_MAX_CHANNELS)
3667 hdspm_write_pb_gain(hdspm, destination,
3668 source - HDSPM_MAX_CHANNELS,
3669 gain);
3670 else
3671 hdspm_write_in_gain(hdspm, destination, source,
3672 gain);
3673 }
3674 spin_unlock_irq(&hdspm->lock);
3675
3676 return change;
3677}
3678
3679/* The simple mixer control(s) provide gain control for the
3680 basic 1:1 mappings of playback streams to output
Adrian Knoth0dca1792011-01-26 19:32:14 +01003681 streams.
Takashi Iwai763f3562005-06-03 11:25:34 +02003682*/
3683
3684#define HDSPM_PLAYBACK_MIXER \
3685{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3686 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
3687 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3688 .info = snd_hdspm_info_playback_mixer, \
3689 .get = snd_hdspm_get_playback_mixer, \
3690 .put = snd_hdspm_put_playback_mixer \
3691}
3692
Takashi Iwai98274f02005-11-17 14:52:34 +01003693static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
3694 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003695{
3696 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3697 uinfo->count = 1;
3698 uinfo->value.integer.min = 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003699 uinfo->value.integer.max = 64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003700 uinfo->value.integer.step = 1;
3701 return 0;
3702}
3703
Takashi Iwai98274f02005-11-17 14:52:34 +01003704static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
3705 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003706{
Takashi Iwai98274f02005-11-17 14:52:34 +01003707 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003708 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003709
3710 channel = ucontrol->id.index - 1;
3711
Takashi Iwaida3cec32008-08-08 17:12:14 +02003712 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3713 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003714
Takashi Iwai763f3562005-06-03 11:25:34 +02003715 spin_lock_irq(&hdspm->lock);
3716 ucontrol->value.integer.value[0] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003717 (hdspm_read_pb_gain(hdspm, channel, channel)*64)/UNITY_GAIN;
Takashi Iwai763f3562005-06-03 11:25:34 +02003718 spin_unlock_irq(&hdspm->lock);
3719
Takashi Iwai763f3562005-06-03 11:25:34 +02003720 return 0;
3721}
3722
Takashi Iwai98274f02005-11-17 14:52:34 +01003723static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
3724 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003725{
Takashi Iwai98274f02005-11-17 14:52:34 +01003726 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003727 int change;
3728 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003729 int gain;
3730
3731 if (!snd_hdspm_use_is_exclusive(hdspm))
3732 return -EBUSY;
3733
3734 channel = ucontrol->id.index - 1;
3735
Takashi Iwaida3cec32008-08-08 17:12:14 +02003736 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3737 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003738
Adrian Knoth0dca1792011-01-26 19:32:14 +01003739 gain = ucontrol->value.integer.value[0]*UNITY_GAIN/64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003740
3741 spin_lock_irq(&hdspm->lock);
3742 change =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003743 gain != hdspm_read_pb_gain(hdspm, channel,
3744 channel);
Takashi Iwai763f3562005-06-03 11:25:34 +02003745 if (change)
Adrian Knoth0dca1792011-01-26 19:32:14 +01003746 hdspm_write_pb_gain(hdspm, channel, channel,
Takashi Iwai763f3562005-06-03 11:25:34 +02003747 gain);
3748 spin_unlock_irq(&hdspm->lock);
3749 return change;
3750}
3751
Adrian Knoth0dca1792011-01-26 19:32:14 +01003752#define HDSPM_SYNC_CHECK(xname, xindex) \
3753{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3754 .name = xname, \
3755 .private_value = xindex, \
3756 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3757 .info = snd_hdspm_info_sync_check, \
3758 .get = snd_hdspm_get_sync_check \
Takashi Iwai763f3562005-06-03 11:25:34 +02003759}
3760
Adrian Knoth0dca1792011-01-26 19:32:14 +01003761
Takashi Iwai98274f02005-11-17 14:52:34 +01003762static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
3763 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003764{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003765 static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" };
Takashi Iwai763f3562005-06-03 11:25:34 +02003766 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3767 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003768 uinfo->value.enumerated.items = 4;
Takashi Iwai763f3562005-06-03 11:25:34 +02003769 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3770 uinfo->value.enumerated.item =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003771 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02003772 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01003773 texts[uinfo->value.enumerated.item]);
Takashi Iwai763f3562005-06-03 11:25:34 +02003774 return 0;
3775}
3776
Adrian Knoth0dca1792011-01-26 19:32:14 +01003777static int hdspm_wc_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003778{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003779 int status, status2;
3780
3781 switch (hdspm->io_type) {
3782 case AES32:
3783 status = hdspm_read(hdspm, HDSPM_statusRegister);
3784 if (status & HDSPM_wcSync)
Takashi Iwai763f3562005-06-03 11:25:34 +02003785 return 2;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003786 else if (status & HDSPM_wcLock)
3787 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003788 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003789 break;
3790
3791 case MADI:
3792 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003793 if (status2 & HDSPM_wcLock) {
3794 if (status2 & HDSPM_wcSync)
3795 return 2;
3796 else
3797 return 1;
3798 }
3799 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003800 break;
3801
3802 case RayDAT:
3803 case AIO:
3804 status = hdspm_read(hdspm, HDSPM_statusRegister);
3805
3806 if (status & 0x2000000)
3807 return 2;
3808 else if (status & 0x1000000)
3809 return 1;
3810 return 0;
3811
3812 break;
3813
3814 case MADIface:
3815 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02003816 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003817
Takashi Iwai763f3562005-06-03 11:25:34 +02003818
Adrian Knoth0dca1792011-01-26 19:32:14 +01003819 return 3;
Takashi Iwai763f3562005-06-03 11:25:34 +02003820}
3821
3822
Adrian Knoth0dca1792011-01-26 19:32:14 +01003823static int hdspm_madi_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003824{
3825 int status = hdspm_read(hdspm, HDSPM_statusRegister);
3826 if (status & HDSPM_madiLock) {
3827 if (status & HDSPM_madiSync)
3828 return 2;
3829 else
3830 return 1;
3831 }
3832 return 0;
3833}
3834
Adrian Knoth0dca1792011-01-26 19:32:14 +01003835
3836static int hdspm_s1_sync_check(struct hdspm *hdspm, int idx)
3837{
3838 int status, lock, sync;
3839
3840 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3841
3842 lock = (status & (0x1<<idx)) ? 1 : 0;
3843 sync = (status & (0x100<<idx)) ? 1 : 0;
3844
3845 if (lock && sync)
3846 return 2;
3847 else if (lock)
3848 return 1;
3849 return 0;
3850}
3851
3852
3853static int hdspm_sync_in_sync_check(struct hdspm *hdspm)
3854{
3855 int status, lock = 0, sync = 0;
3856
3857 switch (hdspm->io_type) {
3858 case RayDAT:
3859 case AIO:
3860 status = hdspm_read(hdspm, HDSPM_RD_STATUS_3);
3861 lock = (status & 0x400) ? 1 : 0;
3862 sync = (status & 0x800) ? 1 : 0;
3863 break;
3864
3865 case MADI:
3866 case AES32:
3867 status = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knotha7edbd52011-02-23 11:43:15 +01003868 lock = (status & HDSPM_syncInLock) ? 1 : 0;
3869 sync = (status & HDSPM_syncInSync) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003870 break;
3871
3872 case MADIface:
3873 break;
3874 }
3875
3876 if (lock && sync)
3877 return 2;
3878 else if (lock)
3879 return 1;
3880
3881 return 0;
3882}
3883
3884static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx)
3885{
3886 int status2, lock, sync;
3887 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
3888
3889 lock = (status2 & (0x0080 >> idx)) ? 1 : 0;
3890 sync = (status2 & (0x8000 >> idx)) ? 1 : 0;
3891
3892 if (sync)
3893 return 2;
3894 else if (lock)
3895 return 1;
3896 return 0;
3897}
3898
3899
3900static int hdspm_tco_sync_check(struct hdspm *hdspm)
3901{
3902 int status;
3903
3904 if (hdspm->tco) {
3905 switch (hdspm->io_type) {
3906 case MADI:
3907 case AES32:
3908 status = hdspm_read(hdspm, HDSPM_statusRegister);
3909 if (status & HDSPM_tcoLock) {
3910 if (status & HDSPM_tcoSync)
3911 return 2;
3912 else
3913 return 1;
3914 }
3915 return 0;
3916
3917 break;
3918
3919 case RayDAT:
3920 case AIO:
3921 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3922
3923 if (status & 0x8000000)
3924 return 2; /* Sync */
3925 if (status & 0x4000000)
3926 return 1; /* Lock */
3927 return 0; /* No signal */
3928 break;
3929
3930 default:
3931 break;
3932 }
3933 }
3934
3935 return 3; /* N/A */
3936}
3937
3938
3939static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
3940 struct snd_ctl_elem_value *ucontrol)
3941{
3942 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3943 int val = -1;
3944
3945 switch (hdspm->io_type) {
3946 case RayDAT:
3947 switch (kcontrol->private_value) {
3948 case 0: /* WC */
3949 val = hdspm_wc_sync_check(hdspm); break;
3950 case 7: /* TCO */
3951 val = hdspm_tco_sync_check(hdspm); break;
3952 case 8: /* SYNC IN */
3953 val = hdspm_sync_in_sync_check(hdspm); break;
3954 default:
3955 val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
3956 }
3957
3958 case AIO:
3959 switch (kcontrol->private_value) {
3960 case 0: /* WC */
3961 val = hdspm_wc_sync_check(hdspm); break;
3962 case 4: /* TCO */
3963 val = hdspm_tco_sync_check(hdspm); break;
3964 case 5: /* SYNC IN */
3965 val = hdspm_sync_in_sync_check(hdspm); break;
3966 default:
3967 val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
3968 }
3969
3970 case MADI:
3971 switch (kcontrol->private_value) {
3972 case 0: /* WC */
3973 val = hdspm_wc_sync_check(hdspm); break;
3974 case 1: /* MADI */
3975 val = hdspm_madi_sync_check(hdspm); break;
3976 case 2: /* TCO */
3977 val = hdspm_tco_sync_check(hdspm); break;
3978 case 3: /* SYNC_IN */
3979 val = hdspm_sync_in_sync_check(hdspm); break;
3980 }
3981
3982 case MADIface:
3983 val = hdspm_madi_sync_check(hdspm); /* MADI */
3984 break;
3985
3986 case AES32:
3987 switch (kcontrol->private_value) {
3988 case 0: /* WC */
3989 val = hdspm_wc_sync_check(hdspm); break;
3990 case 9: /* TCO */
3991 val = hdspm_tco_sync_check(hdspm); break;
3992 case 10 /* SYNC IN */:
3993 val = hdspm_sync_in_sync_check(hdspm); break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01003994 default: /* AES1 to AES8 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01003995 val = hdspm_aes_sync_check(hdspm,
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01003996 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003997 }
3998
3999 }
4000
4001 if (-1 == val)
4002 val = 3;
4003
4004 ucontrol->value.enumerated.item[0] = val;
4005 return 0;
4006}
4007
4008
4009
4010/**
4011 * TCO controls
4012 **/
4013static void hdspm_tco_write(struct hdspm *hdspm)
4014{
4015 unsigned int tc[4] = { 0, 0, 0, 0};
4016
4017 switch (hdspm->tco->input) {
4018 case 0:
4019 tc[2] |= HDSPM_TCO2_set_input_MSB;
4020 break;
4021 case 1:
4022 tc[2] |= HDSPM_TCO2_set_input_LSB;
4023 break;
4024 default:
4025 break;
4026 }
4027
4028 switch (hdspm->tco->framerate) {
4029 case 1:
4030 tc[1] |= HDSPM_TCO1_LTC_Format_LSB;
4031 break;
4032 case 2:
4033 tc[1] |= HDSPM_TCO1_LTC_Format_MSB;
4034 break;
4035 case 3:
4036 tc[1] |= HDSPM_TCO1_LTC_Format_MSB +
4037 HDSPM_TCO1_set_drop_frame_flag;
4038 break;
4039 case 4:
4040 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
4041 HDSPM_TCO1_LTC_Format_MSB;
4042 break;
4043 case 5:
4044 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
4045 HDSPM_TCO1_LTC_Format_MSB +
4046 HDSPM_TCO1_set_drop_frame_flag;
4047 break;
4048 default:
4049 break;
4050 }
4051
4052 switch (hdspm->tco->wordclock) {
4053 case 1:
4054 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_LSB;
4055 break;
4056 case 2:
4057 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_MSB;
4058 break;
4059 default:
4060 break;
4061 }
4062
4063 switch (hdspm->tco->samplerate) {
4064 case 1:
4065 tc[2] |= HDSPM_TCO2_set_freq;
4066 break;
4067 case 2:
4068 tc[2] |= HDSPM_TCO2_set_freq_from_app;
4069 break;
4070 default:
4071 break;
4072 }
4073
4074 switch (hdspm->tco->pull) {
4075 case 1:
4076 tc[2] |= HDSPM_TCO2_set_pull_up;
4077 break;
4078 case 2:
4079 tc[2] |= HDSPM_TCO2_set_pull_down;
4080 break;
4081 case 3:
4082 tc[2] |= HDSPM_TCO2_set_pull_up + HDSPM_TCO2_set_01_4;
4083 break;
4084 case 4:
4085 tc[2] |= HDSPM_TCO2_set_pull_down + HDSPM_TCO2_set_01_4;
4086 break;
4087 default:
4088 break;
4089 }
4090
4091 if (1 == hdspm->tco->term) {
4092 tc[2] |= HDSPM_TCO2_set_term_75R;
4093 }
4094
4095 hdspm_write(hdspm, HDSPM_WR_TCO, tc[0]);
4096 hdspm_write(hdspm, HDSPM_WR_TCO+4, tc[1]);
4097 hdspm_write(hdspm, HDSPM_WR_TCO+8, tc[2]);
4098 hdspm_write(hdspm, HDSPM_WR_TCO+12, tc[3]);
4099}
4100
4101
4102#define HDSPM_TCO_SAMPLE_RATE(xname, xindex) \
4103{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4104 .name = xname, \
4105 .index = xindex, \
4106 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4107 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4108 .info = snd_hdspm_info_tco_sample_rate, \
4109 .get = snd_hdspm_get_tco_sample_rate, \
4110 .put = snd_hdspm_put_tco_sample_rate \
4111}
4112
4113static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol,
4114 struct snd_ctl_elem_info *uinfo)
4115{
4116 static char *texts[] = { "44.1 kHz", "48 kHz" };
4117 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4118 uinfo->count = 1;
4119 uinfo->value.enumerated.items = 2;
4120
4121 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4122 uinfo->value.enumerated.item =
4123 uinfo->value.enumerated.items - 1;
4124
4125 strcpy(uinfo->value.enumerated.name,
4126 texts[uinfo->value.enumerated.item]);
4127
4128 return 0;
4129}
4130
4131static int snd_hdspm_get_tco_sample_rate(struct snd_kcontrol *kcontrol,
4132 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02004133{
Takashi Iwai98274f02005-11-17 14:52:34 +01004134 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02004135
Adrian Knoth0dca1792011-01-26 19:32:14 +01004136 ucontrol->value.enumerated.item[0] = hdspm->tco->samplerate;
4137
Takashi Iwai763f3562005-06-03 11:25:34 +02004138 return 0;
4139}
4140
Adrian Knoth0dca1792011-01-26 19:32:14 +01004141static int snd_hdspm_put_tco_sample_rate(struct snd_kcontrol *kcontrol,
4142 struct snd_ctl_elem_value *ucontrol)
Remy Bruno3cee5a62006-10-16 12:46:32 +02004143{
Adrian Knoth0dca1792011-01-26 19:32:14 +01004144 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4145
4146 if (hdspm->tco->samplerate != ucontrol->value.enumerated.item[0]) {
4147 hdspm->tco->samplerate = ucontrol->value.enumerated.item[0];
4148
4149 hdspm_tco_write(hdspm);
4150
4151 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004152 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01004153
Remy Bruno3cee5a62006-10-16 12:46:32 +02004154 return 0;
4155}
4156
Adrian Knoth0dca1792011-01-26 19:32:14 +01004157
4158#define HDSPM_TCO_PULL(xname, xindex) \
4159{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4160 .name = xname, \
4161 .index = xindex, \
4162 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4163 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4164 .info = snd_hdspm_info_tco_pull, \
4165 .get = snd_hdspm_get_tco_pull, \
4166 .put = snd_hdspm_put_tco_pull \
4167}
4168
4169static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol,
4170 struct snd_ctl_elem_info *uinfo)
4171{
4172 static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" };
4173 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4174 uinfo->count = 1;
4175 uinfo->value.enumerated.items = 5;
4176
4177 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4178 uinfo->value.enumerated.item =
4179 uinfo->value.enumerated.items - 1;
4180
4181 strcpy(uinfo->value.enumerated.name,
4182 texts[uinfo->value.enumerated.item]);
4183
4184 return 0;
4185}
4186
4187static int snd_hdspm_get_tco_pull(struct snd_kcontrol *kcontrol,
4188 struct snd_ctl_elem_value *ucontrol)
4189{
4190 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4191
4192 ucontrol->value.enumerated.item[0] = hdspm->tco->pull;
4193
4194 return 0;
4195}
4196
4197static int snd_hdspm_put_tco_pull(struct snd_kcontrol *kcontrol,
4198 struct snd_ctl_elem_value *ucontrol)
4199{
4200 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4201
4202 if (hdspm->tco->pull != ucontrol->value.enumerated.item[0]) {
4203 hdspm->tco->pull = ucontrol->value.enumerated.item[0];
4204
4205 hdspm_tco_write(hdspm);
4206
4207 return 1;
4208 }
4209
4210 return 0;
4211}
4212
4213#define HDSPM_TCO_WCK_CONVERSION(xname, xindex) \
4214{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4215 .name = xname, \
4216 .index = xindex, \
4217 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4218 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4219 .info = snd_hdspm_info_tco_wck_conversion, \
4220 .get = snd_hdspm_get_tco_wck_conversion, \
4221 .put = snd_hdspm_put_tco_wck_conversion \
4222}
4223
4224static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4225 struct snd_ctl_elem_info *uinfo)
4226{
4227 static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
4228 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4229 uinfo->count = 1;
4230 uinfo->value.enumerated.items = 3;
4231
4232 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4233 uinfo->value.enumerated.item =
4234 uinfo->value.enumerated.items - 1;
4235
4236 strcpy(uinfo->value.enumerated.name,
4237 texts[uinfo->value.enumerated.item]);
4238
4239 return 0;
4240}
4241
4242static int snd_hdspm_get_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4243 struct snd_ctl_elem_value *ucontrol)
4244{
4245 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4246
4247 ucontrol->value.enumerated.item[0] = hdspm->tco->wordclock;
4248
4249 return 0;
4250}
4251
4252static int snd_hdspm_put_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4253 struct snd_ctl_elem_value *ucontrol)
4254{
4255 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4256
4257 if (hdspm->tco->wordclock != ucontrol->value.enumerated.item[0]) {
4258 hdspm->tco->wordclock = ucontrol->value.enumerated.item[0];
4259
4260 hdspm_tco_write(hdspm);
4261
4262 return 1;
4263 }
4264
4265 return 0;
4266}
4267
4268
4269#define HDSPM_TCO_FRAME_RATE(xname, xindex) \
4270{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4271 .name = xname, \
4272 .index = xindex, \
4273 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4274 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4275 .info = snd_hdspm_info_tco_frame_rate, \
4276 .get = snd_hdspm_get_tco_frame_rate, \
4277 .put = snd_hdspm_put_tco_frame_rate \
4278}
4279
4280static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol,
4281 struct snd_ctl_elem_info *uinfo)
4282{
4283 static char *texts[] = { "24 fps", "25 fps", "29.97fps",
4284 "29.97 dfps", "30 fps", "30 dfps" };
4285 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4286 uinfo->count = 1;
4287 uinfo->value.enumerated.items = 6;
4288
4289 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4290 uinfo->value.enumerated.item =
4291 uinfo->value.enumerated.items - 1;
4292
4293 strcpy(uinfo->value.enumerated.name,
4294 texts[uinfo->value.enumerated.item]);
4295
4296 return 0;
4297}
4298
4299static int snd_hdspm_get_tco_frame_rate(struct snd_kcontrol *kcontrol,
Remy Bruno3cee5a62006-10-16 12:46:32 +02004300 struct snd_ctl_elem_value *ucontrol)
4301{
Remy Bruno3cee5a62006-10-16 12:46:32 +02004302 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4303
Adrian Knoth0dca1792011-01-26 19:32:14 +01004304 ucontrol->value.enumerated.item[0] = hdspm->tco->framerate;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004305
Remy Bruno3cee5a62006-10-16 12:46:32 +02004306 return 0;
4307}
Takashi Iwai763f3562005-06-03 11:25:34 +02004308
Adrian Knoth0dca1792011-01-26 19:32:14 +01004309static int snd_hdspm_put_tco_frame_rate(struct snd_kcontrol *kcontrol,
4310 struct snd_ctl_elem_value *ucontrol)
4311{
4312 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4313
4314 if (hdspm->tco->framerate != ucontrol->value.enumerated.item[0]) {
4315 hdspm->tco->framerate = ucontrol->value.enumerated.item[0];
4316
4317 hdspm_tco_write(hdspm);
4318
4319 return 1;
4320 }
4321
4322 return 0;
4323}
4324
4325
4326#define HDSPM_TCO_SYNC_SOURCE(xname, xindex) \
4327{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4328 .name = xname, \
4329 .index = xindex, \
4330 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4331 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4332 .info = snd_hdspm_info_tco_sync_source, \
4333 .get = snd_hdspm_get_tco_sync_source, \
4334 .put = snd_hdspm_put_tco_sync_source \
4335}
4336
4337static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol,
4338 struct snd_ctl_elem_info *uinfo)
4339{
4340 static char *texts[] = { "LTC", "Video", "WCK" };
4341 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4342 uinfo->count = 1;
4343 uinfo->value.enumerated.items = 3;
4344
4345 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4346 uinfo->value.enumerated.item =
4347 uinfo->value.enumerated.items - 1;
4348
4349 strcpy(uinfo->value.enumerated.name,
4350 texts[uinfo->value.enumerated.item]);
4351
4352 return 0;
4353}
4354
4355static int snd_hdspm_get_tco_sync_source(struct snd_kcontrol *kcontrol,
4356 struct snd_ctl_elem_value *ucontrol)
4357{
4358 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4359
4360 ucontrol->value.enumerated.item[0] = hdspm->tco->input;
4361
4362 return 0;
4363}
4364
4365static int snd_hdspm_put_tco_sync_source(struct snd_kcontrol *kcontrol,
4366 struct snd_ctl_elem_value *ucontrol)
4367{
4368 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4369
4370 if (hdspm->tco->input != ucontrol->value.enumerated.item[0]) {
4371 hdspm->tco->input = ucontrol->value.enumerated.item[0];
4372
4373 hdspm_tco_write(hdspm);
4374
4375 return 1;
4376 }
4377
4378 return 0;
4379}
4380
4381
4382#define HDSPM_TCO_WORD_TERM(xname, xindex) \
4383{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4384 .name = xname, \
4385 .index = xindex, \
4386 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4387 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4388 .info = snd_hdspm_info_tco_word_term, \
4389 .get = snd_hdspm_get_tco_word_term, \
4390 .put = snd_hdspm_put_tco_word_term \
4391}
4392
4393static int snd_hdspm_info_tco_word_term(struct snd_kcontrol *kcontrol,
4394 struct snd_ctl_elem_info *uinfo)
4395{
4396 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
4397 uinfo->count = 1;
4398 uinfo->value.integer.min = 0;
4399 uinfo->value.integer.max = 1;
4400
4401 return 0;
4402}
4403
4404
4405static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol,
4406 struct snd_ctl_elem_value *ucontrol)
4407{
4408 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4409
4410 ucontrol->value.enumerated.item[0] = hdspm->tco->term;
4411
4412 return 0;
4413}
4414
4415
4416static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol,
4417 struct snd_ctl_elem_value *ucontrol)
4418{
4419 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4420
4421 if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) {
4422 hdspm->tco->term = ucontrol->value.enumerated.item[0];
4423
4424 hdspm_tco_write(hdspm);
4425
4426 return 1;
4427 }
4428
4429 return 0;
4430}
4431
4432
4433
Takashi Iwai763f3562005-06-03 11:25:34 +02004434
Remy Bruno3cee5a62006-10-16 12:46:32 +02004435static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004436 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004437 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Takashi Iwai763f3562005-06-03 11:25:34 +02004438 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4439 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4440 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4441 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004442 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4443 HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
4444 HDSPM_SYNC_CHECK("TCO SyncCHeck", 2),
4445 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
Takashi Iwai763f3562005-06-03 11:25:34 +02004446 HDSPM_LINE_OUT("Line Out", 0),
4447 HDSPM_TX_64("TX 64 channels mode", 0),
4448 HDSPM_C_TMS("Clear Track Marker", 0),
4449 HDSPM_SAFE_MODE("Safe Mode", 0),
Adrian Knoth700d1ef2011-07-29 03:11:02 +02004450 HDSPM_INPUT_SELECT("Input Select", 0),
4451 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004452};
4453
4454
4455static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
4456 HDSPM_MIXER("Mixer", 0),
4457 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4458 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4459 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4460 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4461 HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
4462 HDSPM_TX_64("TX 64 channels mode", 0),
4463 HDSPM_C_TMS("Clear Track Marker", 0),
Adrian Knoth700d1ef2011-07-29 03:11:02 +02004464 HDSPM_SAFE_MODE("Safe Mode", 0),
4465 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004466};
4467
Adrian Knoth0dca1792011-01-26 19:32:14 +01004468static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004469 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004470 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004471 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4472 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4473 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4474 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004475 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004476 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4477 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4478 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4479 HDSPM_SYNC_CHECK("ADAT SyncCheck", 3),
4480 HDSPM_SYNC_CHECK("TCO SyncCheck", 4),
4481 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 5),
4482 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4483 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4484 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4485 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT Frequency", 3),
4486 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 4),
4487 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5)
4488
4489 /*
4490 HDSPM_INPUT_SELECT("Input Select", 0),
4491 HDSPM_SPDIF_OPTICAL("SPDIF Out Optical", 0),
4492 HDSPM_PROFESSIONAL("SPDIF Out Professional", 0);
4493 HDSPM_SPDIF_IN("SPDIF In", 0);
4494 HDSPM_BREAKOUT_CABLE("Breakout Cable", 0);
4495 HDSPM_INPUT_LEVEL("Input Level", 0);
4496 HDSPM_OUTPUT_LEVEL("Output Level", 0);
4497 HDSPM_PHONES("Phones", 0);
4498 */
4499};
4500
4501static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = {
4502 HDSPM_MIXER("Mixer", 0),
4503 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4504 HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0),
4505 HDSPM_PREF_SYNC_REF("Pref Sync Ref", 0),
4506 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4507 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4508 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4509 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4510 HDSPM_SYNC_CHECK("ADAT1 SyncCheck", 3),
4511 HDSPM_SYNC_CHECK("ADAT2 SyncCheck", 4),
4512 HDSPM_SYNC_CHECK("ADAT3 SyncCheck", 5),
4513 HDSPM_SYNC_CHECK("ADAT4 SyncCheck", 6),
4514 HDSPM_SYNC_CHECK("TCO SyncCheck", 7),
4515 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 8),
4516 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4517 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4518 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4519 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT1 Frequency", 3),
4520 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT2 Frequency", 4),
4521 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT3 Frequency", 5),
4522 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT4 Frequency", 6),
4523 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 7),
4524 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8)
4525};
4526
4527static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
4528 HDSPM_MIXER("Mixer", 0),
4529 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4530 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4531 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4532 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4533 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4534 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4535 HDSPM_SYNC_CHECK("WC Sync Check", 0),
4536 HDSPM_SYNC_CHECK("AES1 Sync Check", 1),
4537 HDSPM_SYNC_CHECK("AES2 Sync Check", 2),
4538 HDSPM_SYNC_CHECK("AES3 Sync Check", 3),
4539 HDSPM_SYNC_CHECK("AES4 Sync Check", 4),
4540 HDSPM_SYNC_CHECK("AES5 Sync Check", 5),
4541 HDSPM_SYNC_CHECK("AES6 Sync Check", 6),
4542 HDSPM_SYNC_CHECK("AES7 Sync Check", 7),
4543 HDSPM_SYNC_CHECK("AES8 Sync Check", 8),
4544 HDSPM_SYNC_CHECK("TCO Sync Check", 9),
4545 HDSPM_SYNC_CHECK("SYNC IN Sync Check", 10),
4546 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4547 HDSPM_AUTOSYNC_SAMPLE_RATE("AES1 Frequency", 1),
4548 HDSPM_AUTOSYNC_SAMPLE_RATE("AES2 Frequency", 2),
4549 HDSPM_AUTOSYNC_SAMPLE_RATE("AES3 Frequency", 3),
4550 HDSPM_AUTOSYNC_SAMPLE_RATE("AES4 Frequency", 4),
4551 HDSPM_AUTOSYNC_SAMPLE_RATE("AES5 Frequency", 5),
4552 HDSPM_AUTOSYNC_SAMPLE_RATE("AES6 Frequency", 6),
4553 HDSPM_AUTOSYNC_SAMPLE_RATE("AES7 Frequency", 7),
4554 HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8),
4555 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9),
4556 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004557 HDSPM_LINE_OUT("Line Out", 0),
4558 HDSPM_EMPHASIS("Emphasis", 0),
4559 HDSPM_DOLBY("Non Audio", 0),
4560 HDSPM_PROFESSIONAL("Professional", 0),
4561 HDSPM_C_TMS("Clear Track Marker", 0),
4562 HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
4563 HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
4564};
4565
Adrian Knoth0dca1792011-01-26 19:32:14 +01004566
4567
4568/* Control elements for the optional TCO module */
4569static struct snd_kcontrol_new snd_hdspm_controls_tco[] = {
4570 HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0),
4571 HDSPM_TCO_PULL("TCO Pull", 0),
4572 HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0),
4573 HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0),
4574 HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0),
4575 HDSPM_TCO_WORD_TERM("TCO Word Term", 0)
4576};
4577
4578
Takashi Iwai98274f02005-11-17 14:52:34 +01004579static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
Takashi Iwai763f3562005-06-03 11:25:34 +02004580
4581
Takashi Iwai98274f02005-11-17 14:52:34 +01004582static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004583{
4584 int i;
4585
Adrian Knoth0dca1792011-01-26 19:32:14 +01004586 for (i = hdspm->ds_out_channels; i < hdspm->ss_out_channels; ++i) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004587 if (hdspm->system_sample_rate > 48000) {
4588 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004589 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
4590 SNDRV_CTL_ELEM_ACCESS_READ |
4591 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004592 } else {
4593 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004594 SNDRV_CTL_ELEM_ACCESS_READWRITE |
4595 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004596 }
4597 snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
Adrian Knoth0dca1792011-01-26 19:32:14 +01004598 SNDRV_CTL_EVENT_MASK_INFO,
4599 &hdspm->playback_mixer_ctls[i]->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02004600 }
4601
4602 return 0;
4603}
4604
4605
Adrian Knoth0dca1792011-01-26 19:32:14 +01004606static int snd_hdspm_create_controls(struct snd_card *card,
4607 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004608{
4609 unsigned int idx, limit;
4610 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01004611 struct snd_kcontrol *kctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004612 struct snd_kcontrol_new *list = NULL;
Takashi Iwai763f3562005-06-03 11:25:34 +02004613
Adrian Knoth0dca1792011-01-26 19:32:14 +01004614 switch (hdspm->io_type) {
4615 case MADI:
4616 list = snd_hdspm_controls_madi;
4617 limit = ARRAY_SIZE(snd_hdspm_controls_madi);
4618 break;
4619 case MADIface:
4620 list = snd_hdspm_controls_madiface;
4621 limit = ARRAY_SIZE(snd_hdspm_controls_madiface);
4622 break;
4623 case AIO:
4624 list = snd_hdspm_controls_aio;
4625 limit = ARRAY_SIZE(snd_hdspm_controls_aio);
4626 break;
4627 case RayDAT:
4628 list = snd_hdspm_controls_raydat;
4629 limit = ARRAY_SIZE(snd_hdspm_controls_raydat);
4630 break;
4631 case AES32:
4632 list = snd_hdspm_controls_aes32;
4633 limit = ARRAY_SIZE(snd_hdspm_controls_aes32);
4634 break;
4635 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004636
Adrian Knoth0dca1792011-01-26 19:32:14 +01004637 if (NULL != list) {
4638 for (idx = 0; idx < limit; idx++) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004639 err = snd_ctl_add(card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004640 snd_ctl_new1(&list[idx], hdspm));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004641 if (err < 0)
4642 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004643 }
4644 }
4645
Takashi Iwai763f3562005-06-03 11:25:34 +02004646
Adrian Knoth0dca1792011-01-26 19:32:14 +01004647 /* create simple 1:1 playback mixer controls */
Takashi Iwai763f3562005-06-03 11:25:34 +02004648 snd_hdspm_playback_mixer.name = "Chn";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004649 if (hdspm->system_sample_rate >= 128000) {
4650 limit = hdspm->qs_out_channels;
4651 } else if (hdspm->system_sample_rate >= 64000) {
4652 limit = hdspm->ds_out_channels;
4653 } else {
4654 limit = hdspm->ss_out_channels;
4655 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004656 for (idx = 0; idx < limit; ++idx) {
4657 snd_hdspm_playback_mixer.index = idx + 1;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004658 kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm);
4659 err = snd_ctl_add(card, kctl);
4660 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004661 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004662 hdspm->playback_mixer_ctls[idx] = kctl;
4663 }
4664
Adrian Knoth0dca1792011-01-26 19:32:14 +01004665
4666 if (hdspm->tco) {
4667 /* add tco control elements */
4668 list = snd_hdspm_controls_tco;
4669 limit = ARRAY_SIZE(snd_hdspm_controls_tco);
4670 for (idx = 0; idx < limit; idx++) {
4671 err = snd_ctl_add(card,
4672 snd_ctl_new1(&list[idx], hdspm));
4673 if (err < 0)
4674 return err;
4675 }
4676 }
4677
Takashi Iwai763f3562005-06-03 11:25:34 +02004678 return 0;
4679}
4680
4681/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01004682 /proc interface
Takashi Iwai763f3562005-06-03 11:25:34 +02004683 ------------------------------------------------------------*/
4684
4685static void
Remy Bruno3cee5a62006-10-16 12:46:32 +02004686snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
4687 struct snd_info_buffer *buffer)
Takashi Iwai763f3562005-06-03 11:25:34 +02004688{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004689 struct hdspm *hdspm = entry->private_data;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004690 unsigned int status, status2, control, freq;
4691
Takashi Iwai763f3562005-06-03 11:25:34 +02004692 char *pref_sync_ref;
4693 char *autosync_ref;
4694 char *system_clock_mode;
Takashi Iwai763f3562005-06-03 11:25:34 +02004695 char *insel;
Takashi Iwai763f3562005-06-03 11:25:34 +02004696 int x, x2;
4697
Adrian Knoth0dca1792011-01-26 19:32:14 +01004698 /* TCO stuff */
4699 int a, ltc, frames, seconds, minutes, hours;
4700 unsigned int period;
4701 u64 freq_const = 0;
4702 u32 rate;
4703
Takashi Iwai763f3562005-06-03 11:25:34 +02004704 status = hdspm_read(hdspm, HDSPM_statusRegister);
4705 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004706 control = hdspm->control_register;
4707 freq = hdspm_read(hdspm, HDSPM_timecodeRegister);
Takashi Iwai763f3562005-06-03 11:25:34 +02004708
4709 snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004710 hdspm->card_name, hdspm->card->number + 1,
4711 hdspm->firmware_rev,
4712 (status2 & HDSPM_version0) |
4713 (status2 & HDSPM_version1) | (status2 &
4714 HDSPM_version2));
4715
4716 snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n",
4717 (hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF,
Adrian Knoth7d53a632012-01-04 14:31:16 +01004718 hdspm->serial);
Takashi Iwai763f3562005-06-03 11:25:34 +02004719
4720 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004721 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
Takashi Iwai763f3562005-06-03 11:25:34 +02004722
4723 snd_iprintf(buffer, "--- System ---\n");
4724
4725 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004726 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4727 status & HDSPM_audioIRQPending,
4728 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4729 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4730 hdspm->irq_count);
Takashi Iwai763f3562005-06-03 11:25:34 +02004731 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004732 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4733 "estimated= %ld (bytes)\n",
4734 ((status & HDSPM_BufferID) ? 1 : 0),
4735 (status & HDSPM_BufferPositionMask),
4736 (status & HDSPM_BufferPositionMask) %
4737 (2 * (int)hdspm->period_bytes),
4738 ((status & HDSPM_BufferPositionMask) - 64) %
4739 (2 * (int)hdspm->period_bytes),
4740 (long) hdspm_hw_pointer(hdspm) * 4);
Takashi Iwai763f3562005-06-03 11:25:34 +02004741
4742 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004743 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4744 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4745 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4746 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4747 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
Takashi Iwai763f3562005-06-03 11:25:34 +02004748 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004749 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4750 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4751 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4752 snd_iprintf(buffer,
4753 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4754 "status2=0x%x\n",
4755 hdspm->control_register, hdspm->control2_register,
4756 status, status2);
4757 if (status & HDSPM_tco_detect) {
4758 snd_iprintf(buffer, "TCO module detected.\n");
4759 a = hdspm_read(hdspm, HDSPM_RD_TCO+4);
4760 if (a & HDSPM_TCO1_LTC_Input_valid) {
4761 snd_iprintf(buffer, " LTC valid, ");
4762 switch (a & (HDSPM_TCO1_LTC_Format_LSB |
4763 HDSPM_TCO1_LTC_Format_MSB)) {
4764 case 0:
4765 snd_iprintf(buffer, "24 fps, ");
4766 break;
4767 case HDSPM_TCO1_LTC_Format_LSB:
4768 snd_iprintf(buffer, "25 fps, ");
4769 break;
4770 case HDSPM_TCO1_LTC_Format_MSB:
4771 snd_iprintf(buffer, "29.97 fps, ");
4772 break;
4773 default:
4774 snd_iprintf(buffer, "30 fps, ");
4775 break;
4776 }
4777 if (a & HDSPM_TCO1_set_drop_frame_flag) {
4778 snd_iprintf(buffer, "drop frame\n");
4779 } else {
4780 snd_iprintf(buffer, "full frame\n");
4781 }
4782 } else {
4783 snd_iprintf(buffer, " no LTC\n");
4784 }
4785 if (a & HDSPM_TCO1_Video_Input_Format_NTSC) {
4786 snd_iprintf(buffer, " Video: NTSC\n");
4787 } else if (a & HDSPM_TCO1_Video_Input_Format_PAL) {
4788 snd_iprintf(buffer, " Video: PAL\n");
4789 } else {
4790 snd_iprintf(buffer, " No video\n");
4791 }
4792 if (a & HDSPM_TCO1_TCO_lock) {
4793 snd_iprintf(buffer, " Sync: lock\n");
4794 } else {
4795 snd_iprintf(buffer, " Sync: no lock\n");
4796 }
4797
4798 switch (hdspm->io_type) {
4799 case MADI:
4800 case AES32:
4801 freq_const = 110069313433624ULL;
4802 break;
4803 case RayDAT:
4804 case AIO:
4805 freq_const = 104857600000000ULL;
4806 break;
4807 case MADIface:
4808 break; /* no TCO possible */
4809 }
4810
4811 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
4812 snd_iprintf(buffer, " period: %u\n", period);
4813
4814
4815 /* rate = freq_const/period; */
4816 rate = div_u64(freq_const, period);
4817
4818 if (control & HDSPM_QuadSpeed) {
4819 rate *= 4;
4820 } else if (control & HDSPM_DoubleSpeed) {
4821 rate *= 2;
4822 }
4823
4824 snd_iprintf(buffer, " Frequency: %u Hz\n",
4825 (unsigned int) rate);
4826
4827 ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
4828 frames = ltc & 0xF;
4829 ltc >>= 4;
4830 frames += (ltc & 0x3) * 10;
4831 ltc >>= 4;
4832 seconds = ltc & 0xF;
4833 ltc >>= 4;
4834 seconds += (ltc & 0x7) * 10;
4835 ltc >>= 4;
4836 minutes = ltc & 0xF;
4837 ltc >>= 4;
4838 minutes += (ltc & 0x7) * 10;
4839 ltc >>= 4;
4840 hours = ltc & 0xF;
4841 ltc >>= 4;
4842 hours += (ltc & 0x3) * 10;
4843 snd_iprintf(buffer,
4844 " LTC In: %02d:%02d:%02d:%02d\n",
4845 hours, minutes, seconds, frames);
4846
4847 } else {
4848 snd_iprintf(buffer, "No TCO module detected.\n");
4849 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004850
4851 snd_iprintf(buffer, "--- Settings ---\n");
4852
Adrian Knoth7cb155f2011-08-15 00:22:53 +02004853 x = hdspm_get_latency(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02004854
4855 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004856 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4857 x, (unsigned long) hdspm->period_bytes);
Takashi Iwai763f3562005-06-03 11:25:34 +02004858
Adrian Knoth0dca1792011-01-26 19:32:14 +01004859 snd_iprintf(buffer, "Line out: %s\n",
4860 (hdspm->control_register & HDSPM_LineOut) ? "on " : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004861
4862 switch (hdspm->control_register & HDSPM_InputMask) {
4863 case HDSPM_InputOptical:
4864 insel = "Optical";
4865 break;
4866 case HDSPM_InputCoaxial:
4867 insel = "Coaxial";
4868 break;
4869 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01004870 insel = "Unkown";
Takashi Iwai763f3562005-06-03 11:25:34 +02004871 }
4872
Takashi Iwai763f3562005-06-03 11:25:34 +02004873 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004874 "ClearTrackMarker = %s, Transmit in %s Channel Mode, "
4875 "Auto Input %s\n",
4876 (hdspm->control_register & HDSPM_clr_tms) ? "on" : "off",
4877 (hdspm->control_register & HDSPM_TX_64ch) ? "64" : "56",
4878 (hdspm->control_register & HDSPM_AutoInp) ? "on" : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004879
Adrian Knoth0dca1792011-01-26 19:32:14 +01004880
Remy Bruno3cee5a62006-10-16 12:46:32 +02004881 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
Adrian Knoth0dca1792011-01-26 19:32:14 +01004882 system_clock_mode = "AutoSync";
Remy Bruno3cee5a62006-10-16 12:46:32 +02004883 else
Takashi Iwai763f3562005-06-03 11:25:34 +02004884 system_clock_mode = "Master";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004885 snd_iprintf(buffer, "AutoSync Reference: %s\n", system_clock_mode);
Takashi Iwai763f3562005-06-03 11:25:34 +02004886
4887 switch (hdspm_pref_sync_ref(hdspm)) {
4888 case HDSPM_SYNC_FROM_WORD:
4889 pref_sync_ref = "Word Clock";
4890 break;
4891 case HDSPM_SYNC_FROM_MADI:
4892 pref_sync_ref = "MADI Sync";
4893 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004894 case HDSPM_SYNC_FROM_TCO:
4895 pref_sync_ref = "TCO";
4896 break;
4897 case HDSPM_SYNC_FROM_SYNC_IN:
4898 pref_sync_ref = "Sync In";
4899 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004900 default:
4901 pref_sync_ref = "XXXX Clock";
4902 break;
4903 }
4904 snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004905 pref_sync_ref);
Takashi Iwai763f3562005-06-03 11:25:34 +02004906
4907 snd_iprintf(buffer, "System Clock Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004908 hdspm->system_sample_rate);
Takashi Iwai763f3562005-06-03 11:25:34 +02004909
4910
4911 snd_iprintf(buffer, "--- Status:\n");
4912
4913 x = status & HDSPM_madiSync;
4914 x2 = status2 & HDSPM_wcSync;
4915
4916 snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004917 (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
4918 "NoLock",
4919 (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
4920 "NoLock");
Takashi Iwai763f3562005-06-03 11:25:34 +02004921
4922 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004923 case HDSPM_AUTOSYNC_FROM_SYNC_IN:
4924 autosync_ref = "Sync In";
4925 break;
4926 case HDSPM_AUTOSYNC_FROM_TCO:
4927 autosync_ref = "TCO";
4928 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004929 case HDSPM_AUTOSYNC_FROM_WORD:
4930 autosync_ref = "Word Clock";
4931 break;
4932 case HDSPM_AUTOSYNC_FROM_MADI:
4933 autosync_ref = "MADI Sync";
4934 break;
4935 case HDSPM_AUTOSYNC_FROM_NONE:
4936 autosync_ref = "Input not valid";
4937 break;
4938 default:
4939 autosync_ref = "---";
4940 break;
4941 }
4942 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004943 "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
4944 autosync_ref, hdspm_external_sample_rate(hdspm),
4945 (status & HDSPM_madiFreqMask) >> 22,
4946 (status2 & HDSPM_wcFreqMask) >> 5);
Takashi Iwai763f3562005-06-03 11:25:34 +02004947
4948 snd_iprintf(buffer, "Input: %s, Mode=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004949 (status & HDSPM_AB_int) ? "Coax" : "Optical",
4950 (status & HDSPM_RX_64ch) ? "64 channels" :
4951 "56 channels");
Takashi Iwai763f3562005-06-03 11:25:34 +02004952
4953 snd_iprintf(buffer, "\n");
4954}
4955
Remy Bruno3cee5a62006-10-16 12:46:32 +02004956static void
4957snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
4958 struct snd_info_buffer *buffer)
4959{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004960 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004961 unsigned int status;
4962 unsigned int status2;
4963 unsigned int timecode;
4964 int pref_syncref;
4965 char *autosync_ref;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004966 int x;
4967
4968 status = hdspm_read(hdspm, HDSPM_statusRegister);
4969 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
4970 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
4971
4972 snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
4973 hdspm->card_name, hdspm->card->number + 1,
4974 hdspm->firmware_rev);
4975
4976 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
4977 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
4978
4979 snd_iprintf(buffer, "--- System ---\n");
4980
4981 snd_iprintf(buffer,
4982 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4983 status & HDSPM_audioIRQPending,
4984 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4985 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4986 hdspm->irq_count);
4987 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004988 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4989 "estimated= %ld (bytes)\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004990 ((status & HDSPM_BufferID) ? 1 : 0),
4991 (status & HDSPM_BufferPositionMask),
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004992 (status & HDSPM_BufferPositionMask) %
4993 (2 * (int)hdspm->period_bytes),
4994 ((status & HDSPM_BufferPositionMask) - 64) %
4995 (2 * (int)hdspm->period_bytes),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004996 (long) hdspm_hw_pointer(hdspm) * 4);
4997
4998 snd_iprintf(buffer,
4999 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
5000 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
5001 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
5002 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
5003 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
5004 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005005 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
5006 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
5007 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
5008 snd_iprintf(buffer,
5009 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
5010 "status2=0x%x\n",
5011 hdspm->control_register, hdspm->control2_register,
5012 status, status2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02005013
5014 snd_iprintf(buffer, "--- Settings ---\n");
5015
Adrian Knoth7cb155f2011-08-15 00:22:53 +02005016 x = hdspm_get_latency(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02005017
5018 snd_iprintf(buffer,
5019 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
5020 x, (unsigned long) hdspm->period_bytes);
5021
Adrian Knoth0dca1792011-01-26 19:32:14 +01005022 snd_iprintf(buffer, "Line out: %s\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005023 (hdspm->
Adrian Knoth0dca1792011-01-26 19:32:14 +01005024 control_register & HDSPM_LineOut) ? "on " : "off");
Remy Bruno3cee5a62006-10-16 12:46:32 +02005025
5026 snd_iprintf(buffer,
5027 "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
5028 (hdspm->
5029 control_register & HDSPM_clr_tms) ? "on" : "off",
5030 (hdspm->
5031 control_register & HDSPM_Emphasis) ? "on" : "off",
5032 (hdspm->
5033 control_register & HDSPM_Dolby) ? "on" : "off");
5034
Remy Bruno3cee5a62006-10-16 12:46:32 +02005035
5036 pref_syncref = hdspm_pref_sync_ref(hdspm);
5037 if (pref_syncref == 0)
5038 snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
5039 else
5040 snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
5041 pref_syncref);
5042
5043 snd_iprintf(buffer, "System Clock Frequency: %d\n",
5044 hdspm->system_sample_rate);
5045
5046 snd_iprintf(buffer, "Double speed: %s\n",
5047 hdspm->control_register & HDSPM_DS_DoubleWire?
5048 "Double wire" : "Single wire");
5049 snd_iprintf(buffer, "Quad speed: %s\n",
5050 hdspm->control_register & HDSPM_QS_DoubleWire?
5051 "Double wire" :
5052 hdspm->control_register & HDSPM_QS_QuadWire?
5053 "Quad wire" : "Single wire");
5054
5055 snd_iprintf(buffer, "--- Status:\n");
5056
5057 snd_iprintf(buffer, "Word: %s Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01005058 (status & HDSPM_AES32_wcLock) ? "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005059 HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02005060
5061 for (x = 0; x < 8; x++) {
5062 snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005063 x+1,
5064 (status2 & (HDSPM_LockAES >> x)) ?
Adrian Knoth0dca1792011-01-26 19:32:14 +01005065 "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005066 HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02005067 }
5068
5069 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005070 case HDSPM_AES32_AUTOSYNC_FROM_NONE:
5071 autosync_ref = "None"; break;
5072 case HDSPM_AES32_AUTOSYNC_FROM_WORD:
5073 autosync_ref = "Word Clock"; break;
5074 case HDSPM_AES32_AUTOSYNC_FROM_AES1:
5075 autosync_ref = "AES1"; break;
5076 case HDSPM_AES32_AUTOSYNC_FROM_AES2:
5077 autosync_ref = "AES2"; break;
5078 case HDSPM_AES32_AUTOSYNC_FROM_AES3:
5079 autosync_ref = "AES3"; break;
5080 case HDSPM_AES32_AUTOSYNC_FROM_AES4:
5081 autosync_ref = "AES4"; break;
5082 case HDSPM_AES32_AUTOSYNC_FROM_AES5:
5083 autosync_ref = "AES5"; break;
5084 case HDSPM_AES32_AUTOSYNC_FROM_AES6:
5085 autosync_ref = "AES6"; break;
5086 case HDSPM_AES32_AUTOSYNC_FROM_AES7:
5087 autosync_ref = "AES7"; break;
5088 case HDSPM_AES32_AUTOSYNC_FROM_AES8:
5089 autosync_ref = "AES8"; break;
5090 default:
5091 autosync_ref = "---"; break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005092 }
5093 snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
5094
5095 snd_iprintf(buffer, "\n");
5096}
5097
Adrian Knoth0dca1792011-01-26 19:32:14 +01005098static void
5099snd_hdspm_proc_read_raydat(struct snd_info_entry *entry,
5100 struct snd_info_buffer *buffer)
5101{
5102 struct hdspm *hdspm = entry->private_data;
5103 unsigned int status1, status2, status3, control, i;
5104 unsigned int lock, sync;
5105
5106 status1 = hdspm_read(hdspm, HDSPM_RD_STATUS_1); /* s1 */
5107 status2 = hdspm_read(hdspm, HDSPM_RD_STATUS_2); /* freq */
5108 status3 = hdspm_read(hdspm, HDSPM_RD_STATUS_3); /* s2 */
5109
5110 control = hdspm->control_register;
5111
5112 snd_iprintf(buffer, "STATUS1: 0x%08x\n", status1);
5113 snd_iprintf(buffer, "STATUS2: 0x%08x\n", status2);
5114 snd_iprintf(buffer, "STATUS3: 0x%08x\n", status3);
5115
5116
5117 snd_iprintf(buffer, "\n*** CLOCK MODE\n\n");
5118
5119 snd_iprintf(buffer, "Clock mode : %s\n",
5120 (hdspm_system_clock_mode(hdspm) == 0) ? "master" : "slave");
5121 snd_iprintf(buffer, "System frequency: %d Hz\n",
5122 hdspm_get_system_sample_rate(hdspm));
5123
5124 snd_iprintf(buffer, "\n*** INPUT STATUS\n\n");
5125
5126 lock = 0x1;
5127 sync = 0x100;
5128
5129 for (i = 0; i < 8; i++) {
5130 snd_iprintf(buffer, "s1_input %d: Lock %d, Sync %d, Freq %s\n",
5131 i,
5132 (status1 & lock) ? 1 : 0,
5133 (status1 & sync) ? 1 : 0,
5134 texts_freq[(status2 >> (i * 4)) & 0xF]);
5135
5136 lock = lock<<1;
5137 sync = sync<<1;
5138 }
5139
5140 snd_iprintf(buffer, "WC input: Lock %d, Sync %d, Freq %s\n",
5141 (status1 & 0x1000000) ? 1 : 0,
5142 (status1 & 0x2000000) ? 1 : 0,
5143 texts_freq[(status1 >> 16) & 0xF]);
5144
5145 snd_iprintf(buffer, "TCO input: Lock %d, Sync %d, Freq %s\n",
5146 (status1 & 0x4000000) ? 1 : 0,
5147 (status1 & 0x8000000) ? 1 : 0,
5148 texts_freq[(status1 >> 20) & 0xF]);
5149
5150 snd_iprintf(buffer, "SYNC IN: Lock %d, Sync %d, Freq %s\n",
5151 (status3 & 0x400) ? 1 : 0,
5152 (status3 & 0x800) ? 1 : 0,
5153 texts_freq[(status2 >> 12) & 0xF]);
5154
5155}
5156
Remy Bruno3cee5a62006-10-16 12:46:32 +02005157#ifdef CONFIG_SND_DEBUG
5158static void
Adrian Knoth0dca1792011-01-26 19:32:14 +01005159snd_hdspm_proc_read_debug(struct snd_info_entry *entry,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005160 struct snd_info_buffer *buffer)
5161{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005162 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005163
5164 int j,i;
5165
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005166 for (i = 0; i < 256 /* 1024*64 */; i += j) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02005167 snd_iprintf(buffer, "0x%08X: ", i);
5168 for (j = 0; j < 16; j += 4)
5169 snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
5170 snd_iprintf(buffer, "\n");
5171 }
5172}
5173#endif
5174
5175
Adrian Knoth0dca1792011-01-26 19:32:14 +01005176static void snd_hdspm_proc_ports_in(struct snd_info_entry *entry,
5177 struct snd_info_buffer *buffer)
5178{
5179 struct hdspm *hdspm = entry->private_data;
5180 int i;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005181
Adrian Knoth0dca1792011-01-26 19:32:14 +01005182 snd_iprintf(buffer, "# generated by hdspm\n");
5183
5184 for (i = 0; i < hdspm->max_channels_in; i++) {
5185 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_in[i]);
5186 }
5187}
5188
5189static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry,
5190 struct snd_info_buffer *buffer)
5191{
5192 struct hdspm *hdspm = entry->private_data;
5193 int i;
5194
5195 snd_iprintf(buffer, "# generated by hdspm\n");
5196
5197 for (i = 0; i < hdspm->max_channels_out; i++) {
5198 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_out[i]);
5199 }
5200}
5201
5202
5203static void __devinit snd_hdspm_proc_init(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005204{
Takashi Iwai98274f02005-11-17 14:52:34 +01005205 struct snd_info_entry *entry;
Takashi Iwai763f3562005-06-03 11:25:34 +02005206
Adrian Knoth0dca1792011-01-26 19:32:14 +01005207 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) {
5208 switch (hdspm->io_type) {
5209 case AES32:
5210 snd_info_set_text_ops(entry, hdspm,
5211 snd_hdspm_proc_read_aes32);
5212 break;
5213 case MADI:
5214 snd_info_set_text_ops(entry, hdspm,
5215 snd_hdspm_proc_read_madi);
5216 break;
5217 case MADIface:
5218 /* snd_info_set_text_ops(entry, hdspm,
5219 snd_hdspm_proc_read_madiface); */
5220 break;
5221 case RayDAT:
5222 snd_info_set_text_ops(entry, hdspm,
5223 snd_hdspm_proc_read_raydat);
5224 break;
5225 case AIO:
5226 break;
5227 }
5228 }
5229
5230 if (!snd_card_proc_new(hdspm->card, "ports.in", &entry)) {
5231 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_in);
5232 }
5233
5234 if (!snd_card_proc_new(hdspm->card, "ports.out", &entry)) {
5235 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_out);
5236 }
5237
Remy Bruno3cee5a62006-10-16 12:46:32 +02005238#ifdef CONFIG_SND_DEBUG
5239 /* debug file to read all hdspm registers */
5240 if (!snd_card_proc_new(hdspm->card, "debug", &entry))
5241 snd_info_set_text_ops(entry, hdspm,
5242 snd_hdspm_proc_read_debug);
5243#endif
Takashi Iwai763f3562005-06-03 11:25:34 +02005244}
5245
5246/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005247 hdspm intitialize
Takashi Iwai763f3562005-06-03 11:25:34 +02005248 ------------------------------------------------------------*/
5249
Takashi Iwai98274f02005-11-17 14:52:34 +01005250static int snd_hdspm_set_defaults(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005251{
Takashi Iwai763f3562005-06-03 11:25:34 +02005252 /* ASSUMPTION: hdspm->lock is either held, or there is no need to
Joe Perches561de312007-12-18 13:13:47 +01005253 hold it (e.g. during module initialization).
Adrian Knoth0dca1792011-01-26 19:32:14 +01005254 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005255
5256 /* set defaults: */
5257
Adrian Knoth0dca1792011-01-26 19:32:14 +01005258 hdspm->settings_register = 0;
5259
5260 switch (hdspm->io_type) {
5261 case MADI:
5262 case MADIface:
5263 hdspm->control_register =
5264 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5265 break;
5266
5267 case RayDAT:
5268 case AIO:
5269 hdspm->settings_register = 0x1 + 0x1000;
5270 /* Magic values are: LAT_0, LAT_2, Master, freq1, tx64ch, inp_0,
5271 * line_out */
5272 hdspm->control_register =
5273 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5274 break;
5275
5276 case AES32:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005277 hdspm->control_register =
5278 HDSPM_ClockModeMaster | /* Master Cloack Mode on */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005279 hdspm_encode_latency(7) | /* latency max=8192samples */
Remy Bruno3cee5a62006-10-16 12:46:32 +02005280 HDSPM_SyncRef0 | /* AES1 is syncclock */
5281 HDSPM_LineOut | /* Analog output in */
5282 HDSPM_Professional; /* Professional mode */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005283 break;
5284 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005285
5286 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5287
Adrian Knoth0dca1792011-01-26 19:32:14 +01005288 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005289 /* No control2 register for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005290#ifdef SNDRV_BIG_ENDIAN
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005291 hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
Takashi Iwai763f3562005-06-03 11:25:34 +02005292#else
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005293 hdspm->control2_register = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005294#endif
5295
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005296 hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
5297 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005298 hdspm_compute_period_size(hdspm);
5299
5300 /* silence everything */
5301
5302 all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
5303
Adrian Knoth0dca1792011-01-26 19:32:14 +01005304 if (hdspm->io_type == AIO || hdspm->io_type == RayDAT) {
5305 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
Takashi Iwai763f3562005-06-03 11:25:34 +02005306 }
5307
5308 /* set a default rate so that the channel map is set up. */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005309 hdspm_set_rate(hdspm, 48000, 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02005310
5311 return 0;
5312}
5313
5314
5315/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005316 interrupt
Takashi Iwai763f3562005-06-03 11:25:34 +02005317 ------------------------------------------------------------*/
5318
David Howells7d12e782006-10-05 14:55:46 +01005319static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02005320{
Takashi Iwai98274f02005-11-17 14:52:34 +01005321 struct hdspm *hdspm = (struct hdspm *) dev_id;
Takashi Iwai763f3562005-06-03 11:25:34 +02005322 unsigned int status;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005323 int i, audio, midi, schedule = 0;
5324 /* cycles_t now; */
Takashi Iwai763f3562005-06-03 11:25:34 +02005325
5326 status = hdspm_read(hdspm, HDSPM_statusRegister);
5327
5328 audio = status & HDSPM_audioIRQPending;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005329 midi = status & (HDSPM_midi0IRQPending | HDSPM_midi1IRQPending |
5330 HDSPM_midi2IRQPending | HDSPM_midi3IRQPending);
Takashi Iwai763f3562005-06-03 11:25:34 +02005331
Adrian Knoth0dca1792011-01-26 19:32:14 +01005332 /* now = get_cycles(); */
5333 /**
5334 * LAT_2..LAT_0 period counter (win) counter (mac)
5335 * 6 4096 ~256053425 ~514672358
5336 * 5 2048 ~128024983 ~257373821
5337 * 4 1024 ~64023706 ~128718089
5338 * 3 512 ~32005945 ~64385999
5339 * 2 256 ~16003039 ~32260176
5340 * 1 128 ~7998738 ~16194507
5341 * 0 64 ~3998231 ~8191558
5342 **/
5343 /*
5344 snd_printk(KERN_INFO "snd_hdspm_interrupt %llu @ %llx\n",
5345 now-hdspm->last_interrupt, status & 0xFFC0);
5346 hdspm->last_interrupt = now;
5347 */
5348
5349 if (!audio && !midi)
Takashi Iwai763f3562005-06-03 11:25:34 +02005350 return IRQ_NONE;
5351
5352 hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
5353 hdspm->irq_count++;
5354
Takashi Iwai763f3562005-06-03 11:25:34 +02005355
5356 if (audio) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005357 if (hdspm->capture_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005358 snd_pcm_period_elapsed(hdspm->capture_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005359
5360 if (hdspm->playback_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005361 snd_pcm_period_elapsed(hdspm->playback_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005362 }
5363
Adrian Knoth0dca1792011-01-26 19:32:14 +01005364 if (midi) {
5365 i = 0;
5366 while (i < hdspm->midiPorts) {
5367 if ((hdspm_read(hdspm,
5368 hdspm->midi[i].statusIn) & 0xff) &&
5369 (status & hdspm->midi[i].irq)) {
5370 /* we disable interrupts for this input until
5371 * processing is done
5372 */
5373 hdspm->control_register &= ~hdspm->midi[i].ie;
5374 hdspm_write(hdspm, HDSPM_controlRegister,
5375 hdspm->control_register);
5376 hdspm->midi[i].pending = 1;
5377 schedule = 1;
5378 }
5379
5380 i++;
5381 }
5382
5383 if (schedule)
5384 tasklet_hi_schedule(&hdspm->midi_tasklet);
Takashi Iwai763f3562005-06-03 11:25:34 +02005385 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005386
Takashi Iwai763f3562005-06-03 11:25:34 +02005387 return IRQ_HANDLED;
5388}
5389
5390/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005391 pcm interface
Takashi Iwai763f3562005-06-03 11:25:34 +02005392 ------------------------------------------------------------*/
5393
5394
Adrian Knoth0dca1792011-01-26 19:32:14 +01005395static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream
5396 *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005397{
Takashi Iwai98274f02005-11-17 14:52:34 +01005398 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005399 return hdspm_hw_pointer(hdspm);
5400}
5401
Takashi Iwai763f3562005-06-03 11:25:34 +02005402
Takashi Iwai98274f02005-11-17 14:52:34 +01005403static int snd_hdspm_reset(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005404{
Takashi Iwai98274f02005-11-17 14:52:34 +01005405 struct snd_pcm_runtime *runtime = substream->runtime;
5406 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5407 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005408
5409 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5410 other = hdspm->capture_substream;
5411 else
5412 other = hdspm->playback_substream;
5413
5414 if (hdspm->running)
5415 runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
5416 else
5417 runtime->status->hw_ptr = 0;
5418 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005419 struct snd_pcm_substream *s;
5420 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01005421 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005422 if (s == other) {
5423 oruntime->status->hw_ptr =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005424 runtime->status->hw_ptr;
Takashi Iwai763f3562005-06-03 11:25:34 +02005425 break;
5426 }
5427 }
5428 }
5429 return 0;
5430}
5431
Takashi Iwai98274f02005-11-17 14:52:34 +01005432static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
5433 struct snd_pcm_hw_params *params)
Takashi Iwai763f3562005-06-03 11:25:34 +02005434{
Takashi Iwai98274f02005-11-17 14:52:34 +01005435 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005436 int err;
5437 int i;
5438 pid_t this_pid;
5439 pid_t other_pid;
Takashi Iwai763f3562005-06-03 11:25:34 +02005440
5441 spin_lock_irq(&hdspm->lock);
5442
5443 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5444 this_pid = hdspm->playback_pid;
5445 other_pid = hdspm->capture_pid;
5446 } else {
5447 this_pid = hdspm->capture_pid;
5448 other_pid = hdspm->playback_pid;
5449 }
5450
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005451 if (other_pid > 0 && this_pid != other_pid) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005452
5453 /* The other stream is open, and not by the same
5454 task as this one. Make sure that the parameters
5455 that matter are the same.
Adrian Knoth0dca1792011-01-26 19:32:14 +01005456 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005457
5458 if (params_rate(params) != hdspm->system_sample_rate) {
5459 spin_unlock_irq(&hdspm->lock);
5460 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005461 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005462 return -EBUSY;
5463 }
5464
5465 if (params_period_size(params) != hdspm->period_bytes / 4) {
5466 spin_unlock_irq(&hdspm->lock);
5467 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005468 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005469 return -EBUSY;
5470 }
5471
5472 }
5473 /* We're fine. */
5474 spin_unlock_irq(&hdspm->lock);
5475
5476 /* how to make sure that the rate matches an externally-set one ? */
5477
5478 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005479 err = hdspm_set_rate(hdspm, params_rate(params), 0);
5480 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005481 snd_printk(KERN_INFO "err on hdspm_set_rate: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005482 spin_unlock_irq(&hdspm->lock);
5483 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005484 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005485 return err;
5486 }
5487 spin_unlock_irq(&hdspm->lock);
5488
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005489 err = hdspm_set_interrupt_interval(hdspm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005490 params_period_size(params));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005491 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005492 snd_printk(KERN_INFO "err on hdspm_set_interrupt_interval: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005493 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005494 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005495 return err;
5496 }
5497
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005498 /* Memory allocation, takashi's method, dont know if we should
5499 * spinlock
5500 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005501 /* malloc all buffer even if not enabled to get sure */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005502 /* Update for MADI rev 204: we need to allocate for all channels,
5503 * otherwise it doesn't work at 96kHz */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005504
Takashi Iwai763f3562005-06-03 11:25:34 +02005505 err =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005506 snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
5507 if (err < 0) {
5508 snd_printk(KERN_INFO "err on snd_pcm_lib_malloc_pages: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005509 return err;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005510 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005511
Takashi Iwai763f3562005-06-03 11:25:34 +02005512 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5513
Takashi Iwai77a23f22008-08-21 13:00:13 +02005514 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferOut,
Takashi Iwai763f3562005-06-03 11:25:34 +02005515 params_channels(params));
5516
5517 for (i = 0; i < params_channels(params); ++i)
5518 snd_hdspm_enable_out(hdspm, i, 1);
5519
5520 hdspm->playback_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005521 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005522 snd_printdd("Allocated sample buffer for playback at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005523 hdspm->playback_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005524 } else {
Takashi Iwai77a23f22008-08-21 13:00:13 +02005525 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn,
Takashi Iwai763f3562005-06-03 11:25:34 +02005526 params_channels(params));
5527
5528 for (i = 0; i < params_channels(params); ++i)
5529 snd_hdspm_enable_in(hdspm, i, 1);
5530
5531 hdspm->capture_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005532 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005533 snd_printdd("Allocated sample buffer for capture at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005534 hdspm->capture_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005535 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005536
Remy Bruno3cee5a62006-10-16 12:46:32 +02005537 /*
5538 snd_printdd("Allocated sample buffer for %s at 0x%08X\n",
5539 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5540 "playback" : "capture",
Takashi Iwai77a23f22008-08-21 13:00:13 +02005541 snd_pcm_sgbuf_get_addr(substream, 0));
Adrian Knoth0dca1792011-01-26 19:32:14 +01005542 */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005543 /*
Adrian Knoth0dca1792011-01-26 19:32:14 +01005544 snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n",
5545 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5546 "playback" : "capture",
5547 params_rate(params), params_channels(params),
5548 params_buffer_size(params));
5549 */
5550
5551
5552 /* Switch to native float format if requested */
5553 if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) {
5554 if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT))
5555 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE float format.\n");
5556
5557 hdspm->control_register |= HDSPe_FLOAT_FORMAT;
5558 } else if (SNDRV_PCM_FORMAT_S32_LE == params_format(params)) {
5559 if (hdspm->control_register & HDSPe_FLOAT_FORMAT)
5560 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE integer format.\n");
5561
5562 hdspm->control_register &= ~HDSPe_FLOAT_FORMAT;
5563 }
5564 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5565
Takashi Iwai763f3562005-06-03 11:25:34 +02005566 return 0;
5567}
5568
Takashi Iwai98274f02005-11-17 14:52:34 +01005569static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005570{
5571 int i;
Takashi Iwai98274f02005-11-17 14:52:34 +01005572 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005573
5574 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5575
Adrian Knoth0dca1792011-01-26 19:32:14 +01005576 /* params_channels(params) should be enough,
Takashi Iwai763f3562005-06-03 11:25:34 +02005577 but to get sure in case of error */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005578 for (i = 0; i < hdspm->max_channels_out; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005579 snd_hdspm_enable_out(hdspm, i, 0);
5580
5581 hdspm->playback_buffer = NULL;
5582 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005583 for (i = 0; i < hdspm->max_channels_in; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005584 snd_hdspm_enable_in(hdspm, i, 0);
5585
5586 hdspm->capture_buffer = NULL;
5587
5588 }
5589
5590 snd_pcm_lib_free_pages(substream);
5591
5592 return 0;
5593}
5594
Adrian Knoth0dca1792011-01-26 19:32:14 +01005595
Takashi Iwai98274f02005-11-17 14:52:34 +01005596static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005597 struct snd_pcm_channel_info *info)
Takashi Iwai763f3562005-06-03 11:25:34 +02005598{
Takashi Iwai98274f02005-11-17 14:52:34 +01005599 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005600
Adrian Knoth0dca1792011-01-26 19:32:14 +01005601 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5602 if (snd_BUG_ON(info->channel >= hdspm->max_channels_out)) {
5603 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel out of range (%d)\n", info->channel);
5604 return -EINVAL;
5605 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005606
Adrian Knoth0dca1792011-01-26 19:32:14 +01005607 if (hdspm->channel_map_out[info->channel] < 0) {
5608 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel %d mapped out\n", info->channel);
5609 return -EINVAL;
5610 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005611
Adrian Knoth0dca1792011-01-26 19:32:14 +01005612 info->offset = hdspm->channel_map_out[info->channel] *
5613 HDSPM_CHANNEL_BUFFER_BYTES;
5614 } else {
5615 if (snd_BUG_ON(info->channel >= hdspm->max_channels_in)) {
5616 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel out of range (%d)\n", info->channel);
5617 return -EINVAL;
5618 }
5619
5620 if (hdspm->channel_map_in[info->channel] < 0) {
5621 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel %d mapped out\n", info->channel);
5622 return -EINVAL;
5623 }
5624
5625 info->offset = hdspm->channel_map_in[info->channel] *
5626 HDSPM_CHANNEL_BUFFER_BYTES;
5627 }
5628
Takashi Iwai763f3562005-06-03 11:25:34 +02005629 info->first = 0;
5630 info->step = 32;
5631 return 0;
5632}
5633
Adrian Knoth0dca1792011-01-26 19:32:14 +01005634
Takashi Iwai98274f02005-11-17 14:52:34 +01005635static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005636 unsigned int cmd, void *arg)
Takashi Iwai763f3562005-06-03 11:25:34 +02005637{
5638 switch (cmd) {
5639 case SNDRV_PCM_IOCTL1_RESET:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005640 return snd_hdspm_reset(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005641
5642 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Adrian Knoth0dca1792011-01-26 19:32:14 +01005643 {
5644 struct snd_pcm_channel_info *info = arg;
5645 return snd_hdspm_channel_info(substream, info);
5646 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005647 default:
5648 break;
5649 }
5650
5651 return snd_pcm_lib_ioctl(substream, cmd, arg);
5652}
5653
Takashi Iwai98274f02005-11-17 14:52:34 +01005654static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
Takashi Iwai763f3562005-06-03 11:25:34 +02005655{
Takashi Iwai98274f02005-11-17 14:52:34 +01005656 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5657 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005658 int running;
5659
5660 spin_lock(&hdspm->lock);
5661 running = hdspm->running;
5662 switch (cmd) {
5663 case SNDRV_PCM_TRIGGER_START:
5664 running |= 1 << substream->stream;
5665 break;
5666 case SNDRV_PCM_TRIGGER_STOP:
5667 running &= ~(1 << substream->stream);
5668 break;
5669 default:
5670 snd_BUG();
5671 spin_unlock(&hdspm->lock);
5672 return -EINVAL;
5673 }
5674 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5675 other = hdspm->capture_substream;
5676 else
5677 other = hdspm->playback_substream;
5678
5679 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005680 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01005681 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005682 if (s == other) {
5683 snd_pcm_trigger_done(s, substream);
5684 if (cmd == SNDRV_PCM_TRIGGER_START)
5685 running |= 1 << s->stream;
5686 else
5687 running &= ~(1 << s->stream);
5688 goto _ok;
5689 }
5690 }
5691 if (cmd == SNDRV_PCM_TRIGGER_START) {
5692 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005693 && substream->stream ==
5694 SNDRV_PCM_STREAM_CAPTURE)
Takashi Iwai763f3562005-06-03 11:25:34 +02005695 hdspm_silence_playback(hdspm);
5696 } else {
5697 if (running &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01005698 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Takashi Iwai763f3562005-06-03 11:25:34 +02005699 hdspm_silence_playback(hdspm);
5700 }
5701 } else {
5702 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
5703 hdspm_silence_playback(hdspm);
5704 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005705_ok:
Takashi Iwai763f3562005-06-03 11:25:34 +02005706 snd_pcm_trigger_done(substream, substream);
5707 if (!hdspm->running && running)
5708 hdspm_start_audio(hdspm);
5709 else if (hdspm->running && !running)
5710 hdspm_stop_audio(hdspm);
5711 hdspm->running = running;
5712 spin_unlock(&hdspm->lock);
5713
5714 return 0;
5715}
5716
Takashi Iwai98274f02005-11-17 14:52:34 +01005717static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005718{
5719 return 0;
5720}
5721
Takashi Iwai98274f02005-11-17 14:52:34 +01005722static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005723 .info = (SNDRV_PCM_INFO_MMAP |
5724 SNDRV_PCM_INFO_MMAP_VALID |
5725 SNDRV_PCM_INFO_NONINTERLEAVED |
5726 SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
5727 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5728 .rates = (SNDRV_PCM_RATE_32000 |
5729 SNDRV_PCM_RATE_44100 |
5730 SNDRV_PCM_RATE_48000 |
5731 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005732 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5733 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ),
Takashi Iwai763f3562005-06-03 11:25:34 +02005734 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005735 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005736 .channels_min = 1,
5737 .channels_max = HDSPM_MAX_CHANNELS,
5738 .buffer_bytes_max =
5739 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
Adrian Knoth1b6fa102011-08-15 00:22:51 +02005740 .period_bytes_min = (32 * 4),
Takashi Iwai52e6fb42011-08-15 10:40:59 +02005741 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005742 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005743 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005744 .fifo_size = 0
5745};
5746
Takashi Iwai98274f02005-11-17 14:52:34 +01005747static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005748 .info = (SNDRV_PCM_INFO_MMAP |
5749 SNDRV_PCM_INFO_MMAP_VALID |
5750 SNDRV_PCM_INFO_NONINTERLEAVED |
5751 SNDRV_PCM_INFO_SYNC_START),
5752 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5753 .rates = (SNDRV_PCM_RATE_32000 |
5754 SNDRV_PCM_RATE_44100 |
5755 SNDRV_PCM_RATE_48000 |
5756 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005757 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5758 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
Takashi Iwai763f3562005-06-03 11:25:34 +02005759 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005760 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005761 .channels_min = 1,
5762 .channels_max = HDSPM_MAX_CHANNELS,
5763 .buffer_bytes_max =
5764 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
Adrian Knoth1b6fa102011-08-15 00:22:51 +02005765 .period_bytes_min = (32 * 4),
Takashi Iwai52e6fb42011-08-15 10:40:59 +02005766 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005767 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005768 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005769 .fifo_size = 0
5770};
5771
Adrian Knoth0dca1792011-01-26 19:32:14 +01005772static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
5773 struct snd_pcm_hw_rule *rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005774{
Takashi Iwai98274f02005-11-17 14:52:34 +01005775 struct hdspm *hdspm = rule->private;
5776 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005777 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005778 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005779 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5780
Adrian Knoth0dca1792011-01-26 19:32:14 +01005781 if (r->min > 96000 && r->max <= 192000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005782 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005783 .min = hdspm->qs_in_channels,
5784 .max = hdspm->qs_in_channels,
5785 .integer = 1,
5786 };
5787 return snd_interval_refine(c, &t);
5788 } else if (r->min > 48000 && r->max <= 96000) {
5789 struct snd_interval t = {
5790 .min = hdspm->ds_in_channels,
5791 .max = hdspm->ds_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005792 .integer = 1,
5793 };
5794 return snd_interval_refine(c, &t);
5795 } else if (r->max < 64000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005796 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005797 .min = hdspm->ss_in_channels,
5798 .max = hdspm->ss_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005799 .integer = 1,
5800 };
5801 return snd_interval_refine(c, &t);
5802 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005803
Takashi Iwai763f3562005-06-03 11:25:34 +02005804 return 0;
5805}
5806
Adrian Knoth0dca1792011-01-26 19:32:14 +01005807static int snd_hdspm_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
Takashi Iwai98274f02005-11-17 14:52:34 +01005808 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005809{
Takashi Iwai98274f02005-11-17 14:52:34 +01005810 struct hdspm *hdspm = rule->private;
5811 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005812 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005813 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005814 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5815
Adrian Knoth0dca1792011-01-26 19:32:14 +01005816 if (r->min > 96000 && r->max <= 192000) {
5817 struct snd_interval t = {
5818 .min = hdspm->qs_out_channels,
5819 .max = hdspm->qs_out_channels,
5820 .integer = 1,
5821 };
5822 return snd_interval_refine(c, &t);
5823 } else if (r->min > 48000 && r->max <= 96000) {
5824 struct snd_interval t = {
5825 .min = hdspm->ds_out_channels,
5826 .max = hdspm->ds_out_channels,
5827 .integer = 1,
5828 };
5829 return snd_interval_refine(c, &t);
5830 } else if (r->max < 64000) {
5831 struct snd_interval t = {
5832 .min = hdspm->ss_out_channels,
5833 .max = hdspm->ss_out_channels,
5834 .integer = 1,
5835 };
5836 return snd_interval_refine(c, &t);
5837 } else {
5838 }
5839 return 0;
5840}
5841
5842static int snd_hdspm_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
5843 struct snd_pcm_hw_rule * rule)
5844{
5845 struct hdspm *hdspm = rule->private;
5846 struct snd_interval *c =
5847 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5848 struct snd_interval *r =
5849 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5850
5851 if (c->min >= hdspm->ss_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005852 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005853 .min = 32000,
5854 .max = 48000,
5855 .integer = 1,
5856 };
5857 return snd_interval_refine(r, &t);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005858 } else if (c->max <= hdspm->qs_in_channels) {
5859 struct snd_interval t = {
5860 .min = 128000,
5861 .max = 192000,
5862 .integer = 1,
5863 };
5864 return snd_interval_refine(r, &t);
5865 } else if (c->max <= hdspm->ds_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005866 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005867 .min = 64000,
5868 .max = 96000,
5869 .integer = 1,
5870 };
Takashi Iwai763f3562005-06-03 11:25:34 +02005871 return snd_interval_refine(r, &t);
5872 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005873
5874 return 0;
5875}
5876static int snd_hdspm_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
5877 struct snd_pcm_hw_rule *rule)
5878{
5879 struct hdspm *hdspm = rule->private;
5880 struct snd_interval *c =
5881 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5882 struct snd_interval *r =
5883 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5884
5885 if (c->min >= hdspm->ss_out_channels) {
5886 struct snd_interval t = {
5887 .min = 32000,
5888 .max = 48000,
5889 .integer = 1,
5890 };
5891 return snd_interval_refine(r, &t);
5892 } else if (c->max <= hdspm->qs_out_channels) {
5893 struct snd_interval t = {
5894 .min = 128000,
5895 .max = 192000,
5896 .integer = 1,
5897 };
5898 return snd_interval_refine(r, &t);
5899 } else if (c->max <= hdspm->ds_out_channels) {
5900 struct snd_interval t = {
5901 .min = 64000,
5902 .max = 96000,
5903 .integer = 1,
5904 };
5905 return snd_interval_refine(r, &t);
5906 }
5907
Takashi Iwai763f3562005-06-03 11:25:34 +02005908 return 0;
5909}
5910
Adrian Knoth0dca1792011-01-26 19:32:14 +01005911static int snd_hdspm_hw_rule_in_channels(struct snd_pcm_hw_params *params,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005912 struct snd_pcm_hw_rule *rule)
5913{
5914 unsigned int list[3];
5915 struct hdspm *hdspm = rule->private;
5916 struct snd_interval *c = hw_param_interval(params,
5917 SNDRV_PCM_HW_PARAM_CHANNELS);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005918
5919 list[0] = hdspm->qs_in_channels;
5920 list[1] = hdspm->ds_in_channels;
5921 list[2] = hdspm->ss_in_channels;
5922 return snd_interval_list(c, 3, list, 0);
5923}
5924
5925static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params,
5926 struct snd_pcm_hw_rule *rule)
5927{
5928 unsigned int list[3];
5929 struct hdspm *hdspm = rule->private;
5930 struct snd_interval *c = hw_param_interval(params,
5931 SNDRV_PCM_HW_PARAM_CHANNELS);
5932
5933 list[0] = hdspm->qs_out_channels;
5934 list[1] = hdspm->ds_out_channels;
5935 list[2] = hdspm->ss_out_channels;
5936 return snd_interval_list(c, 3, list, 0);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005937}
5938
5939
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005940static unsigned int hdspm_aes32_sample_rates[] = {
5941 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000
5942};
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005943
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005944static struct snd_pcm_hw_constraint_list
5945hdspm_hw_constraints_aes32_sample_rates = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005946 .count = ARRAY_SIZE(hdspm_aes32_sample_rates),
5947 .list = hdspm_aes32_sample_rates,
5948 .mask = 0
5949};
5950
Takashi Iwai98274f02005-11-17 14:52:34 +01005951static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005952{
Takashi Iwai98274f02005-11-17 14:52:34 +01005953 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5954 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02005955
Takashi Iwai763f3562005-06-03 11:25:34 +02005956 spin_lock_irq(&hdspm->lock);
5957
5958 snd_pcm_set_sync(substream);
5959
Adrian Knoth0dca1792011-01-26 19:32:14 +01005960
Takashi Iwai763f3562005-06-03 11:25:34 +02005961 runtime->hw = snd_hdspm_playback_subinfo;
5962
5963 if (hdspm->capture_substream == NULL)
5964 hdspm_stop_audio(hdspm);
5965
5966 hdspm->playback_pid = current->pid;
5967 hdspm->playback_substream = substream;
5968
5969 spin_unlock_irq(&hdspm->lock);
5970
5971 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Takashi Iwaid8776812011-08-15 10:45:42 +02005972 snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005973
Adrian Knoth0dca1792011-01-26 19:32:14 +01005974 switch (hdspm->io_type) {
5975 case AIO:
5976 case RayDAT:
Takashi Iwaid8776812011-08-15 10:45:42 +02005977 snd_pcm_hw_constraint_minmax(runtime,
5978 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5979 32, 4096);
5980 /* RayDAT & AIO have a fixed buffer of 16384 samples per channel */
5981 snd_pcm_hw_constraint_minmax(runtime,
5982 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
5983 16384, 16384);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005984 break;
5985
5986 default:
Takashi Iwaid8776812011-08-15 10:45:42 +02005987 snd_pcm_hw_constraint_minmax(runtime,
5988 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5989 64, 8192);
5990 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005991 }
5992
5993 if (AES32 == hdspm->io_type) {
Takashi Iwai3fa9e3d2011-08-15 10:42:23 +02005994 runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005995 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
5996 &hdspm_hw_constraints_aes32_sample_rates);
5997 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005998 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005999 snd_hdspm_hw_rule_rate_out_channels, hdspm,
6000 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006001 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01006002
6003 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
6004 snd_hdspm_hw_rule_out_channels, hdspm,
6005 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
6006
6007 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
6008 snd_hdspm_hw_rule_out_channels_rate, hdspm,
6009 SNDRV_PCM_HW_PARAM_RATE, -1);
6010
Takashi Iwai763f3562005-06-03 11:25:34 +02006011 return 0;
6012}
6013
Takashi Iwai98274f02005-11-17 14:52:34 +01006014static int snd_hdspm_playback_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02006015{
Takashi Iwai98274f02005-11-17 14:52:34 +01006016 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02006017
6018 spin_lock_irq(&hdspm->lock);
6019
6020 hdspm->playback_pid = -1;
6021 hdspm->playback_substream = NULL;
6022
6023 spin_unlock_irq(&hdspm->lock);
6024
6025 return 0;
6026}
6027
6028
Takashi Iwai98274f02005-11-17 14:52:34 +01006029static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02006030{
Takashi Iwai98274f02005-11-17 14:52:34 +01006031 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
6032 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02006033
6034 spin_lock_irq(&hdspm->lock);
6035 snd_pcm_set_sync(substream);
6036 runtime->hw = snd_hdspm_capture_subinfo;
6037
6038 if (hdspm->playback_substream == NULL)
6039 hdspm_stop_audio(hdspm);
6040
6041 hdspm->capture_pid = current->pid;
6042 hdspm->capture_substream = substream;
6043
6044 spin_unlock_irq(&hdspm->lock);
6045
6046 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Takashi Iwaid8776812011-08-15 10:45:42 +02006047 snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
6048
Adrian Knoth0dca1792011-01-26 19:32:14 +01006049 switch (hdspm->io_type) {
6050 case AIO:
6051 case RayDAT:
Takashi Iwaid8776812011-08-15 10:45:42 +02006052 snd_pcm_hw_constraint_minmax(runtime,
6053 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
6054 32, 4096);
6055 snd_pcm_hw_constraint_minmax(runtime,
6056 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
6057 16384, 16384);
6058 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006059
6060 default:
Takashi Iwaid8776812011-08-15 10:45:42 +02006061 snd_pcm_hw_constraint_minmax(runtime,
6062 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
6063 64, 8192);
6064 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006065 }
6066
6067 if (AES32 == hdspm->io_type) {
Takashi Iwai3fa9e3d2011-08-15 10:42:23 +02006068 runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006069 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
6070 &hdspm_hw_constraints_aes32_sample_rates);
6071 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006072 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth88fabbf2011-02-23 11:43:10 +01006073 snd_hdspm_hw_rule_rate_in_channels, hdspm,
6074 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006075 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01006076
6077 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
6078 snd_hdspm_hw_rule_in_channels, hdspm,
6079 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
6080
6081 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
6082 snd_hdspm_hw_rule_in_channels_rate, hdspm,
6083 SNDRV_PCM_HW_PARAM_RATE, -1);
6084
Takashi Iwai763f3562005-06-03 11:25:34 +02006085 return 0;
6086}
6087
Takashi Iwai98274f02005-11-17 14:52:34 +01006088static int snd_hdspm_capture_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02006089{
Takashi Iwai98274f02005-11-17 14:52:34 +01006090 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02006091
6092 spin_lock_irq(&hdspm->lock);
6093
6094 hdspm->capture_pid = -1;
6095 hdspm->capture_substream = NULL;
6096
6097 spin_unlock_irq(&hdspm->lock);
6098 return 0;
6099}
6100
Adrian Knoth0dca1792011-01-26 19:32:14 +01006101static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
Takashi Iwai763f3562005-06-03 11:25:34 +02006102{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006103 /* we have nothing to initialize but the call is required */
6104 return 0;
6105}
6106
6107static inline int copy_u32_le(void __user *dest, void __iomem *src)
6108{
6109 u32 val = readl(src);
6110 return copy_to_user(dest, &val, 4);
6111}
6112
6113static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006114 unsigned int cmd, unsigned long arg)
Adrian Knoth0dca1792011-01-26 19:32:14 +01006115{
6116 void __user *argp = (void __user *)arg;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006117 struct hdspm *hdspm = hw->private_data;
Takashi Iwai98274f02005-11-17 14:52:34 +01006118 struct hdspm_mixer_ioctl mixer;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006119 struct hdspm_config info;
6120 struct hdspm_status status;
Takashi Iwai98274f02005-11-17 14:52:34 +01006121 struct hdspm_version hdspm_version;
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006122 struct hdspm_peak_rms *levels;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006123 struct hdspm_ltc ltc;
6124 unsigned int statusregister;
6125 long unsigned int s;
6126 int i = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02006127
6128 switch (cmd) {
6129
Takashi Iwai763f3562005-06-03 11:25:34 +02006130 case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006131 levels = &hdspm->peak_rms;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006132 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006133 levels->input_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006134 readl(hdspm->iobase +
6135 HDSPM_MADI_INPUT_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006136 levels->playback_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006137 readl(hdspm->iobase +
6138 HDSPM_MADI_PLAYBACK_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006139 levels->output_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006140 readl(hdspm->iobase +
6141 HDSPM_MADI_OUTPUT_PEAK + i*4);
6142
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006143 levels->input_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006144 ((uint64_t) readl(hdspm->iobase +
6145 HDSPM_MADI_INPUT_RMS_H + i*4) << 32) |
6146 (uint64_t) readl(hdspm->iobase +
6147 HDSPM_MADI_INPUT_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006148 levels->playback_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006149 ((uint64_t)readl(hdspm->iobase +
6150 HDSPM_MADI_PLAYBACK_RMS_H+i*4) << 32) |
6151 (uint64_t)readl(hdspm->iobase +
6152 HDSPM_MADI_PLAYBACK_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006153 levels->output_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006154 ((uint64_t)readl(hdspm->iobase +
6155 HDSPM_MADI_OUTPUT_RMS_H + i*4) << 32) |
6156 (uint64_t)readl(hdspm->iobase +
6157 HDSPM_MADI_OUTPUT_RMS_L + i*4);
6158 }
6159
6160 if (hdspm->system_sample_rate > 96000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006161 levels->speed = qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006162 } else if (hdspm->system_sample_rate > 48000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006163 levels->speed = ds;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006164 } else {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006165 levels->speed = ss;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006166 }
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006167 levels->status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006168
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006169 s = copy_to_user(argp, levels, sizeof(struct hdspm_peak_rms));
Adrian Knoth0dca1792011-01-26 19:32:14 +01006170 if (0 != s) {
6171 /* snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu
6172 [Levels]\n", sizeof(struct hdspm_peak_rms), s);
6173 */
Takashi Iwai763f3562005-06-03 11:25:34 +02006174 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006175 }
6176 break;
6177
6178 case SNDRV_HDSPM_IOCTL_GET_LTC:
6179 ltc.ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
6180 i = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
6181 if (i & HDSPM_TCO1_LTC_Input_valid) {
6182 switch (i & (HDSPM_TCO1_LTC_Format_LSB |
6183 HDSPM_TCO1_LTC_Format_MSB)) {
6184 case 0:
6185 ltc.format = fps_24;
6186 break;
6187 case HDSPM_TCO1_LTC_Format_LSB:
6188 ltc.format = fps_25;
6189 break;
6190 case HDSPM_TCO1_LTC_Format_MSB:
6191 ltc.format = fps_2997;
6192 break;
6193 default:
6194 ltc.format = 30;
6195 break;
6196 }
6197 if (i & HDSPM_TCO1_set_drop_frame_flag) {
6198 ltc.frame = drop_frame;
6199 } else {
6200 ltc.frame = full_frame;
6201 }
6202 } else {
6203 ltc.format = format_invalid;
6204 ltc.frame = frame_invalid;
6205 }
6206 if (i & HDSPM_TCO1_Video_Input_Format_NTSC) {
6207 ltc.input_format = ntsc;
6208 } else if (i & HDSPM_TCO1_Video_Input_Format_PAL) {
6209 ltc.input_format = pal;
6210 } else {
6211 ltc.input_format = no_video;
6212 }
6213
6214 s = copy_to_user(argp, &ltc, sizeof(struct hdspm_ltc));
6215 if (0 != s) {
6216 /*
6217 snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */
Takashi Iwai763f3562005-06-03 11:25:34 +02006218 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006219 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006220
6221 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02006222
Adrian Knoth0dca1792011-01-26 19:32:14 +01006223 case SNDRV_HDSPM_IOCTL_GET_CONFIG:
Takashi Iwai763f3562005-06-03 11:25:34 +02006224
Adrian Knoth4ab69a22011-02-23 11:43:14 +01006225 memset(&info, 0, sizeof(info));
Takashi Iwai763f3562005-06-03 11:25:34 +02006226 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006227 info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
6228 info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006229
6230 info.system_sample_rate = hdspm->system_sample_rate;
6231 info.autosync_sample_rate =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006232 hdspm_external_sample_rate(hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006233 info.system_clock_mode = hdspm_system_clock_mode(hdspm);
6234 info.clock_source = hdspm_clock_source(hdspm);
6235 info.autosync_ref = hdspm_autosync_ref(hdspm);
6236 info.line_out = hdspm_line_out(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006237 info.passthru = 0;
6238 spin_unlock_irq(&hdspm->lock);
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006239 if (copy_to_user(argp, &info, sizeof(info)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006240 return -EFAULT;
6241 break;
6242
Adrian Knoth0dca1792011-01-26 19:32:14 +01006243 case SNDRV_HDSPM_IOCTL_GET_STATUS:
Dan Carpenter643d6bb2011-09-23 09:24:21 +03006244 memset(&status, 0, sizeof(status));
6245
Adrian Knoth0dca1792011-01-26 19:32:14 +01006246 status.card_type = hdspm->io_type;
6247
6248 status.autosync_source = hdspm_autosync_ref(hdspm);
6249
6250 status.card_clock = 110069313433624ULL;
6251 status.master_period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
6252
6253 switch (hdspm->io_type) {
6254 case MADI:
6255 case MADIface:
6256 status.card_specific.madi.sync_wc =
6257 hdspm_wc_sync_check(hdspm);
6258 status.card_specific.madi.sync_madi =
6259 hdspm_madi_sync_check(hdspm);
6260 status.card_specific.madi.sync_tco =
6261 hdspm_tco_sync_check(hdspm);
6262 status.card_specific.madi.sync_in =
6263 hdspm_sync_in_sync_check(hdspm);
6264
6265 statusregister =
6266 hdspm_read(hdspm, HDSPM_statusRegister);
6267 status.card_specific.madi.madi_input =
6268 (statusregister & HDSPM_AB_int) ? 1 : 0;
6269 status.card_specific.madi.channel_format =
Adrian Knoth9e6ff522011-10-27 21:57:52 +02006270 (statusregister & HDSPM_RX_64ch) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006271 /* TODO: Mac driver sets it when f_s>48kHz */
6272 status.card_specific.madi.frame_format = 0;
6273
6274 default:
6275 break;
6276 }
6277
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006278 if (copy_to_user(argp, &status, sizeof(status)))
Adrian Knoth0dca1792011-01-26 19:32:14 +01006279 return -EFAULT;
6280
6281
6282 break;
6283
Takashi Iwai763f3562005-06-03 11:25:34 +02006284 case SNDRV_HDSPM_IOCTL_GET_VERSION:
Dan Carpenter643d6bb2011-09-23 09:24:21 +03006285 memset(&hdspm_version, 0, sizeof(hdspm_version));
6286
Adrian Knoth0dca1792011-01-26 19:32:14 +01006287 hdspm_version.card_type = hdspm->io_type;
6288 strncpy(hdspm_version.cardname, hdspm->card_name,
6289 sizeof(hdspm_version.cardname));
Adrian Knoth7d53a632012-01-04 14:31:16 +01006290 hdspm_version.serial = hdspm->serial;
Takashi Iwai763f3562005-06-03 11:25:34 +02006291 hdspm_version.firmware_rev = hdspm->firmware_rev;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006292 hdspm_version.addons = 0;
6293 if (hdspm->tco)
6294 hdspm_version.addons |= HDSPM_ADDON_TCO;
6295
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006296 if (copy_to_user(argp, &hdspm_version,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006297 sizeof(hdspm_version)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006298 return -EFAULT;
6299 break;
6300
6301 case SNDRV_HDSPM_IOCTL_GET_MIXER:
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006302 if (copy_from_user(&mixer, argp, sizeof(mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006303 return -EFAULT;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006304 if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006305 sizeof(struct hdspm_mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006306 return -EFAULT;
6307 break;
6308
6309 default:
6310 return -EINVAL;
6311 }
6312 return 0;
6313}
6314
Takashi Iwai98274f02005-11-17 14:52:34 +01006315static struct snd_pcm_ops snd_hdspm_playback_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006316 .open = snd_hdspm_playback_open,
6317 .close = snd_hdspm_playback_release,
6318 .ioctl = snd_hdspm_ioctl,
6319 .hw_params = snd_hdspm_hw_params,
6320 .hw_free = snd_hdspm_hw_free,
6321 .prepare = snd_hdspm_prepare,
6322 .trigger = snd_hdspm_trigger,
6323 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006324 .page = snd_pcm_sgbuf_ops_page,
6325};
6326
Takashi Iwai98274f02005-11-17 14:52:34 +01006327static struct snd_pcm_ops snd_hdspm_capture_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006328 .open = snd_hdspm_capture_open,
6329 .close = snd_hdspm_capture_release,
6330 .ioctl = snd_hdspm_ioctl,
6331 .hw_params = snd_hdspm_hw_params,
6332 .hw_free = snd_hdspm_hw_free,
6333 .prepare = snd_hdspm_prepare,
6334 .trigger = snd_hdspm_trigger,
6335 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006336 .page = snd_pcm_sgbuf_ops_page,
6337};
6338
Takashi Iwai98274f02005-11-17 14:52:34 +01006339static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
6340 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006341{
Takashi Iwai98274f02005-11-17 14:52:34 +01006342 struct snd_hwdep *hw;
Takashi Iwai763f3562005-06-03 11:25:34 +02006343 int err;
6344
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006345 err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw);
6346 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006347 return err;
6348
6349 hdspm->hwdep = hw;
6350 hw->private_data = hdspm;
6351 strcpy(hw->name, "HDSPM hwdep interface");
6352
Adrian Knoth0dca1792011-01-26 19:32:14 +01006353 hw->ops.open = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006354 hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
Adrian Knoth8de5d6f2012-03-08 15:38:04 +01006355 hw->ops.ioctl_compat = snd_hdspm_hwdep_ioctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006356 hw->ops.release = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006357
6358 return 0;
6359}
6360
6361
6362/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01006363 memory interface
Takashi Iwai763f3562005-06-03 11:25:34 +02006364 ------------------------------------------------------------*/
Adrian Knoth0dca1792011-01-26 19:32:14 +01006365static int __devinit snd_hdspm_preallocate_memory(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006366{
6367 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01006368 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006369 size_t wanted;
6370
6371 pcm = hdspm->pcm;
6372
Remy Bruno3cee5a62006-10-16 12:46:32 +02006373 wanted = HDSPM_DMA_AREA_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02006374
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006375 err =
Takashi Iwai763f3562005-06-03 11:25:34 +02006376 snd_pcm_lib_preallocate_pages_for_all(pcm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006377 SNDRV_DMA_TYPE_DEV_SG,
Takashi Iwai763f3562005-06-03 11:25:34 +02006378 snd_dma_pci_data(hdspm->pci),
6379 wanted,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006380 wanted);
6381 if (err < 0) {
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006382 snd_printdd("Could not preallocate %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006383
6384 return err;
6385 } else
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006386 snd_printdd(" Preallocated %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006387
6388 return 0;
6389}
6390
Adrian Knoth0dca1792011-01-26 19:32:14 +01006391
6392static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +02006393 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02006394 unsigned int reg, int channels)
6395{
6396 int i;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006397
6398 /* continuous memory segment */
Takashi Iwai763f3562005-06-03 11:25:34 +02006399 for (i = 0; i < (channels * 16); i++)
6400 hdspm_write(hdspm, reg + 4 * i,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006401 snd_pcm_sgbuf_get_addr(substream, 4096 * i));
Takashi Iwai763f3562005-06-03 11:25:34 +02006402}
6403
Adrian Knoth0dca1792011-01-26 19:32:14 +01006404
Takashi Iwai763f3562005-06-03 11:25:34 +02006405/* ------------- ALSA Devices ---------------------------- */
Takashi Iwai98274f02005-11-17 14:52:34 +01006406static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006407 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006408{
Takashi Iwai98274f02005-11-17 14:52:34 +01006409 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006410 int err;
6411
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006412 err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm);
6413 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006414 return err;
6415
6416 hdspm->pcm = pcm;
6417 pcm->private_data = hdspm;
6418 strcpy(pcm->name, hdspm->card_name);
6419
6420 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
6421 &snd_hdspm_playback_ops);
6422 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
6423 &snd_hdspm_capture_ops);
6424
6425 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
6426
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006427 err = snd_hdspm_preallocate_memory(hdspm);
6428 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006429 return err;
6430
6431 return 0;
6432}
6433
Takashi Iwai98274f02005-11-17 14:52:34 +01006434static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006435{
Adrian Knoth7c7102b2011-02-28 15:14:50 +01006436 int i;
6437
6438 for (i = 0; i < hdspm->midiPorts; i++)
6439 snd_hdspm_flush_midi_input(hdspm, i);
Takashi Iwai763f3562005-06-03 11:25:34 +02006440}
6441
Takashi Iwai98274f02005-11-17 14:52:34 +01006442static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
6443 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006444{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006445 int err, i;
Takashi Iwai763f3562005-06-03 11:25:34 +02006446
6447 snd_printdd("Create card...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006448 err = snd_hdspm_create_pcm(card, hdspm);
6449 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006450 return err;
6451
Adrian Knoth0dca1792011-01-26 19:32:14 +01006452 i = 0;
6453 while (i < hdspm->midiPorts) {
6454 err = snd_hdspm_create_midi(card, hdspm, i);
6455 if (err < 0) {
6456 return err;
6457 }
6458 i++;
6459 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006460
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006461 err = snd_hdspm_create_controls(card, hdspm);
6462 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006463 return err;
6464
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006465 err = snd_hdspm_create_hwdep(card, hdspm);
6466 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006467 return err;
6468
6469 snd_printdd("proc init...\n");
6470 snd_hdspm_proc_init(hdspm);
6471
6472 hdspm->system_sample_rate = -1;
6473 hdspm->last_external_sample_rate = -1;
6474 hdspm->last_internal_sample_rate = -1;
6475 hdspm->playback_pid = -1;
6476 hdspm->capture_pid = -1;
6477 hdspm->capture_substream = NULL;
6478 hdspm->playback_substream = NULL;
6479
6480 snd_printdd("Set defaults...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006481 err = snd_hdspm_set_defaults(hdspm);
6482 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006483 return err;
6484
6485 snd_printdd("Update mixer controls...\n");
6486 hdspm_update_simple_mixer_controls(hdspm);
6487
6488 snd_printdd("Initializeing complete ???\n");
6489
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006490 err = snd_card_register(card);
6491 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006492 snd_printk(KERN_ERR "HDSPM: error registering card\n");
6493 return err;
6494 }
6495
6496 snd_printdd("... yes now\n");
6497
6498 return 0;
6499}
6500
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006501static int __devinit snd_hdspm_create(struct snd_card *card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006502 struct hdspm *hdspm) {
6503
Takashi Iwai763f3562005-06-03 11:25:34 +02006504 struct pci_dev *pci = hdspm->pci;
6505 int err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006506 unsigned long io_extent;
6507
6508 hdspm->irq = -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02006509 hdspm->card = card;
6510
6511 spin_lock_init(&hdspm->lock);
6512
Takashi Iwai763f3562005-06-03 11:25:34 +02006513 pci_read_config_word(hdspm->pci,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006514 PCI_CLASS_REVISION, &hdspm->firmware_rev);
Remy Bruno3cee5a62006-10-16 12:46:32 +02006515
Takashi Iwai763f3562005-06-03 11:25:34 +02006516 strcpy(card->mixername, "Xilinx FPGA");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006517 strcpy(card->driver, "HDSPM");
6518
6519 switch (hdspm->firmware_rev) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01006520 case HDSPM_RAYDAT_REV:
6521 hdspm->io_type = RayDAT;
6522 hdspm->card_name = "RME RayDAT";
6523 hdspm->midiPorts = 2;
6524 break;
6525 case HDSPM_AIO_REV:
6526 hdspm->io_type = AIO;
6527 hdspm->card_name = "RME AIO";
6528 hdspm->midiPorts = 1;
6529 break;
6530 case HDSPM_MADIFACE_REV:
6531 hdspm->io_type = MADIface;
6532 hdspm->card_name = "RME MADIface";
6533 hdspm->midiPorts = 1;
6534 break;
Adrian Knoth5027f342011-02-28 15:14:49 +01006535 default:
Adrian Knothc09403d2011-10-27 21:57:54 +02006536 if ((hdspm->firmware_rev == 0xf0) ||
6537 ((hdspm->firmware_rev >= 0xe6) &&
6538 (hdspm->firmware_rev <= 0xea))) {
6539 hdspm->io_type = AES32;
6540 hdspm->card_name = "RME AES32";
6541 hdspm->midiPorts = 2;
Adrian Knoth05c7cc92011-11-21 16:15:36 +01006542 } else if ((hdspm->firmware_rev == 0xd2) ||
Adrian Knothc09403d2011-10-27 21:57:54 +02006543 ((hdspm->firmware_rev >= 0xc8) &&
6544 (hdspm->firmware_rev <= 0xcf))) {
6545 hdspm->io_type = MADI;
6546 hdspm->card_name = "RME MADI";
6547 hdspm->midiPorts = 3;
6548 } else {
6549 snd_printk(KERN_ERR
6550 "HDSPM: unknown firmware revision %x\n",
Adrian Knoth5027f342011-02-28 15:14:49 +01006551 hdspm->firmware_rev);
Adrian Knothc09403d2011-10-27 21:57:54 +02006552 return -ENODEV;
6553 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02006554 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006555
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006556 err = pci_enable_device(pci);
6557 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006558 return err;
6559
6560 pci_set_master(hdspm->pci);
6561
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006562 err = pci_request_regions(pci, "hdspm");
6563 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006564 return err;
6565
6566 hdspm->port = pci_resource_start(pci, 0);
6567 io_extent = pci_resource_len(pci, 0);
6568
6569 snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006570 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006571
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006572 hdspm->iobase = ioremap_nocache(hdspm->port, io_extent);
6573 if (!hdspm->iobase) {
6574 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006575 "unable to remap region 0x%lx-0x%lx\n",
6576 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006577 return -EBUSY;
6578 }
6579 snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006580 (unsigned long)hdspm->iobase, hdspm->port,
6581 hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006582
6583 if (request_irq(pci->irq, snd_hdspm_interrupt,
Takashi Iwai934c2b62011-06-10 16:36:37 +02006584 IRQF_SHARED, KBUILD_MODNAME, hdspm)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006585 snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
6586 return -EBUSY;
6587 }
6588
6589 snd_printdd("use IRQ %d\n", pci->irq);
6590
6591 hdspm->irq = pci->irq;
Takashi Iwai763f3562005-06-03 11:25:34 +02006592
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006593 snd_printdd("kmalloc Mixer memory of %zd Bytes\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006594 sizeof(struct hdspm_mixer));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006595 hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL);
6596 if (!hdspm->mixer) {
6597 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006598 "unable to kmalloc Mixer memory of %d Bytes\n",
6599 (int)sizeof(struct hdspm_mixer));
Julia Lawallb17cbdd2012-08-19 09:02:54 +02006600 return -ENOMEM;
Takashi Iwai763f3562005-06-03 11:25:34 +02006601 }
6602
Adrian Knoth0dca1792011-01-26 19:32:14 +01006603 hdspm->port_names_in = NULL;
6604 hdspm->port_names_out = NULL;
6605
6606 switch (hdspm->io_type) {
6607 case AES32:
Adrian Knothd2d10a22011-02-28 15:14:47 +01006608 hdspm->ss_in_channels = hdspm->ss_out_channels = AES32_CHANNELS;
6609 hdspm->ds_in_channels = hdspm->ds_out_channels = AES32_CHANNELS;
6610 hdspm->qs_in_channels = hdspm->qs_out_channels = AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006611
6612 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6613 channel_map_aes32;
6614 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6615 channel_map_aes32;
6616 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6617 channel_map_aes32;
6618 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6619 texts_ports_aes32;
6620 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6621 texts_ports_aes32;
6622 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6623 texts_ports_aes32;
6624
Adrian Knothd2d10a22011-02-28 15:14:47 +01006625 hdspm->max_channels_out = hdspm->max_channels_in =
6626 AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006627 hdspm->port_names_in = hdspm->port_names_out =
6628 texts_ports_aes32;
6629 hdspm->channel_map_in = hdspm->channel_map_out =
6630 channel_map_aes32;
6631
Adrian Knoth0dca1792011-01-26 19:32:14 +01006632 break;
6633
6634 case MADI:
6635 case MADIface:
6636 hdspm->ss_in_channels = hdspm->ss_out_channels =
6637 MADI_SS_CHANNELS;
6638 hdspm->ds_in_channels = hdspm->ds_out_channels =
6639 MADI_DS_CHANNELS;
6640 hdspm->qs_in_channels = hdspm->qs_out_channels =
6641 MADI_QS_CHANNELS;
6642
6643 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6644 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006645 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006646 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006647 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006648 channel_map_unity_ss;
6649
6650 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6651 texts_ports_madi;
6652 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6653 texts_ports_madi;
6654 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6655 texts_ports_madi;
6656 break;
6657
6658 case AIO:
6659 if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) {
6660 snd_printk(KERN_INFO "HDSPM: AEB input board found, but not supported\n");
6661 }
6662
6663 hdspm->ss_in_channels = AIO_IN_SS_CHANNELS;
6664 hdspm->ds_in_channels = AIO_IN_DS_CHANNELS;
6665 hdspm->qs_in_channels = AIO_IN_QS_CHANNELS;
6666 hdspm->ss_out_channels = AIO_OUT_SS_CHANNELS;
6667 hdspm->ds_out_channels = AIO_OUT_DS_CHANNELS;
6668 hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS;
6669
6670 hdspm->channel_map_out_ss = channel_map_aio_out_ss;
6671 hdspm->channel_map_out_ds = channel_map_aio_out_ds;
6672 hdspm->channel_map_out_qs = channel_map_aio_out_qs;
6673
6674 hdspm->channel_map_in_ss = channel_map_aio_in_ss;
6675 hdspm->channel_map_in_ds = channel_map_aio_in_ds;
6676 hdspm->channel_map_in_qs = channel_map_aio_in_qs;
6677
6678 hdspm->port_names_in_ss = texts_ports_aio_in_ss;
6679 hdspm->port_names_out_ss = texts_ports_aio_out_ss;
6680 hdspm->port_names_in_ds = texts_ports_aio_in_ds;
6681 hdspm->port_names_out_ds = texts_ports_aio_out_ds;
6682 hdspm->port_names_in_qs = texts_ports_aio_in_qs;
6683 hdspm->port_names_out_qs = texts_ports_aio_out_qs;
6684
6685 break;
6686
6687 case RayDAT:
6688 hdspm->ss_in_channels = hdspm->ss_out_channels =
6689 RAYDAT_SS_CHANNELS;
6690 hdspm->ds_in_channels = hdspm->ds_out_channels =
6691 RAYDAT_DS_CHANNELS;
6692 hdspm->qs_in_channels = hdspm->qs_out_channels =
6693 RAYDAT_QS_CHANNELS;
6694
6695 hdspm->max_channels_in = RAYDAT_SS_CHANNELS;
6696 hdspm->max_channels_out = RAYDAT_SS_CHANNELS;
6697
6698 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6699 channel_map_raydat_ss;
6700 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6701 channel_map_raydat_ds;
6702 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6703 channel_map_raydat_qs;
6704 hdspm->channel_map_in = hdspm->channel_map_out =
6705 channel_map_raydat_ss;
6706
6707 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6708 texts_ports_raydat_ss;
6709 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6710 texts_ports_raydat_ds;
6711 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6712 texts_ports_raydat_qs;
6713
6714
6715 break;
6716
6717 }
6718
6719 /* TCO detection */
6720 switch (hdspm->io_type) {
6721 case AIO:
6722 case RayDAT:
6723 if (hdspm_read(hdspm, HDSPM_statusRegister2) &
6724 HDSPM_s2_tco_detect) {
6725 hdspm->midiPorts++;
6726 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6727 GFP_KERNEL);
6728 if (NULL != hdspm->tco) {
6729 hdspm_tco_write(hdspm);
6730 }
6731 snd_printk(KERN_INFO "HDSPM: AIO/RayDAT TCO module found\n");
6732 } else {
6733 hdspm->tco = NULL;
6734 }
6735 break;
6736
6737 case MADI:
6738 if (hdspm_read(hdspm, HDSPM_statusRegister) & HDSPM_tco_detect) {
6739 hdspm->midiPorts++;
6740 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6741 GFP_KERNEL);
6742 if (NULL != hdspm->tco) {
6743 hdspm_tco_write(hdspm);
6744 }
6745 snd_printk(KERN_INFO "HDSPM: MADI TCO module found\n");
6746 } else {
6747 hdspm->tco = NULL;
6748 }
6749 break;
6750
6751 default:
6752 hdspm->tco = NULL;
6753 }
6754
6755 /* texts */
6756 switch (hdspm->io_type) {
6757 case AES32:
6758 if (hdspm->tco) {
6759 hdspm->texts_autosync = texts_autosync_aes_tco;
6760 hdspm->texts_autosync_items = 10;
6761 } else {
6762 hdspm->texts_autosync = texts_autosync_aes;
6763 hdspm->texts_autosync_items = 9;
6764 }
6765 break;
6766
6767 case MADI:
6768 if (hdspm->tco) {
6769 hdspm->texts_autosync = texts_autosync_madi_tco;
6770 hdspm->texts_autosync_items = 4;
6771 } else {
6772 hdspm->texts_autosync = texts_autosync_madi;
6773 hdspm->texts_autosync_items = 3;
6774 }
6775 break;
6776
6777 case MADIface:
6778
6779 break;
6780
6781 case RayDAT:
6782 if (hdspm->tco) {
6783 hdspm->texts_autosync = texts_autosync_raydat_tco;
6784 hdspm->texts_autosync_items = 9;
6785 } else {
6786 hdspm->texts_autosync = texts_autosync_raydat;
6787 hdspm->texts_autosync_items = 8;
6788 }
6789 break;
6790
6791 case AIO:
6792 if (hdspm->tco) {
6793 hdspm->texts_autosync = texts_autosync_aio_tco;
6794 hdspm->texts_autosync_items = 6;
6795 } else {
6796 hdspm->texts_autosync = texts_autosync_aio;
6797 hdspm->texts_autosync_items = 5;
6798 }
6799 break;
6800
6801 }
6802
6803 tasklet_init(&hdspm->midi_tasklet,
6804 hdspm_midi_tasklet, (unsigned long) hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006805
Adrian Knothf7de8ba2012-01-10 20:58:40 +01006806
6807 if (hdspm->io_type != MADIface) {
6808 hdspm->serial = (hdspm_read(hdspm,
6809 HDSPM_midiStatusIn0)>>8) & 0xFFFFFF;
6810 /* id contains either a user-provided value or the default
6811 * NULL. If it's the default, we're safe to
6812 * fill card->id with the serial number.
6813 *
6814 * If the serial number is 0xFFFFFF, then we're dealing with
6815 * an old PCI revision that comes without a sane number. In
6816 * this case, we don't set card->id to avoid collisions
6817 * when running with multiple cards.
6818 */
6819 if (NULL == id[hdspm->dev] && hdspm->serial != 0xFFFFFF) {
6820 sprintf(card->id, "HDSPMx%06x", hdspm->serial);
6821 snd_card_set_id(card, card->id);
6822 }
6823 }
6824
Takashi Iwai763f3562005-06-03 11:25:34 +02006825 snd_printdd("create alsa devices.\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006826 err = snd_hdspm_create_alsa_devices(card, hdspm);
6827 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006828 return err;
6829
6830 snd_hdspm_initialize_midi_flush(hdspm);
6831
6832 return 0;
6833}
6834
Adrian Knoth0dca1792011-01-26 19:32:14 +01006835
Takashi Iwai98274f02005-11-17 14:52:34 +01006836static int snd_hdspm_free(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006837{
6838
6839 if (hdspm->port) {
6840
6841 /* stop th audio, and cancel all interrupts */
6842 hdspm->control_register &=
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006843 ~(HDSPM_Start | HDSPM_AudioInterruptEnable |
Adrian Knoth0dca1792011-01-26 19:32:14 +01006844 HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable |
6845 HDSPM_Midi2InterruptEnable | HDSPM_Midi3InterruptEnable);
Takashi Iwai763f3562005-06-03 11:25:34 +02006846 hdspm_write(hdspm, HDSPM_controlRegister,
6847 hdspm->control_register);
6848 }
6849
6850 if (hdspm->irq >= 0)
6851 free_irq(hdspm->irq, (void *) hdspm);
6852
Jesper Juhlfc584222005-10-24 15:11:28 +02006853 kfree(hdspm->mixer);
Takashi Iwai763f3562005-06-03 11:25:34 +02006854
6855 if (hdspm->iobase)
6856 iounmap(hdspm->iobase);
6857
Takashi Iwai763f3562005-06-03 11:25:34 +02006858 if (hdspm->port)
6859 pci_release_regions(hdspm->pci);
6860
6861 pci_disable_device(hdspm->pci);
6862 return 0;
6863}
6864
Adrian Knoth0dca1792011-01-26 19:32:14 +01006865
Takashi Iwai98274f02005-11-17 14:52:34 +01006866static void snd_hdspm_card_free(struct snd_card *card)
Takashi Iwai763f3562005-06-03 11:25:34 +02006867{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006868 struct hdspm *hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006869
6870 if (hdspm)
6871 snd_hdspm_free(hdspm);
6872}
6873
Adrian Knoth0dca1792011-01-26 19:32:14 +01006874
Takashi Iwai763f3562005-06-03 11:25:34 +02006875static int __devinit snd_hdspm_probe(struct pci_dev *pci,
6876 const struct pci_device_id *pci_id)
6877{
6878 static int dev;
Takashi Iwai98274f02005-11-17 14:52:34 +01006879 struct hdspm *hdspm;
6880 struct snd_card *card;
Takashi Iwai763f3562005-06-03 11:25:34 +02006881 int err;
6882
6883 if (dev >= SNDRV_CARDS)
6884 return -ENODEV;
6885 if (!enable[dev]) {
6886 dev++;
6887 return -ENOENT;
6888 }
6889
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006890 err = snd_card_create(index[dev], id[dev],
Adrian Knoth0dca1792011-01-26 19:32:14 +01006891 THIS_MODULE, sizeof(struct hdspm), &card);
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006892 if (err < 0)
6893 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006894
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006895 hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006896 card->private_free = snd_hdspm_card_free;
6897 hdspm->dev = dev;
6898 hdspm->pci = pci;
6899
Takashi Iwaic187c042007-02-19 15:27:33 +01006900 snd_card_set_dev(card, &pci->dev);
6901
Adrian Knoth0dca1792011-01-26 19:32:14 +01006902 err = snd_hdspm_create(card, hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006903 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006904 snd_card_free(card);
6905 return err;
6906 }
6907
Adrian Knoth0dca1792011-01-26 19:32:14 +01006908 if (hdspm->io_type != MADIface) {
6909 sprintf(card->shortname, "%s_%x",
6910 hdspm->card_name,
Adrian Knoth7d53a632012-01-04 14:31:16 +01006911 hdspm->serial);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006912 sprintf(card->longname, "%s S/N 0x%x at 0x%lx, irq %d",
6913 hdspm->card_name,
Adrian Knoth7d53a632012-01-04 14:31:16 +01006914 hdspm->serial,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006915 hdspm->port, hdspm->irq);
6916 } else {
6917 sprintf(card->shortname, "%s", hdspm->card_name);
6918 sprintf(card->longname, "%s at 0x%lx, irq %d",
6919 hdspm->card_name, hdspm->port, hdspm->irq);
6920 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006921
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006922 err = snd_card_register(card);
6923 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006924 snd_card_free(card);
6925 return err;
6926 }
6927
6928 pci_set_drvdata(pci, card);
6929
6930 dev++;
6931 return 0;
6932}
6933
6934static void __devexit snd_hdspm_remove(struct pci_dev *pci)
6935{
6936 snd_card_free(pci_get_drvdata(pci));
6937 pci_set_drvdata(pci, NULL);
6938}
6939
Takashi Iwaie9f66d92012-04-24 12:25:00 +02006940static struct pci_driver hdspm_driver = {
Takashi Iwai3733e422011-06-10 16:20:20 +02006941 .name = KBUILD_MODNAME,
Takashi Iwai763f3562005-06-03 11:25:34 +02006942 .id_table = snd_hdspm_ids,
6943 .probe = snd_hdspm_probe,
6944 .remove = __devexit_p(snd_hdspm_remove),
6945};
6946
Takashi Iwaie9f66d92012-04-24 12:25:00 +02006947module_pci_driver(hdspm_driver);