blob: 2db871d9a007d3659e3c09dcffcb42945064d400 [file] [log] [blame]
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001/*
Takashi Iwai763f3562005-06-03 11:25:34 +02002 * ALSA driver for RME Hammerfall DSP MADI audio interface(s)
3 *
4 * Copyright (c) 2003 Winfried Ritsch (IEM)
5 * code based on hdsp.c Paul Davis
6 * Marcus Andersson
7 * Thomas Charbonnel
Remy Bruno3cee5a62006-10-16 12:46:32 +02008 * Modified 2006-06-01 for AES32 support by Remy Bruno
9 * <remy.bruno@trinnov.com>
Takashi Iwai763f3562005-06-03 11:25:34 +020010 *
Adrian Knoth0dca1792011-01-26 19:32:14 +010011 * Modified 2009-04-13 for proper metering by Florian Faber
12 * <faber@faberman.de>
13 *
14 * Modified 2009-04-14 for native float support by Florian Faber
15 * <faber@faberman.de>
16 *
17 * Modified 2009-04-26 fixed bug in rms metering by Florian Faber
18 * <faber@faberman.de>
19 *
20 * Modified 2009-04-30 added hw serial number support by Florian Faber
21 *
22 * Modified 2011-01-14 added S/PDIF input on RayDATs by Adrian Knoth
23 *
24 * Modified 2011-01-25 variable period sizes on RayDAT/AIO by Adrian Knoth
25 *
Takashi Iwai763f3562005-06-03 11:25:34 +020026 * This program is free software; you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License as published by
28 * the Free Software Foundation; either version 2 of the License, or
29 * (at your option) any later version.
30 *
31 * This program is distributed in the hope that it will be useful,
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 * GNU General Public License for more details.
35 *
36 * You should have received a copy of the GNU General Public License
37 * along with this program; if not, write to the Free Software
38 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 *
40 */
Takashi Iwai763f3562005-06-03 11:25:34 +020041#include <linux/init.h>
42#include <linux/delay.h>
43#include <linux/interrupt.h>
44#include <linux/moduleparam.h>
45#include <linux/slab.h>
46#include <linux/pci.h>
Takashi Iwai3f7440a2009-06-05 17:40:04 +020047#include <linux/math64.h>
Takashi Iwai763f3562005-06-03 11:25:34 +020048#include <asm/io.h>
49
50#include <sound/core.h>
51#include <sound/control.h>
52#include <sound/pcm.h>
Adrian Knoth0dca1792011-01-26 19:32:14 +010053#include <sound/pcm_params.h>
Takashi Iwai763f3562005-06-03 11:25:34 +020054#include <sound/info.h>
55#include <sound/asoundef.h>
56#include <sound/rawmidi.h>
57#include <sound/hwdep.h>
58#include <sound/initval.h>
59
60#include <sound/hdspm.h>
61
62static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
63static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
64static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
65
Takashi Iwai763f3562005-06-03 11:25:34 +020066module_param_array(index, int, NULL, 0444);
67MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");
68
69module_param_array(id, charp, NULL, 0444);
70MODULE_PARM_DESC(id, "ID string for RME HDSPM interface.");
71
72module_param_array(enable, bool, NULL, 0444);
73MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");
74
Takashi Iwai763f3562005-06-03 11:25:34 +020075
76MODULE_AUTHOR
Adrian Knoth0dca1792011-01-26 19:32:14 +010077(
78 "Winfried Ritsch <ritsch_AT_iem.at>, "
79 "Paul Davis <paul@linuxaudiosystems.com>, "
80 "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, "
81 "Remy Bruno <remy.bruno@trinnov.com>, "
82 "Florian Faber <faberman@linuxproaudio.org>, "
83 "Adrian Knoth <adi@drcomp.erfurt.thur.de>"
84);
Takashi Iwai763f3562005-06-03 11:25:34 +020085MODULE_DESCRIPTION("RME HDSPM");
86MODULE_LICENSE("GPL");
87MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
88
Adrian Knoth0dca1792011-01-26 19:32:14 +010089/* --- Write registers. ---
Takashi Iwai763f3562005-06-03 11:25:34 +020090 These are defined as byte-offsets from the iobase value. */
91
Adrian Knoth0dca1792011-01-26 19:32:14 +010092#define HDSPM_WR_SETTINGS 0
93#define HDSPM_outputBufferAddress 32
94#define HDSPM_inputBufferAddress 36
Takashi Iwai763f3562005-06-03 11:25:34 +020095#define HDSPM_controlRegister 64
96#define HDSPM_interruptConfirmation 96
97#define HDSPM_control2Reg 256 /* not in specs ???????? */
Remy Brunoffb2c3c2007-03-07 19:08:46 +010098#define HDSPM_freqReg 256 /* for AES32 */
Adrian Knoth0dca1792011-01-26 19:32:14 +010099#define HDSPM_midiDataOut0 352 /* just believe in old code */
100#define HDSPM_midiDataOut1 356
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100101#define HDSPM_eeprom_wr 384 /* for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200102
103/* DMA enable for 64 channels, only Bit 0 is relevant */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100104#define HDSPM_outputEnableBase 512 /* 512-767 input DMA */
Takashi Iwai763f3562005-06-03 11:25:34 +0200105#define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */
106
Adrian Knoth0dca1792011-01-26 19:32:14 +0100107/* 16 page addresses for each of the 64 channels DMA buffer in and out
Takashi Iwai763f3562005-06-03 11:25:34 +0200108 (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */
109#define HDSPM_pageAddressBufferOut 8192
110#define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4)
111
112#define HDSPM_MADI_mixerBase 32768 /* 32768-65535 for 2x64x64 Fader */
113
114#define HDSPM_MATRIX_MIXER_SIZE 8192 /* = 2*64*64 * 4 Byte => 32kB */
115
116/* --- Read registers. ---
117 These are defined as byte-offsets from the iobase value */
118#define HDSPM_statusRegister 0
Remy Bruno3cee5a62006-10-16 12:46:32 +0200119/*#define HDSPM_statusRegister2 96 */
120/* after RME Windows driver sources, status2 is 4-byte word # 48 = word at
121 * offset 192, for AES32 *and* MADI
122 * => need to check that offset 192 is working on MADI */
123#define HDSPM_statusRegister2 192
124#define HDSPM_timecodeRegister 128
Takashi Iwai763f3562005-06-03 11:25:34 +0200125
Adrian Knoth0dca1792011-01-26 19:32:14 +0100126/* AIO, RayDAT */
127#define HDSPM_RD_STATUS_0 0
128#define HDSPM_RD_STATUS_1 64
129#define HDSPM_RD_STATUS_2 128
130#define HDSPM_RD_STATUS_3 192
131
132#define HDSPM_RD_TCO 256
133#define HDSPM_RD_PLL_FREQ 512
134#define HDSPM_WR_TCO 128
135
136#define HDSPM_TCO1_TCO_lock 0x00000001
137#define HDSPM_TCO1_WCK_Input_Range_LSB 0x00000002
138#define HDSPM_TCO1_WCK_Input_Range_MSB 0x00000004
139#define HDSPM_TCO1_LTC_Input_valid 0x00000008
140#define HDSPM_TCO1_WCK_Input_valid 0x00000010
141#define HDSPM_TCO1_Video_Input_Format_NTSC 0x00000020
142#define HDSPM_TCO1_Video_Input_Format_PAL 0x00000040
143
144#define HDSPM_TCO1_set_TC 0x00000100
145#define HDSPM_TCO1_set_drop_frame_flag 0x00000200
146#define HDSPM_TCO1_LTC_Format_LSB 0x00000400
147#define HDSPM_TCO1_LTC_Format_MSB 0x00000800
148
149#define HDSPM_TCO2_TC_run 0x00010000
150#define HDSPM_TCO2_WCK_IO_ratio_LSB 0x00020000
151#define HDSPM_TCO2_WCK_IO_ratio_MSB 0x00040000
152#define HDSPM_TCO2_set_num_drop_frames_LSB 0x00080000
153#define HDSPM_TCO2_set_num_drop_frames_MSB 0x00100000
154#define HDSPM_TCO2_set_jam_sync 0x00200000
155#define HDSPM_TCO2_set_flywheel 0x00400000
156
157#define HDSPM_TCO2_set_01_4 0x01000000
158#define HDSPM_TCO2_set_pull_down 0x02000000
159#define HDSPM_TCO2_set_pull_up 0x04000000
160#define HDSPM_TCO2_set_freq 0x08000000
161#define HDSPM_TCO2_set_term_75R 0x10000000
162#define HDSPM_TCO2_set_input_LSB 0x20000000
163#define HDSPM_TCO2_set_input_MSB 0x40000000
164#define HDSPM_TCO2_set_freq_from_app 0x80000000
165
166
167#define HDSPM_midiDataOut0 352
168#define HDSPM_midiDataOut1 356
169#define HDSPM_midiDataOut2 368
170
Takashi Iwai763f3562005-06-03 11:25:34 +0200171#define HDSPM_midiDataIn0 360
172#define HDSPM_midiDataIn1 364
Adrian Knoth0dca1792011-01-26 19:32:14 +0100173#define HDSPM_midiDataIn2 372
174#define HDSPM_midiDataIn3 376
Takashi Iwai763f3562005-06-03 11:25:34 +0200175
176/* status is data bytes in MIDI-FIFO (0-128) */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100177#define HDSPM_midiStatusOut0 384
178#define HDSPM_midiStatusOut1 388
179#define HDSPM_midiStatusOut2 400
180
181#define HDSPM_midiStatusIn0 392
182#define HDSPM_midiStatusIn1 396
183#define HDSPM_midiStatusIn2 404
184#define HDSPM_midiStatusIn3 408
Takashi Iwai763f3562005-06-03 11:25:34 +0200185
186
187/* the meters are regular i/o-mapped registers, but offset
188 considerably from the rest. the peak registers are reset
Adrian Knoth0dca1792011-01-26 19:32:14 +0100189 when read; the least-significant 4 bits are full-scale counters;
Takashi Iwai763f3562005-06-03 11:25:34 +0200190 the actual peak value is in the most-significant 24 bits.
191*/
Adrian Knoth0dca1792011-01-26 19:32:14 +0100192
193#define HDSPM_MADI_INPUT_PEAK 4096
194#define HDSPM_MADI_PLAYBACK_PEAK 4352
195#define HDSPM_MADI_OUTPUT_PEAK 4608
196
197#define HDSPM_MADI_INPUT_RMS_L 6144
198#define HDSPM_MADI_PLAYBACK_RMS_L 6400
199#define HDSPM_MADI_OUTPUT_RMS_L 6656
200
201#define HDSPM_MADI_INPUT_RMS_H 7168
202#define HDSPM_MADI_PLAYBACK_RMS_H 7424
203#define HDSPM_MADI_OUTPUT_RMS_H 7680
Takashi Iwai763f3562005-06-03 11:25:34 +0200204
205/* --- Control Register bits --------- */
206#define HDSPM_Start (1<<0) /* start engine */
207
208#define HDSPM_Latency0 (1<<1) /* buffer size = 2^n */
209#define HDSPM_Latency1 (1<<2) /* where n is defined */
210#define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */
211
Adrian Knoth0dca1792011-01-26 19:32:14 +0100212#define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Autosync */
213#define HDSPM_c0Master 0x1 /* Master clock bit in settings
214 register [RayDAT, AIO] */
Takashi Iwai763f3562005-06-03 11:25:34 +0200215
216#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */
217
218#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */
219#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */
220#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200221#define HDSPM_QuadSpeed (1<<31) /* quad speed bit */
Takashi Iwai763f3562005-06-03 11:25:34 +0200222
Remy Bruno3cee5a62006-10-16 12:46:32 +0200223#define HDSPM_Professional (1<<9) /* Professional */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200224#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200225 56channelMODE=0 */ /* MADI ONLY*/
226#define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200227
Adrian Knoth0dca1792011-01-26 19:32:14 +0100228#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200229 0=off, 1=on */ /* MADI ONLY */
230#define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200231
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200232#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax
233 * -- MADI ONLY
234 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200235#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
236
Remy Bruno3cee5a62006-10-16 12:46:32 +0200237#define HDSPM_SyncRef2 (1<<13)
238#define HDSPM_SyncRef3 (1<<25)
Takashi Iwai763f3562005-06-03 11:25:34 +0200239
Remy Bruno3cee5a62006-10-16 12:46:32 +0200240#define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100241#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use
Takashi Iwai763f3562005-06-03 11:25:34 +0200242 AES additional bits in
243 lower 5 Audiodatabits ??? */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200244#define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */
245#define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200246
Adrian Knoth0dca1792011-01-26 19:32:14 +0100247#define HDSPM_Midi0InterruptEnable 0x0400000
248#define HDSPM_Midi1InterruptEnable 0x0800000
249#define HDSPM_Midi2InterruptEnable 0x0200000
250#define HDSPM_Midi3InterruptEnable 0x4000000
Takashi Iwai763f3562005-06-03 11:25:34 +0200251
252#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100253#define HDSPe_FLOAT_FORMAT 0x2000000
Takashi Iwai763f3562005-06-03 11:25:34 +0200254
Remy Bruno3cee5a62006-10-16 12:46:32 +0200255#define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */
256#define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */
257#define HDSPM_QS_QuadWire (1<<28) /* AES32 ONLY */
258
259#define HDSPM_wclk_sel (1<<30)
Takashi Iwai763f3562005-06-03 11:25:34 +0200260
261/* --- bit helper defines */
262#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200263#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|\
264 HDSPM_DoubleSpeed|HDSPM_QuadSpeed)
Takashi Iwai763f3562005-06-03 11:25:34 +0200265#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1)
266#define HDSPM_InputOptical 0
267#define HDSPM_InputCoaxial (HDSPM_InputSelect0)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200268#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\
269 HDSPM_SyncRef2|HDSPM_SyncRef3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200270
Adrian Knoth0dca1792011-01-26 19:32:14 +0100271#define HDSPM_c0_SyncRef0 0x2
272#define HDSPM_c0_SyncRef1 0x4
273#define HDSPM_c0_SyncRef2 0x8
274#define HDSPM_c0_SyncRef3 0x10
275#define HDSPM_c0_SyncRefMask (HDSPM_c0_SyncRef0 | HDSPM_c0_SyncRef1 |\
276 HDSPM_c0_SyncRef2 | HDSPM_c0_SyncRef3)
277
278#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */
279#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */
280#define HDSPM_SYNC_FROM_TCO 2
281#define HDSPM_SYNC_FROM_SYNC_IN 3
Takashi Iwai763f3562005-06-03 11:25:34 +0200282
283#define HDSPM_Frequency32KHz HDSPM_Frequency0
284#define HDSPM_Frequency44_1KHz HDSPM_Frequency1
285#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0)
286#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0)
287#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200288#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|\
289 HDSPM_Frequency0)
Remy Bruno3cee5a62006-10-16 12:46:32 +0200290#define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0)
291#define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200292#define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\
293 HDSPM_Frequency0)
Takashi Iwai763f3562005-06-03 11:25:34 +0200294
Takashi Iwai763f3562005-06-03 11:25:34 +0200295
296/* Synccheck Status */
297#define HDSPM_SYNC_CHECK_NO_LOCK 0
298#define HDSPM_SYNC_CHECK_LOCK 1
299#define HDSPM_SYNC_CHECK_SYNC 2
300
301/* AutoSync References - used by "autosync_ref" control switch */
302#define HDSPM_AUTOSYNC_FROM_WORD 0
303#define HDSPM_AUTOSYNC_FROM_MADI 1
Adrian Knoth0dca1792011-01-26 19:32:14 +0100304#define HDSPM_AUTOSYNC_FROM_TCO 2
305#define HDSPM_AUTOSYNC_FROM_SYNC_IN 3
306#define HDSPM_AUTOSYNC_FROM_NONE 4
Takashi Iwai763f3562005-06-03 11:25:34 +0200307
308/* Possible sources of MADI input */
309#define HDSPM_OPTICAL 0 /* optical */
310#define HDSPM_COAXIAL 1 /* BNC */
311
312#define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask)
Adrian Knoth0dca1792011-01-26 19:32:14 +0100313#define hdspm_decode_latency(x) ((((x) & HDSPM_LatencyMask)>>1))
Takashi Iwai763f3562005-06-03 11:25:34 +0200314
315#define hdspm_encode_in(x) (((x)&0x3)<<14)
316#define hdspm_decode_in(x) (((x)>>14)&0x3)
317
318/* --- control2 register bits --- */
319#define HDSPM_TMS (1<<0)
320#define HDSPM_TCK (1<<1)
321#define HDSPM_TDI (1<<2)
322#define HDSPM_JTAG (1<<3)
323#define HDSPM_PWDN (1<<4)
324#define HDSPM_PROGRAM (1<<5)
325#define HDSPM_CONFIG_MODE_0 (1<<6)
326#define HDSPM_CONFIG_MODE_1 (1<<7)
327/*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/
328#define HDSPM_BIGENDIAN_MODE (1<<9)
329#define HDSPM_RD_MULTIPLE (1<<10)
330
Remy Bruno3cee5a62006-10-16 12:46:32 +0200331/* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200332 that do not conflict with specific bits for AES32 seem to be valid also
333 for the AES32
334 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200335#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200336#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn MODE=0 */
337#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1
338 * (like inp0)
339 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100340
Takashi Iwai763f3562005-06-03 11:25:34 +0200341#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100342#define HDSPM_madiSync (1<<18) /* MADI is in sync */
343
344#define HDSPM_tcoLock 0x00000020 /* Optional TCO locked status FOR HDSPe MADI! */
345#define HDSPM_tcoSync 0x10000000 /* Optional TCO sync status */
346
347#define HDSPM_syncInLock 0x00010000 /* Sync In lock status FOR HDSPe MADI! */
348#define HDSPM_syncInSync 0x00020000 /* Sync In sync status FOR HDSPe MADI! */
Takashi Iwai763f3562005-06-03 11:25:34 +0200349
350#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100351 /* since 64byte accurate, last 6 bits are not used */
Takashi Iwai763f3562005-06-03 11:25:34 +0200352
Adrian Knoth0dca1792011-01-26 19:32:14 +0100353
354
Takashi Iwai763f3562005-06-03 11:25:34 +0200355#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */
356
357#define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */
358#define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */
359#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */
360#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */
361
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200362#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with
363 * Interrupt
364 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100365#define HDSPM_tco_detect 0x08000000
366#define HDSPM_tco_lock 0x20000000
367
368#define HDSPM_s2_tco_detect 0x00000040
369#define HDSPM_s2_AEBO_D 0x00000080
370#define HDSPM_s2_AEBI_D 0x00000100
371
372
373#define HDSPM_midi0IRQPending 0x40000000
374#define HDSPM_midi1IRQPending 0x80000000
375#define HDSPM_midi2IRQPending 0x20000000
376#define HDSPM_midi2IRQPendingAES 0x00000020
377#define HDSPM_midi3IRQPending 0x00200000
Takashi Iwai763f3562005-06-03 11:25:34 +0200378
379/* --- status bit helpers */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200380#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\
381 HDSPM_madiFreq2|HDSPM_madiFreq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200382#define HDSPM_madiFreq32 (HDSPM_madiFreq0)
383#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1)
384#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1)
385#define HDSPM_madiFreq64 (HDSPM_madiFreq2)
386#define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2)
387#define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2)
388#define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2)
389#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
390#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0)
391
Remy Bruno3cee5a62006-10-16 12:46:32 +0200392/* Status2 Register bits */ /* MADI ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200393
394#define HDSPM_version0 (1<<0) /* not realy defined but I guess */
395#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
Takashi Iwai763f3562005-06-03 11:25:34 +0200509/* the size of a substream (1 mono data stream) */
510#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024)
511#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
512
513/* the size of the area we need to allocate for DMA transfers. the
514 size is the same regardless of the number of channels, and
Adrian Knoth0dca1792011-01-26 19:32:14 +0100515 also the latency to use.
Takashi Iwai763f3562005-06-03 11:25:34 +0200516 for one direction !!!
517*/
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100518#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
Takashi Iwai763f3562005-06-03 11:25:34 +0200519#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
520
Remy Bruno3cee5a62006-10-16 12:46:32 +0200521/* revisions >= 230 indicate AES32 card */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100522#define HDSPM_MADI_REV 210
523#define HDSPM_RAYDAT_REV 211
524#define HDSPM_AIO_REV 212
525#define HDSPM_MADIFACE_REV 213
526#define HDSPM_AES_REV 240
Remy Bruno3cee5a62006-10-16 12:46:32 +0200527
Remy Bruno65345992007-08-31 12:21:08 +0200528/* speed factor modes */
529#define HDSPM_SPEED_SINGLE 0
530#define HDSPM_SPEED_DOUBLE 1
531#define HDSPM_SPEED_QUAD 2
Adrian Knoth0dca1792011-01-26 19:32:14 +0100532
Remy Bruno65345992007-08-31 12:21:08 +0200533/* names for speed modes */
534static char *hdspm_speed_names[] = { "single", "double", "quad" };
535
Adrian Knoth0dca1792011-01-26 19:32:14 +0100536static char *texts_autosync_aes_tco[] = { "Word Clock",
537 "AES1", "AES2", "AES3", "AES4",
538 "AES5", "AES6", "AES7", "AES8",
539 "TCO" };
540static char *texts_autosync_aes[] = { "Word Clock",
541 "AES1", "AES2", "AES3", "AES4",
542 "AES5", "AES6", "AES7", "AES8" };
543static char *texts_autosync_madi_tco[] = { "Word Clock",
544 "MADI", "TCO", "Sync In" };
545static char *texts_autosync_madi[] = { "Word Clock",
546 "MADI", "Sync In" };
547
548static char *texts_autosync_raydat_tco[] = {
549 "Word Clock",
550 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
551 "AES", "SPDIF", "TCO", "Sync In"
552};
553static char *texts_autosync_raydat[] = {
554 "Word Clock",
555 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
556 "AES", "SPDIF", "Sync In"
557};
558static char *texts_autosync_aio_tco[] = {
559 "Word Clock",
560 "ADAT", "AES", "SPDIF", "TCO", "Sync In"
561};
562static char *texts_autosync_aio[] = { "Word Clock",
563 "ADAT", "AES", "SPDIF", "Sync In" };
564
565static char *texts_freq[] = {
566 "No Lock",
567 "32 kHz",
568 "44.1 kHz",
569 "48 kHz",
570 "64 kHz",
571 "88.2 kHz",
572 "96 kHz",
573 "128 kHz",
574 "176.4 kHz",
575 "192 kHz"
576};
577
578static char *texts_sync_status[] = {
579 "no lock",
580 "lock",
581 "sync"
582};
583
584static char *texts_ports_madi[] = {
585 "MADI.1", "MADI.2", "MADI.3", "MADI.4", "MADI.5", "MADI.6",
586 "MADI.7", "MADI.8", "MADI.9", "MADI.10", "MADI.11", "MADI.12",
587 "MADI.13", "MADI.14", "MADI.15", "MADI.16", "MADI.17", "MADI.18",
588 "MADI.19", "MADI.20", "MADI.21", "MADI.22", "MADI.23", "MADI.24",
589 "MADI.25", "MADI.26", "MADI.27", "MADI.28", "MADI.29", "MADI.30",
590 "MADI.31", "MADI.32", "MADI.33", "MADI.34", "MADI.35", "MADI.36",
591 "MADI.37", "MADI.38", "MADI.39", "MADI.40", "MADI.41", "MADI.42",
592 "MADI.43", "MADI.44", "MADI.45", "MADI.46", "MADI.47", "MADI.48",
593 "MADI.49", "MADI.50", "MADI.51", "MADI.52", "MADI.53", "MADI.54",
594 "MADI.55", "MADI.56", "MADI.57", "MADI.58", "MADI.59", "MADI.60",
595 "MADI.61", "MADI.62", "MADI.63", "MADI.64",
596};
597
598
599static char *texts_ports_raydat_ss[] = {
600 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT1.5", "ADAT1.6",
601 "ADAT1.7", "ADAT1.8", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
602 "ADAT2.5", "ADAT2.6", "ADAT2.7", "ADAT2.8", "ADAT3.1", "ADAT3.2",
603 "ADAT3.3", "ADAT3.4", "ADAT3.5", "ADAT3.6", "ADAT3.7", "ADAT3.8",
604 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4", "ADAT4.5", "ADAT4.6",
605 "ADAT4.7", "ADAT4.8",
606 "AES.L", "AES.R",
607 "SPDIF.L", "SPDIF.R"
608};
609
610static char *texts_ports_raydat_ds[] = {
611 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4",
612 "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
613 "ADAT3.1", "ADAT3.2", "ADAT3.3", "ADAT3.4",
614 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4",
615 "AES.L", "AES.R",
616 "SPDIF.L", "SPDIF.R"
617};
618
619static char *texts_ports_raydat_qs[] = {
620 "ADAT1.1", "ADAT1.2",
621 "ADAT2.1", "ADAT2.2",
622 "ADAT3.1", "ADAT3.2",
623 "ADAT4.1", "ADAT4.2",
624 "AES.L", "AES.R",
625 "SPDIF.L", "SPDIF.R"
626};
627
628
629static char *texts_ports_aio_in_ss[] = {
630 "Analogue.L", "Analogue.R",
631 "AES.L", "AES.R",
632 "SPDIF.L", "SPDIF.R",
633 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
634 "ADAT.7", "ADAT.8"
635};
636
637static char *texts_ports_aio_out_ss[] = {
638 "Analogue.L", "Analogue.R",
639 "AES.L", "AES.R",
640 "SPDIF.L", "SPDIF.R",
641 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
642 "ADAT.7", "ADAT.8",
643 "Phone.L", "Phone.R"
644};
645
646static char *texts_ports_aio_in_ds[] = {
647 "Analogue.L", "Analogue.R",
648 "AES.L", "AES.R",
649 "SPDIF.L", "SPDIF.R",
650 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
651};
652
653static char *texts_ports_aio_out_ds[] = {
654 "Analogue.L", "Analogue.R",
655 "AES.L", "AES.R",
656 "SPDIF.L", "SPDIF.R",
657 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
658 "Phone.L", "Phone.R"
659};
660
661static char *texts_ports_aio_in_qs[] = {
662 "Analogue.L", "Analogue.R",
663 "AES.L", "AES.R",
664 "SPDIF.L", "SPDIF.R",
665 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
666};
667
668static char *texts_ports_aio_out_qs[] = {
669 "Analogue.L", "Analogue.R",
670 "AES.L", "AES.R",
671 "SPDIF.L", "SPDIF.R",
672 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
673 "Phone.L", "Phone.R"
674};
675
Takashi Iwai98274f02005-11-17 14:52:34 +0100676struct hdspm_midi {
677 struct hdspm *hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +0200678 int id;
Takashi Iwai98274f02005-11-17 14:52:34 +0100679 struct snd_rawmidi *rmidi;
680 struct snd_rawmidi_substream *input;
681 struct snd_rawmidi_substream *output;
Takashi Iwai763f3562005-06-03 11:25:34 +0200682 char istimer; /* timer in use */
683 struct timer_list timer;
684 spinlock_t lock;
685 int pending;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100686 int dataIn;
687 int statusIn;
688 int dataOut;
689 int statusOut;
690 int ie;
691 int irq;
692};
693
694struct hdspm_tco {
695 int input;
696 int framerate;
697 int wordclock;
698 int samplerate;
699 int pull;
700 int term; /* 0 = off, 1 = on */
Takashi Iwai763f3562005-06-03 11:25:34 +0200701};
702
Takashi Iwai98274f02005-11-17 14:52:34 +0100703struct hdspm {
Takashi Iwai763f3562005-06-03 11:25:34 +0200704 spinlock_t lock;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200705 /* only one playback and/or capture stream */
706 struct snd_pcm_substream *capture_substream;
707 struct snd_pcm_substream *playback_substream;
Takashi Iwai763f3562005-06-03 11:25:34 +0200708
709 char *card_name; /* for procinfo */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200710 unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
711
Adrian Knoth0dca1792011-01-26 19:32:14 +0100712 uint8_t io_type;
Takashi Iwai763f3562005-06-03 11:25:34 +0200713
Takashi Iwai763f3562005-06-03 11:25:34 +0200714 int monitor_outs; /* set up monitoring outs init flag */
715
716 u32 control_register; /* cached value */
717 u32 control2_register; /* cached value */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100718 u32 settings_register;
Takashi Iwai763f3562005-06-03 11:25:34 +0200719
Adrian Knoth0dca1792011-01-26 19:32:14 +0100720 struct hdspm_midi midi[4];
Takashi Iwai763f3562005-06-03 11:25:34 +0200721 struct tasklet_struct midi_tasklet;
722
723 size_t period_bytes;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100724 unsigned char ss_in_channels;
725 unsigned char ds_in_channels;
726 unsigned char qs_in_channels;
727 unsigned char ss_out_channels;
728 unsigned char ds_out_channels;
729 unsigned char qs_out_channels;
730
731 unsigned char max_channels_in;
732 unsigned char max_channels_out;
733
734 char *channel_map_in;
735 char *channel_map_out;
736
737 char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs;
738 char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs;
739
740 char **port_names_in;
741 char **port_names_out;
742
743 char **port_names_in_ss, **port_names_in_ds, **port_names_in_qs;
744 char **port_names_out_ss, **port_names_out_ds, **port_names_out_qs;
Takashi Iwai763f3562005-06-03 11:25:34 +0200745
746 unsigned char *playback_buffer; /* suitably aligned address */
747 unsigned char *capture_buffer; /* suitably aligned address */
748
749 pid_t capture_pid; /* process id which uses capture */
750 pid_t playback_pid; /* process id which uses capture */
751 int running; /* running status */
752
753 int last_external_sample_rate; /* samplerate mystic ... */
754 int last_internal_sample_rate;
755 int system_sample_rate;
756
Takashi Iwai763f3562005-06-03 11:25:34 +0200757 int dev; /* Hardware vars... */
758 int irq;
759 unsigned long port;
760 void __iomem *iobase;
761
762 int irq_count; /* for debug */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100763 int midiPorts;
Takashi Iwai763f3562005-06-03 11:25:34 +0200764
Takashi Iwai98274f02005-11-17 14:52:34 +0100765 struct snd_card *card; /* one card */
766 struct snd_pcm *pcm; /* has one pcm */
767 struct snd_hwdep *hwdep; /* and a hwdep for additional ioctl */
Takashi Iwai763f3562005-06-03 11:25:34 +0200768 struct pci_dev *pci; /* and an pci info */
769
770 /* Mixer vars */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200771 /* fast alsa mixer */
772 struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS];
773 /* but input to much, so not used */
774 struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS];
Adrian Knoth0dca1792011-01-26 19:32:14 +0100775 /* full mixer accessable over mixer ioctl or hwdep-device */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200776 struct hdspm_mixer *mixer;
Takashi Iwai763f3562005-06-03 11:25:34 +0200777
Adrian Knoth0dca1792011-01-26 19:32:14 +0100778 struct hdspm_tco *tco; /* NULL if no TCO detected */
Takashi Iwai763f3562005-06-03 11:25:34 +0200779
Adrian Knoth0dca1792011-01-26 19:32:14 +0100780 char **texts_autosync;
781 int texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +0200782
Adrian Knoth0dca1792011-01-26 19:32:14 +0100783 cycles_t last_interrupt;
Takashi Iwai763f3562005-06-03 11:25:34 +0200784};
785
Takashi Iwai763f3562005-06-03 11:25:34 +0200786
Alexey Dobriyancebe41d2010-02-06 00:21:03 +0200787static DEFINE_PCI_DEVICE_TABLE(snd_hdspm_ids) = {
Takashi Iwai763f3562005-06-03 11:25:34 +0200788 {
789 .vendor = PCI_VENDOR_ID_XILINX,
790 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
791 .subvendor = PCI_ANY_ID,
792 .subdevice = PCI_ANY_ID,
793 .class = 0,
794 .class_mask = 0,
795 .driver_data = 0},
796 {0,}
797};
798
799MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
800
801/* prototypes */
Takashi Iwai98274f02005-11-17 14:52:34 +0100802static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
803 struct hdspm * hdspm);
804static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
805 struct hdspm * hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +0200806
Adrian Knoth0dca1792011-01-26 19:32:14 +0100807static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
808static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
809static int hdspm_autosync_ref(struct hdspm *hdspm);
810static int snd_hdspm_set_defaults(struct hdspm *hdspm);
811static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +0200812 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +0200813 unsigned int reg, int channels);
814
Remy Bruno3cee5a62006-10-16 12:46:32 +0200815static inline int HDSPM_bit2freq(int n)
816{
Denys Vlasenko62cef822008-04-14 13:04:18 +0200817 static const int bit2freq_tab[] = {
818 0, 32000, 44100, 48000, 64000, 88200,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200819 96000, 128000, 176400, 192000 };
820 if (n < 1 || n > 9)
821 return 0;
822 return bit2freq_tab[n];
823}
824
Adrian Knoth0dca1792011-01-26 19:32:14 +0100825/* Write/read to/from HDSPM with Adresses in Bytes
Takashi Iwai763f3562005-06-03 11:25:34 +0200826 not words but only 32Bit writes are allowed */
827
Takashi Iwai98274f02005-11-17 14:52:34 +0100828static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
Takashi Iwai763f3562005-06-03 11:25:34 +0200829 unsigned int val)
830{
831 writel(val, hdspm->iobase + reg);
832}
833
Takashi Iwai98274f02005-11-17 14:52:34 +0100834static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
Takashi Iwai763f3562005-06-03 11:25:34 +0200835{
836 return readl(hdspm->iobase + reg);
837}
838
Adrian Knoth0dca1792011-01-26 19:32:14 +0100839/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
840 mixer is write only on hardware so we have to cache him for read
Takashi Iwai763f3562005-06-03 11:25:34 +0200841 each fader is a u32, but uses only the first 16 bit */
842
Takashi Iwai98274f02005-11-17 14:52:34 +0100843static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200844 unsigned int in)
845{
Adrian Bunk5bab24822006-03-13 14:15:04 +0100846 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +0200847 return 0;
848
849 return hdspm->mixer->ch[chan].in[in];
850}
851
Takashi Iwai98274f02005-11-17 14:52:34 +0100852static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200853 unsigned int pb)
854{
Adrian Bunk5bab24822006-03-13 14:15:04 +0100855 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +0200856 return 0;
857 return hdspm->mixer->ch[chan].pb[pb];
858}
859
Denys Vlasenko62cef822008-04-14 13:04:18 +0200860static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200861 unsigned int in, unsigned short data)
862{
863 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
864 return -1;
865
866 hdspm_write(hdspm,
867 HDSPM_MADI_mixerBase +
868 ((in + 128 * chan) * sizeof(u32)),
869 (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
870 return 0;
871}
872
Denys Vlasenko62cef822008-04-14 13:04:18 +0200873static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200874 unsigned int pb, unsigned short data)
875{
876 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
877 return -1;
878
879 hdspm_write(hdspm,
880 HDSPM_MADI_mixerBase +
881 ((64 + pb + 128 * chan) * sizeof(u32)),
882 (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
883 return 0;
884}
885
886
887/* enable DMA for specific channels, now available for DSP-MADI */
Takashi Iwai98274f02005-11-17 14:52:34 +0100888static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +0200889{
890 hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
891}
892
Takashi Iwai98274f02005-11-17 14:52:34 +0100893static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +0200894{
895 hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
896}
897
898/* check if same process is writing and reading */
Denys Vlasenko62cef822008-04-14 13:04:18 +0200899static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200900{
901 unsigned long flags;
902 int ret = 1;
903
904 spin_lock_irqsave(&hdspm->lock, flags);
905 if ((hdspm->playback_pid != hdspm->capture_pid) &&
906 (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
907 ret = 0;
908 }
909 spin_unlock_irqrestore(&hdspm->lock, flags);
910 return ret;
911}
912
913/* check for external sample rate */
Denys Vlasenko62cef822008-04-14 13:04:18 +0200914static int hdspm_external_sample_rate(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200915{
Adrian Knoth0dca1792011-01-26 19:32:14 +0100916 unsigned int status, status2, timecode;
917 int syncref, rate = 0, rate_bits;
Takashi Iwai763f3562005-06-03 11:25:34 +0200918
Adrian Knoth0dca1792011-01-26 19:32:14 +0100919 switch (hdspm->io_type) {
920 case AES32:
921 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
922 status = hdspm_read(hdspm, HDSPM_statusRegister);
923 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
924
925 syncref = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +0200926
Remy Bruno3cee5a62006-10-16 12:46:32 +0200927 if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD &&
928 status & HDSPM_AES32_wcLock)
Adrian Knoth0dca1792011-01-26 19:32:14 +0100929 return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF);
930
Remy Bruno3cee5a62006-10-16 12:46:32 +0200931 if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +0100932 syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
933 status2 & (HDSPM_LockAES >>
934 (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1)))
935 return HDSPM_bit2freq((timecode >> (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF);
Remy Bruno3cee5a62006-10-16 12:46:32 +0200936 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100937 break;
938
939 case MADIface:
940 status = hdspm_read(hdspm, HDSPM_statusRegister);
941
942 if (!(status & HDSPM_madiLock)) {
943 rate = 0; /* no lock */
944 } else {
945 switch (status & (HDSPM_status1_freqMask)) {
946 case HDSPM_status1_F_0*1:
947 rate = 32000; break;
948 case HDSPM_status1_F_0*2:
949 rate = 44100; break;
950 case HDSPM_status1_F_0*3:
951 rate = 48000; break;
952 case HDSPM_status1_F_0*4:
953 rate = 64000; break;
954 case HDSPM_status1_F_0*5:
955 rate = 88200; break;
956 case HDSPM_status1_F_0*6:
957 rate = 96000; break;
958 case HDSPM_status1_F_0*7:
959 rate = 128000; break;
960 case HDSPM_status1_F_0*8:
961 rate = 176400; break;
962 case HDSPM_status1_F_0*9:
963 rate = 192000; break;
964 default:
965 rate = 0; break;
966 }
967 }
968
969 break;
970
971 case MADI:
972 case AIO:
973 case RayDAT:
974 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
975 status = hdspm_read(hdspm, HDSPM_statusRegister);
976 rate = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +0200977
Remy Bruno3cee5a62006-10-16 12:46:32 +0200978 /* if wordclock has synced freq and wordclock is valid */
979 if ((status2 & HDSPM_wcLock) != 0 &&
980 (status & HDSPM_SelSyncRef0) == 0) {
981
982 rate_bits = status2 & HDSPM_wcFreqMask;
983
Adrian Knoth0dca1792011-01-26 19:32:14 +0100984
Remy Bruno3cee5a62006-10-16 12:46:32 +0200985 switch (rate_bits) {
986 case HDSPM_wcFreq32:
987 rate = 32000;
988 break;
989 case HDSPM_wcFreq44_1:
990 rate = 44100;
991 break;
992 case HDSPM_wcFreq48:
993 rate = 48000;
994 break;
995 case HDSPM_wcFreq64:
996 rate = 64000;
997 break;
998 case HDSPM_wcFreq88_2:
999 rate = 88200;
1000 break;
1001 case HDSPM_wcFreq96:
1002 rate = 96000;
1003 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001004 default:
1005 rate = 0;
1006 break;
1007 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001008 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001009
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001010 /* if rate detected and Syncref is Word than have it,
1011 * word has priority to MADI
1012 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001013 if (rate != 0 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001014 (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
Remy Bruno3cee5a62006-10-16 12:46:32 +02001015 return rate;
1016
Adrian Knoth0dca1792011-01-26 19:32:14 +01001017 /* maybe a madi input (which is taken if sel sync is madi) */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001018 if (status & HDSPM_madiLock) {
1019 rate_bits = status & HDSPM_madiFreqMask;
1020
1021 switch (rate_bits) {
1022 case HDSPM_madiFreq32:
1023 rate = 32000;
1024 break;
1025 case HDSPM_madiFreq44_1:
1026 rate = 44100;
1027 break;
1028 case HDSPM_madiFreq48:
1029 rate = 48000;
1030 break;
1031 case HDSPM_madiFreq64:
1032 rate = 64000;
1033 break;
1034 case HDSPM_madiFreq88_2:
1035 rate = 88200;
1036 break;
1037 case HDSPM_madiFreq96:
1038 rate = 96000;
1039 break;
1040 case HDSPM_madiFreq128:
1041 rate = 128000;
1042 break;
1043 case HDSPM_madiFreq176_4:
1044 rate = 176400;
1045 break;
1046 case HDSPM_madiFreq192:
1047 rate = 192000;
1048 break;
1049 default:
1050 rate = 0;
1051 break;
1052 }
1053 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001054 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001055 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001056
1057 return rate;
Takashi Iwai763f3562005-06-03 11:25:34 +02001058}
1059
1060/* Latency function */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001061static inline void hdspm_compute_period_size(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001062{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001063 hdspm->period_bytes = 1 << ((hdspm_decode_latency(hdspm->control_register) + 8));
Takashi Iwai763f3562005-06-03 11:25:34 +02001064}
1065
Adrian Knoth0dca1792011-01-26 19:32:14 +01001066
1067static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001068{
1069 int position;
1070
1071 position = hdspm_read(hdspm, HDSPM_statusRegister);
Takashi Iwai763f3562005-06-03 11:25:34 +02001072 position &= HDSPM_BufferPositionMask;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001073 position /= 4; /* Bytes per sample */
Takashi Iwai763f3562005-06-03 11:25:34 +02001074
1075 return position;
1076}
1077
1078
Takashi Iwai98274f02005-11-17 14:52:34 +01001079static inline void hdspm_start_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001080{
1081 s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
1082 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1083}
1084
Takashi Iwai98274f02005-11-17 14:52:34 +01001085static inline void hdspm_stop_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001086{
1087 s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
1088 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1089}
1090
1091/* should I silence all or only opened ones ? doit all for first even is 4MB*/
Denys Vlasenko62cef822008-04-14 13:04:18 +02001092static void hdspm_silence_playback(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001093{
1094 int i;
1095 int n = hdspm->period_bytes;
1096 void *buf = hdspm->playback_buffer;
1097
Remy Bruno3cee5a62006-10-16 12:46:32 +02001098 if (buf == NULL)
1099 return;
Takashi Iwai763f3562005-06-03 11:25:34 +02001100
1101 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
1102 memset(buf, 0, n);
1103 buf += HDSPM_CHANNEL_BUFFER_BYTES;
1104 }
1105}
1106
Adrian Knoth0dca1792011-01-26 19:32:14 +01001107static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames)
Takashi Iwai763f3562005-06-03 11:25:34 +02001108{
1109 int n;
1110
1111 spin_lock_irq(&s->lock);
1112
1113 frames >>= 7;
1114 n = 0;
1115 while (frames) {
1116 n++;
1117 frames >>= 1;
1118 }
1119 s->control_register &= ~HDSPM_LatencyMask;
1120 s->control_register |= hdspm_encode_latency(n);
1121
1122 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1123
1124 hdspm_compute_period_size(s);
1125
1126 spin_unlock_irq(&s->lock);
1127
1128 return 0;
1129}
1130
Adrian Knoth0dca1792011-01-26 19:32:14 +01001131static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period)
1132{
1133 u64 freq_const;
1134
1135 if (period == 0)
1136 return 0;
1137
1138 switch (hdspm->io_type) {
1139 case MADI:
1140 case AES32:
1141 freq_const = 110069313433624ULL;
1142 break;
1143 case RayDAT:
1144 case AIO:
1145 freq_const = 104857600000000ULL;
1146 break;
1147 case MADIface:
1148 freq_const = 131072000000000ULL;
1149 }
1150
1151 return div_u64(freq_const, period);
1152}
1153
1154
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001155static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
1156{
1157 u64 n;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001158
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001159 if (rate >= 112000)
1160 rate /= 4;
1161 else if (rate >= 56000)
1162 rate /= 2;
1163
Adrian Knoth0dca1792011-01-26 19:32:14 +01001164 switch (hdspm->io_type) {
1165 case MADIface:
1166 n = 131072000000000ULL; /* 125 MHz */
1167 break;
1168 case MADI:
1169 case AES32:
1170 n = 110069313433624ULL; /* 105 MHz */
1171 break;
1172 case RayDAT:
1173 case AIO:
1174 n = 104857600000000ULL; /* 100 MHz */
1175 break;
1176 }
1177
Takashi Iwai3f7440a2009-06-05 17:40:04 +02001178 n = div_u64(n, rate);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001179 /* n should be less than 2^32 for being written to FREQ register */
Takashi Iwaida3cec32008-08-08 17:12:14 +02001180 snd_BUG_ON(n >> 32);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001181 hdspm_write(hdspm, HDSPM_freqReg, (u32)n);
1182}
Takashi Iwai763f3562005-06-03 11:25:34 +02001183
1184/* dummy set rate lets see what happens */
Takashi Iwai98274f02005-11-17 14:52:34 +01001185static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
Takashi Iwai763f3562005-06-03 11:25:34 +02001186{
Takashi Iwai763f3562005-06-03 11:25:34 +02001187 int current_rate;
1188 int rate_bits;
1189 int not_set = 0;
Remy Bruno65345992007-08-31 12:21:08 +02001190 int current_speed, target_speed;
Takashi Iwai763f3562005-06-03 11:25:34 +02001191
1192 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
1193 it (e.g. during module initialization).
1194 */
1195
1196 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
1197
Adrian Knoth0dca1792011-01-26 19:32:14 +01001198 /* SLAVE --- */
Takashi Iwai763f3562005-06-03 11:25:34 +02001199 if (called_internally) {
1200
Adrian Knoth0dca1792011-01-26 19:32:14 +01001201 /* request from ctl or card initialization
1202 just make a warning an remember setting
1203 for future master mode switching */
1204
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001205 snd_printk(KERN_WARNING "HDSPM: "
1206 "Warning: device is not running "
1207 "as a clock master.\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001208 not_set = 1;
1209 } else {
1210
1211 /* hw_param request while in AutoSync mode */
1212 int external_freq =
1213 hdspm_external_sample_rate(hdspm);
1214
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001215 if (hdspm_autosync_ref(hdspm) ==
1216 HDSPM_AUTOSYNC_FROM_NONE) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001217
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001218 snd_printk(KERN_WARNING "HDSPM: "
1219 "Detected no Externel Sync \n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001220 not_set = 1;
1221
1222 } else if (rate != external_freq) {
1223
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001224 snd_printk(KERN_WARNING "HDSPM: "
1225 "Warning: No AutoSync source for "
1226 "requested rate\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001227 not_set = 1;
1228 }
1229 }
1230 }
1231
1232 current_rate = hdspm->system_sample_rate;
1233
1234 /* Changing between Singe, Double and Quad speed is not
1235 allowed if any substreams are open. This is because such a change
1236 causes a shift in the location of the DMA buffers and a reduction
1237 in the number of available buffers.
1238
1239 Note that a similar but essentially insoluble problem exists for
1240 externally-driven rate changes. All we can do is to flag rate
Adrian Knoth0dca1792011-01-26 19:32:14 +01001241 changes in the read/write routines.
Takashi Iwai763f3562005-06-03 11:25:34 +02001242 */
1243
Remy Bruno65345992007-08-31 12:21:08 +02001244 if (current_rate <= 48000)
1245 current_speed = HDSPM_SPEED_SINGLE;
1246 else if (current_rate <= 96000)
1247 current_speed = HDSPM_SPEED_DOUBLE;
1248 else
1249 current_speed = HDSPM_SPEED_QUAD;
1250
1251 if (rate <= 48000)
1252 target_speed = HDSPM_SPEED_SINGLE;
1253 else if (rate <= 96000)
1254 target_speed = HDSPM_SPEED_DOUBLE;
1255 else
1256 target_speed = HDSPM_SPEED_QUAD;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001257
Takashi Iwai763f3562005-06-03 11:25:34 +02001258 switch (rate) {
1259 case 32000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001260 rate_bits = HDSPM_Frequency32KHz;
1261 break;
1262 case 44100:
Takashi Iwai763f3562005-06-03 11:25:34 +02001263 rate_bits = HDSPM_Frequency44_1KHz;
1264 break;
1265 case 48000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001266 rate_bits = HDSPM_Frequency48KHz;
1267 break;
1268 case 64000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001269 rate_bits = HDSPM_Frequency64KHz;
1270 break;
1271 case 88200:
Takashi Iwai763f3562005-06-03 11:25:34 +02001272 rate_bits = HDSPM_Frequency88_2KHz;
1273 break;
1274 case 96000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001275 rate_bits = HDSPM_Frequency96KHz;
1276 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001277 case 128000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001278 rate_bits = HDSPM_Frequency128KHz;
1279 break;
1280 case 176400:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001281 rate_bits = HDSPM_Frequency176_4KHz;
1282 break;
1283 case 192000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001284 rate_bits = HDSPM_Frequency192KHz;
1285 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001286 default:
1287 return -EINVAL;
1288 }
1289
Remy Bruno65345992007-08-31 12:21:08 +02001290 if (current_speed != target_speed
Takashi Iwai763f3562005-06-03 11:25:34 +02001291 && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
1292 snd_printk
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001293 (KERN_ERR "HDSPM: "
Remy Bruno65345992007-08-31 12:21:08 +02001294 "cannot change from %s speed to %s speed mode "
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001295 "(capture PID = %d, playback PID = %d)\n",
Remy Bruno65345992007-08-31 12:21:08 +02001296 hdspm_speed_names[current_speed],
1297 hdspm_speed_names[target_speed],
Takashi Iwai763f3562005-06-03 11:25:34 +02001298 hdspm->capture_pid, hdspm->playback_pid);
1299 return -EBUSY;
1300 }
1301
1302 hdspm->control_register &= ~HDSPM_FrequencyMask;
1303 hdspm->control_register |= rate_bits;
1304 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1305
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001306 /* For AES32, need to set DDS value in FREQ register
1307 For MADI, also apparently */
1308 hdspm_set_dds_value(hdspm, rate);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001309
1310 if (AES32 == hdspm->io_type && rate != current_rate)
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001311 hdspm_write(hdspm, HDSPM_eeprom_wr, 0);
Takashi Iwai763f3562005-06-03 11:25:34 +02001312
1313 hdspm->system_sample_rate = rate;
1314
Adrian Knoth0dca1792011-01-26 19:32:14 +01001315 if (rate <= 48000) {
1316 hdspm->channel_map_in = hdspm->channel_map_in_ss;
1317 hdspm->channel_map_out = hdspm->channel_map_out_ss;
1318 hdspm->max_channels_in = hdspm->ss_in_channels;
1319 hdspm->max_channels_out = hdspm->ss_out_channels;
1320 hdspm->port_names_in = hdspm->port_names_in_ss;
1321 hdspm->port_names_out = hdspm->port_names_out_ss;
1322 } else if (rate <= 96000) {
1323 hdspm->channel_map_in = hdspm->channel_map_in_ds;
1324 hdspm->channel_map_out = hdspm->channel_map_out_ds;
1325 hdspm->max_channels_in = hdspm->ds_in_channels;
1326 hdspm->max_channels_out = hdspm->ds_out_channels;
1327 hdspm->port_names_in = hdspm->port_names_in_ds;
1328 hdspm->port_names_out = hdspm->port_names_out_ds;
1329 } else {
1330 hdspm->channel_map_in = hdspm->channel_map_in_qs;
1331 hdspm->channel_map_out = hdspm->channel_map_out_qs;
1332 hdspm->max_channels_in = hdspm->qs_in_channels;
1333 hdspm->max_channels_out = hdspm->qs_out_channels;
1334 hdspm->port_names_in = hdspm->port_names_in_qs;
1335 hdspm->port_names_out = hdspm->port_names_out_qs;
1336 }
1337
Takashi Iwai763f3562005-06-03 11:25:34 +02001338 if (not_set != 0)
1339 return -1;
1340
1341 return 0;
1342}
1343
1344/* mainly for init to 0 on load */
Takashi Iwai98274f02005-11-17 14:52:34 +01001345static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
Takashi Iwai763f3562005-06-03 11:25:34 +02001346{
1347 int i, j;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001348 unsigned int gain;
1349
1350 if (sgain > UNITY_GAIN)
1351 gain = UNITY_GAIN;
1352 else if (sgain < 0)
1353 gain = 0;
1354 else
1355 gain = sgain;
Takashi Iwai763f3562005-06-03 11:25:34 +02001356
1357 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
1358 for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
1359 hdspm_write_in_gain(hdspm, i, j, gain);
1360 hdspm_write_pb_gain(hdspm, i, j, gain);
1361 }
1362}
1363
1364/*----------------------------------------------------------------------------
1365 MIDI
1366 ----------------------------------------------------------------------------*/
1367
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001368static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm,
1369 int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001370{
1371 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001372 return hdspm_read(hdspm, hdspm->midi[id].dataIn);
Takashi Iwai763f3562005-06-03 11:25:34 +02001373}
1374
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001375static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
1376 int val)
Takashi Iwai763f3562005-06-03 11:25:34 +02001377{
1378 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001379 return hdspm_write(hdspm, hdspm->midi[id].dataOut, val);
Takashi Iwai763f3562005-06-03 11:25:34 +02001380}
1381
Takashi Iwai98274f02005-11-17 14:52:34 +01001382static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001383{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001384 return hdspm_read(hdspm, hdspm->midi[id].statusIn) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001385}
1386
Takashi Iwai98274f02005-11-17 14:52:34 +01001387static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001388{
1389 int fifo_bytes_used;
1390
Adrian Knoth0dca1792011-01-26 19:32:14 +01001391 fifo_bytes_used = hdspm_read(hdspm, hdspm->midi[id].statusOut) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001392
1393 if (fifo_bytes_used < 128)
1394 return 128 - fifo_bytes_used;
1395 else
1396 return 0;
1397}
1398
Denys Vlasenko62cef822008-04-14 13:04:18 +02001399static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001400{
1401 while (snd_hdspm_midi_input_available (hdspm, id))
1402 snd_hdspm_midi_read_byte (hdspm, id);
1403}
1404
Takashi Iwai98274f02005-11-17 14:52:34 +01001405static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001406{
1407 unsigned long flags;
1408 int n_pending;
1409 int to_write;
1410 int i;
1411 unsigned char buf[128];
1412
1413 /* Output is not interrupt driven */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001414
Takashi Iwai763f3562005-06-03 11:25:34 +02001415 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001416 if (hmidi->output &&
1417 !snd_rawmidi_transmit_empty (hmidi->output)) {
1418 n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm,
1419 hmidi->id);
1420 if (n_pending > 0) {
1421 if (n_pending > (int)sizeof (buf))
1422 n_pending = sizeof (buf);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001423
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001424 to_write = snd_rawmidi_transmit (hmidi->output, buf,
1425 n_pending);
1426 if (to_write > 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001427 for (i = 0; i < to_write; ++i)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001428 snd_hdspm_midi_write_byte (hmidi->hdspm,
1429 hmidi->id,
1430 buf[i]);
Takashi Iwai763f3562005-06-03 11:25:34 +02001431 }
1432 }
1433 }
1434 spin_unlock_irqrestore (&hmidi->lock, flags);
1435 return 0;
1436}
1437
Takashi Iwai98274f02005-11-17 14:52:34 +01001438static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001439{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001440 unsigned char buf[128]; /* this buffer is designed to match the MIDI
1441 * input FIFO size
1442 */
Takashi Iwai763f3562005-06-03 11:25:34 +02001443 unsigned long flags;
1444 int n_pending;
1445 int i;
1446
1447 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001448 n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id);
1449 if (n_pending > 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001450 if (hmidi->input) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001451 if (n_pending > (int)sizeof (buf))
Takashi Iwai763f3562005-06-03 11:25:34 +02001452 n_pending = sizeof (buf);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001453 for (i = 0; i < n_pending; ++i)
1454 buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm,
1455 hmidi->id);
1456 if (n_pending)
1457 snd_rawmidi_receive (hmidi->input, buf,
1458 n_pending);
Takashi Iwai763f3562005-06-03 11:25:34 +02001459 } else {
1460 /* flush the MIDI input FIFO */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001461 while (n_pending--)
1462 snd_hdspm_midi_read_byte (hmidi->hdspm,
1463 hmidi->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02001464 }
1465 }
1466 hmidi->pending = 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001467
1468 hmidi->hdspm->control_register |= hmidi->ie;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001469 hdspm_write(hmidi->hdspm, HDSPM_controlRegister,
1470 hmidi->hdspm->control_register);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001471
Takashi Iwai763f3562005-06-03 11:25:34 +02001472 spin_unlock_irqrestore (&hmidi->lock, flags);
1473 return snd_hdspm_midi_output_write (hmidi);
1474}
1475
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001476static void
1477snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001478{
Takashi Iwai98274f02005-11-17 14:52:34 +01001479 struct hdspm *hdspm;
1480 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001481 unsigned long flags;
Takashi Iwai763f3562005-06-03 11:25:34 +02001482
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001483 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001484 hdspm = hmidi->hdspm;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001485
Takashi Iwai763f3562005-06-03 11:25:34 +02001486 spin_lock_irqsave (&hdspm->lock, flags);
1487 if (up) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001488 if (!(hdspm->control_register & hmidi->ie)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001489 snd_hdspm_flush_midi_input (hdspm, hmidi->id);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001490 hdspm->control_register |= hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001491 }
1492 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001493 hdspm->control_register &= ~hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001494 }
1495
1496 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1497 spin_unlock_irqrestore (&hdspm->lock, flags);
1498}
1499
1500static void snd_hdspm_midi_output_timer(unsigned long data)
1501{
Takashi Iwai98274f02005-11-17 14:52:34 +01001502 struct hdspm_midi *hmidi = (struct hdspm_midi *) data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001503 unsigned long flags;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001504
Takashi Iwai763f3562005-06-03 11:25:34 +02001505 snd_hdspm_midi_output_write(hmidi);
1506 spin_lock_irqsave (&hmidi->lock, flags);
1507
1508 /* this does not bump hmidi->istimer, because the
1509 kernel automatically removed the timer when it
1510 expired, and we are now adding it back, thus
Adrian Knoth0dca1792011-01-26 19:32:14 +01001511 leaving istimer wherever it was set before.
Takashi Iwai763f3562005-06-03 11:25:34 +02001512 */
1513
1514 if (hmidi->istimer) {
1515 hmidi->timer.expires = 1 + jiffies;
1516 add_timer(&hmidi->timer);
1517 }
1518
1519 spin_unlock_irqrestore (&hmidi->lock, flags);
1520}
1521
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001522static void
1523snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001524{
Takashi Iwai98274f02005-11-17 14:52:34 +01001525 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001526 unsigned long flags;
1527
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001528 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001529 spin_lock_irqsave (&hmidi->lock, flags);
1530 if (up) {
1531 if (!hmidi->istimer) {
1532 init_timer(&hmidi->timer);
1533 hmidi->timer.function = snd_hdspm_midi_output_timer;
1534 hmidi->timer.data = (unsigned long) hmidi;
1535 hmidi->timer.expires = 1 + jiffies;
1536 add_timer(&hmidi->timer);
1537 hmidi->istimer++;
1538 }
1539 } else {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001540 if (hmidi->istimer && --hmidi->istimer <= 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02001541 del_timer (&hmidi->timer);
Takashi Iwai763f3562005-06-03 11:25:34 +02001542 }
1543 spin_unlock_irqrestore (&hmidi->lock, flags);
1544 if (up)
1545 snd_hdspm_midi_output_write(hmidi);
1546}
1547
Takashi Iwai98274f02005-11-17 14:52:34 +01001548static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001549{
Takashi Iwai98274f02005-11-17 14:52:34 +01001550 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001551
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001552 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001553 spin_lock_irq (&hmidi->lock);
1554 snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
1555 hmidi->input = substream;
1556 spin_unlock_irq (&hmidi->lock);
1557
1558 return 0;
1559}
1560
Takashi Iwai98274f02005-11-17 14:52:34 +01001561static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001562{
Takashi Iwai98274f02005-11-17 14:52:34 +01001563 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001564
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001565 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001566 spin_lock_irq (&hmidi->lock);
1567 hmidi->output = substream;
1568 spin_unlock_irq (&hmidi->lock);
1569
1570 return 0;
1571}
1572
Takashi Iwai98274f02005-11-17 14:52:34 +01001573static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001574{
Takashi Iwai98274f02005-11-17 14:52:34 +01001575 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001576
1577 snd_hdspm_midi_input_trigger (substream, 0);
1578
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001579 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001580 spin_lock_irq (&hmidi->lock);
1581 hmidi->input = NULL;
1582 spin_unlock_irq (&hmidi->lock);
1583
1584 return 0;
1585}
1586
Takashi Iwai98274f02005-11-17 14:52:34 +01001587static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001588{
Takashi Iwai98274f02005-11-17 14:52:34 +01001589 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001590
1591 snd_hdspm_midi_output_trigger (substream, 0);
1592
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001593 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001594 spin_lock_irq (&hmidi->lock);
1595 hmidi->output = NULL;
1596 spin_unlock_irq (&hmidi->lock);
1597
1598 return 0;
1599}
1600
Takashi Iwai98274f02005-11-17 14:52:34 +01001601static struct snd_rawmidi_ops snd_hdspm_midi_output =
Takashi Iwai763f3562005-06-03 11:25:34 +02001602{
1603 .open = snd_hdspm_midi_output_open,
1604 .close = snd_hdspm_midi_output_close,
1605 .trigger = snd_hdspm_midi_output_trigger,
1606};
1607
Takashi Iwai98274f02005-11-17 14:52:34 +01001608static struct snd_rawmidi_ops snd_hdspm_midi_input =
Takashi Iwai763f3562005-06-03 11:25:34 +02001609{
1610 .open = snd_hdspm_midi_input_open,
1611 .close = snd_hdspm_midi_input_close,
1612 .trigger = snd_hdspm_midi_input_trigger,
1613};
1614
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001615static int __devinit snd_hdspm_create_midi (struct snd_card *card,
1616 struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001617{
1618 int err;
1619 char buf[32];
1620
1621 hdspm->midi[id].id = id;
Takashi Iwai763f3562005-06-03 11:25:34 +02001622 hdspm->midi[id].hdspm = hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +02001623 spin_lock_init (&hdspm->midi[id].lock);
1624
Adrian Knoth0dca1792011-01-26 19:32:14 +01001625 if (0 == id) {
1626 if (MADIface == hdspm->io_type) {
1627 /* MIDI-over-MADI on HDSPe MADIface */
1628 hdspm->midi[0].dataIn = HDSPM_midiDataIn2;
1629 hdspm->midi[0].statusIn = HDSPM_midiStatusIn2;
1630 hdspm->midi[0].dataOut = HDSPM_midiDataOut2;
1631 hdspm->midi[0].statusOut = HDSPM_midiStatusOut2;
1632 hdspm->midi[0].ie = HDSPM_Midi2InterruptEnable;
1633 hdspm->midi[0].irq = HDSPM_midi2IRQPending;
1634 } else {
1635 hdspm->midi[0].dataIn = HDSPM_midiDataIn0;
1636 hdspm->midi[0].statusIn = HDSPM_midiStatusIn0;
1637 hdspm->midi[0].dataOut = HDSPM_midiDataOut0;
1638 hdspm->midi[0].statusOut = HDSPM_midiStatusOut0;
1639 hdspm->midi[0].ie = HDSPM_Midi0InterruptEnable;
1640 hdspm->midi[0].irq = HDSPM_midi0IRQPending;
1641 }
1642 } else if (1 == id) {
1643 hdspm->midi[1].dataIn = HDSPM_midiDataIn1;
1644 hdspm->midi[1].statusIn = HDSPM_midiStatusIn1;
1645 hdspm->midi[1].dataOut = HDSPM_midiDataOut1;
1646 hdspm->midi[1].statusOut = HDSPM_midiStatusOut1;
1647 hdspm->midi[1].ie = HDSPM_Midi1InterruptEnable;
1648 hdspm->midi[1].irq = HDSPM_midi1IRQPending;
1649 } else if ((2 == id) && (MADI == hdspm->io_type)) {
1650 /* MIDI-over-MADI on HDSPe MADI */
1651 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1652 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1653 hdspm->midi[2].dataOut = HDSPM_midiDataOut2;
1654 hdspm->midi[2].statusOut = HDSPM_midiStatusOut2;
1655 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1656 hdspm->midi[2].irq = HDSPM_midi2IRQPending;
1657 } else if (2 == id) {
1658 /* TCO MTC, read only */
1659 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1660 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1661 hdspm->midi[2].dataOut = -1;
1662 hdspm->midi[2].statusOut = -1;
1663 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1664 hdspm->midi[2].irq = HDSPM_midi2IRQPendingAES;
1665 } else if (3 == id) {
1666 /* TCO MTC on HDSPe MADI */
1667 hdspm->midi[3].dataIn = HDSPM_midiDataIn3;
1668 hdspm->midi[3].statusIn = HDSPM_midiStatusIn3;
1669 hdspm->midi[3].dataOut = -1;
1670 hdspm->midi[3].statusOut = -1;
1671 hdspm->midi[3].ie = HDSPM_Midi3InterruptEnable;
1672 hdspm->midi[3].irq = HDSPM_midi3IRQPending;
1673 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001674
Adrian Knoth0dca1792011-01-26 19:32:14 +01001675 if ((id < 2) || ((2 == id) && ((MADI == hdspm->io_type) ||
1676 (MADIface == hdspm->io_type)))) {
1677 if ((id == 0) && (MADIface == hdspm->io_type)) {
1678 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1679 } else if ((id == 2) && (MADI == hdspm->io_type)) {
1680 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1681 } else {
1682 sprintf(buf, "%s MIDI %d", card->shortname, id+1);
1683 }
1684 err = snd_rawmidi_new(card, buf, id, 1, 1,
1685 &hdspm->midi[id].rmidi);
1686 if (err < 0)
1687 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02001688
Adrian Knoth0dca1792011-01-26 19:32:14 +01001689 sprintf(hdspm->midi[id].rmidi->name, "%s MIDI %d",
1690 card->id, id+1);
1691 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
Takashi Iwai763f3562005-06-03 11:25:34 +02001692
Adrian Knoth0dca1792011-01-26 19:32:14 +01001693 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1694 SNDRV_RAWMIDI_STREAM_OUTPUT,
1695 &snd_hdspm_midi_output);
1696 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1697 SNDRV_RAWMIDI_STREAM_INPUT,
1698 &snd_hdspm_midi_input);
1699
1700 hdspm->midi[id].rmidi->info_flags |=
1701 SNDRV_RAWMIDI_INFO_OUTPUT |
1702 SNDRV_RAWMIDI_INFO_INPUT |
1703 SNDRV_RAWMIDI_INFO_DUPLEX;
1704 } else {
1705 /* TCO MTC, read only */
1706 sprintf(buf, "%s MTC %d", card->shortname, id+1);
1707 err = snd_rawmidi_new(card, buf, id, 1, 1,
1708 &hdspm->midi[id].rmidi);
1709 if (err < 0)
1710 return err;
1711
1712 sprintf(hdspm->midi[id].rmidi->name,
1713 "%s MTC %d", card->id, id+1);
1714 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
1715
1716 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1717 SNDRV_RAWMIDI_STREAM_INPUT,
1718 &snd_hdspm_midi_input);
1719
1720 hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
1721 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001722
1723 return 0;
1724}
1725
1726
1727static void hdspm_midi_tasklet(unsigned long arg)
1728{
Takashi Iwai98274f02005-11-17 14:52:34 +01001729 struct hdspm *hdspm = (struct hdspm *)arg;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001730 int i = 0;
1731
1732 while (i < hdspm->midiPorts) {
1733 if (hdspm->midi[i].pending)
1734 snd_hdspm_midi_input_read(&hdspm->midi[i]);
1735
1736 i++;
1737 }
1738}
Takashi Iwai763f3562005-06-03 11:25:34 +02001739
1740
1741/*-----------------------------------------------------------------------------
1742 Status Interface
1743 ----------------------------------------------------------------------------*/
1744
1745/* get the system sample rate which is set */
1746
Adrian Knoth0dca1792011-01-26 19:32:14 +01001747
1748/**
1749 * Calculate the real sample rate from the
1750 * current DDS value.
1751 **/
1752static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
1753{
1754 unsigned int period, rate;
1755
1756 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
1757 rate = hdspm_calc_dds_value(hdspm, period);
1758
1759 return rate;
1760}
1761
1762
Takashi Iwai763f3562005-06-03 11:25:34 +02001763#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001764{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001765 .name = xname, \
1766 .index = xindex, \
1767 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1768 .info = snd_hdspm_info_system_sample_rate, \
1769 .get = snd_hdspm_get_system_sample_rate \
1770}
1771
Takashi Iwai98274f02005-11-17 14:52:34 +01001772static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
1773 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001774{
1775 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1776 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001777 uinfo->value.integer.min = 27000;
1778 uinfo->value.integer.max = 207000;
1779 uinfo->value.integer.step = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02001780 return 0;
1781}
1782
Adrian Knoth0dca1792011-01-26 19:32:14 +01001783
Takashi Iwai98274f02005-11-17 14:52:34 +01001784static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
1785 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02001786 ucontrol)
1787{
Takashi Iwai98274f02005-11-17 14:52:34 +01001788 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001789
Adrian Knoth0dca1792011-01-26 19:32:14 +01001790 ucontrol->value.integer.value[0] = hdspm_get_system_sample_rate(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001791 return 0;
1792}
1793
Adrian Knoth0dca1792011-01-26 19:32:14 +01001794
1795/**
1796 * Returns the WordClock sample rate class for the given card.
1797 **/
1798static int hdspm_get_wc_sample_rate(struct hdspm *hdspm)
1799{
1800 int status;
1801
1802 switch (hdspm->io_type) {
1803 case RayDAT:
1804 case AIO:
1805 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
1806 return (status >> 16) & 0xF;
1807 break;
1808 default:
1809 break;
1810 }
1811
1812
1813 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02001814}
1815
Adrian Knoth0dca1792011-01-26 19:32:14 +01001816
1817/**
1818 * Returns the TCO sample rate class for the given card.
1819 **/
1820static int hdspm_get_tco_sample_rate(struct hdspm *hdspm)
1821{
1822 int status;
1823
1824 if (hdspm->tco) {
1825 switch (hdspm->io_type) {
1826 case RayDAT:
1827 case AIO:
1828 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
1829 return (status >> 20) & 0xF;
1830 break;
1831 default:
1832 break;
1833 }
1834 }
1835
1836 return 0;
1837}
1838
1839
1840/**
1841 * Returns the SYNC_IN sample rate class for the given card.
1842 **/
1843static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm)
1844{
1845 int status;
1846
1847 if (hdspm->tco) {
1848 switch (hdspm->io_type) {
1849 case RayDAT:
1850 case AIO:
1851 status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
1852 return (status >> 12) & 0xF;
1853 break;
1854 default:
1855 break;
1856 }
1857 }
1858
1859 return 0;
1860}
1861
1862
1863/**
1864 * Returns the sample rate class for input source <idx> for
1865 * 'new style' cards like the AIO and RayDAT.
1866 **/
1867static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
1868{
1869 int status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
1870
1871 return (status >> (idx*4)) & 0xF;
1872}
1873
1874
1875
1876#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
1877{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1878 .name = xname, \
1879 .private_value = xindex, \
1880 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1881 .info = snd_hdspm_info_autosync_sample_rate, \
1882 .get = snd_hdspm_get_autosync_sample_rate \
1883}
1884
1885
Takashi Iwai98274f02005-11-17 14:52:34 +01001886static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
1887 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001888{
Takashi Iwai763f3562005-06-03 11:25:34 +02001889 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1890 uinfo->count = 1;
1891 uinfo->value.enumerated.items = 10;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001892
Takashi Iwai763f3562005-06-03 11:25:34 +02001893 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
Adrian Knoth0dca1792011-01-26 19:32:14 +01001894 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02001895 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01001896 texts_freq[uinfo->value.enumerated.item]);
Takashi Iwai763f3562005-06-03 11:25:34 +02001897 return 0;
1898}
1899
Adrian Knoth0dca1792011-01-26 19:32:14 +01001900
Takashi Iwai98274f02005-11-17 14:52:34 +01001901static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
1902 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02001903 ucontrol)
1904{
Takashi Iwai98274f02005-11-17 14:52:34 +01001905 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001906
Adrian Knoth0dca1792011-01-26 19:32:14 +01001907 switch (hdspm->io_type) {
1908 case RayDAT:
1909 switch (kcontrol->private_value) {
1910 case 0:
1911 ucontrol->value.enumerated.item[0] =
1912 hdspm_get_wc_sample_rate(hdspm);
1913 break;
1914 case 7:
1915 ucontrol->value.enumerated.item[0] =
1916 hdspm_get_tco_sample_rate(hdspm);
1917 break;
1918 case 8:
1919 ucontrol->value.enumerated.item[0] =
1920 hdspm_get_sync_in_sample_rate(hdspm);
1921 break;
1922 default:
1923 ucontrol->value.enumerated.item[0] =
1924 hdspm_get_s1_sample_rate(hdspm,
1925 kcontrol->private_value-1);
1926 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001927
Adrian Knoth0dca1792011-01-26 19:32:14 +01001928 case AIO:
1929 switch (kcontrol->private_value) {
1930 case 0: /* WC */
1931 ucontrol->value.enumerated.item[0] =
1932 hdspm_get_wc_sample_rate(hdspm);
1933 break;
1934 case 4: /* TCO */
1935 ucontrol->value.enumerated.item[0] =
1936 hdspm_get_tco_sample_rate(hdspm);
1937 break;
1938 case 5: /* SYNC_IN */
1939 ucontrol->value.enumerated.item[0] =
1940 hdspm_get_sync_in_sample_rate(hdspm);
1941 break;
1942 default:
1943 ucontrol->value.enumerated.item[0] =
1944 hdspm_get_s1_sample_rate(hdspm,
1945 ucontrol->id.index-1);
1946 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001947 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01001948 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001949 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001950
Takashi Iwai763f3562005-06-03 11:25:34 +02001951 return 0;
1952}
1953
Adrian Knoth0dca1792011-01-26 19:32:14 +01001954
Takashi Iwai763f3562005-06-03 11:25:34 +02001955#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01001956{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1957 .name = xname, \
1958 .index = xindex, \
1959 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
1960 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
1961 .info = snd_hdspm_info_system_clock_mode, \
1962 .get = snd_hdspm_get_system_clock_mode, \
1963 .put = snd_hdspm_put_system_clock_mode, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001964}
1965
1966
Adrian Knoth0dca1792011-01-26 19:32:14 +01001967/**
1968 * Returns the system clock mode for the given card.
1969 * @returns 0 - master, 1 - slave
1970 **/
1971static int hdspm_system_clock_mode(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001972{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001973 switch (hdspm->io_type) {
1974 case AIO:
1975 case RayDAT:
1976 if (hdspm->settings_register & HDSPM_c0Master)
1977 return 0;
1978 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001979
Adrian Knoth0dca1792011-01-26 19:32:14 +01001980 default:
1981 if (hdspm->control_register & HDSPM_ClockModeMaster)
1982 return 0;
1983 }
1984
Takashi Iwai763f3562005-06-03 11:25:34 +02001985 return 1;
1986}
1987
Adrian Knoth0dca1792011-01-26 19:32:14 +01001988
1989/**
1990 * Sets the system clock mode.
1991 * @param mode 0 - master, 1 - slave
1992 **/
1993static void hdspm_set_system_clock_mode(struct hdspm *hdspm, int mode)
1994{
1995 switch (hdspm->io_type) {
1996 case AIO:
1997 case RayDAT:
1998 if (0 == mode)
1999 hdspm->settings_register |= HDSPM_c0Master;
2000 else
2001 hdspm->settings_register &= ~HDSPM_c0Master;
2002
2003 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2004 break;
2005
2006 default:
2007 if (0 == mode)
2008 hdspm->control_register |= HDSPM_ClockModeMaster;
2009 else
2010 hdspm->control_register &= ~HDSPM_ClockModeMaster;
2011
2012 hdspm_write(hdspm, HDSPM_controlRegister,
2013 hdspm->control_register);
2014 }
2015}
2016
2017
Takashi Iwai98274f02005-11-17 14:52:34 +01002018static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
2019 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002020{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002021 static char *texts[] = { "Master", "AutoSync" };
Takashi Iwai763f3562005-06-03 11:25:34 +02002022
2023 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2024 uinfo->count = 1;
2025 uinfo->value.enumerated.items = 2;
2026 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2027 uinfo->value.enumerated.item =
2028 uinfo->value.enumerated.items - 1;
2029 strcpy(uinfo->value.enumerated.name,
2030 texts[uinfo->value.enumerated.item]);
2031 return 0;
2032}
2033
Takashi Iwai98274f02005-11-17 14:52:34 +01002034static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
2035 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002036{
Takashi Iwai98274f02005-11-17 14:52:34 +01002037 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002038
Adrian Knoth0dca1792011-01-26 19:32:14 +01002039 ucontrol->value.enumerated.item[0] = hdspm_system_clock_mode(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002040 return 0;
2041}
2042
Adrian Knoth0dca1792011-01-26 19:32:14 +01002043static int snd_hdspm_put_system_clock_mode(struct snd_kcontrol *kcontrol,
2044 struct snd_ctl_elem_value *ucontrol)
2045{
2046 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2047 int val;
2048
2049 if (!snd_hdspm_use_is_exclusive(hdspm))
2050 return -EBUSY;
2051
2052 val = ucontrol->value.enumerated.item[0];
2053 if (val < 0)
2054 val = 0;
2055 else if (val > 1)
2056 val = 1;
2057
2058 hdspm_set_system_clock_mode(hdspm, val);
2059
2060 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002061}
2062
Adrian Knoth0dca1792011-01-26 19:32:14 +01002063
2064#define HDSPM_INTERNAL_CLOCK(xname, xindex) \
2065{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2066 .name = xname, \
2067 .index = xindex, \
2068 .info = snd_hdspm_info_clock_source, \
2069 .get = snd_hdspm_get_clock_source, \
2070 .put = snd_hdspm_put_clock_source \
2071}
2072
2073
Takashi Iwai98274f02005-11-17 14:52:34 +01002074static int hdspm_clock_source(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002075{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002076 switch (hdspm->system_sample_rate) {
2077 case 32000: return 0;
2078 case 44100: return 1;
2079 case 48000: return 2;
2080 case 64000: return 3;
2081 case 88200: return 4;
2082 case 96000: return 5;
2083 case 128000: return 6;
2084 case 176400: return 7;
2085 case 192000: return 8;
Takashi Iwai763f3562005-06-03 11:25:34 +02002086 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002087
2088 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002089}
2090
Takashi Iwai98274f02005-11-17 14:52:34 +01002091static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
Takashi Iwai763f3562005-06-03 11:25:34 +02002092{
2093 int rate;
2094 switch (mode) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002095 case 0:
2096 rate = 32000; break;
2097 case 1:
2098 rate = 44100; break;
2099 case 2:
2100 rate = 48000; break;
2101 case 3:
2102 rate = 64000; break;
2103 case 4:
2104 rate = 88200; break;
2105 case 5:
2106 rate = 96000; break;
2107 case 6:
2108 rate = 128000; break;
2109 case 7:
2110 rate = 176400; break;
2111 case 8:
2112 rate = 192000; break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002113 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002114 rate = 48000;
Takashi Iwai763f3562005-06-03 11:25:34 +02002115 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002116 hdspm_set_rate(hdspm, rate, 1);
2117 return 0;
2118}
2119
Takashi Iwai98274f02005-11-17 14:52:34 +01002120static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
2121 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002122{
Takashi Iwai763f3562005-06-03 11:25:34 +02002123 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2124 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002125 uinfo->value.enumerated.items = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002126
2127 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2128 uinfo->value.enumerated.item =
2129 uinfo->value.enumerated.items - 1;
2130
2131 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002132 texts_freq[uinfo->value.enumerated.item+1]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002133
2134 return 0;
2135}
2136
Takashi Iwai98274f02005-11-17 14:52:34 +01002137static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
2138 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002139{
Takashi Iwai98274f02005-11-17 14:52:34 +01002140 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002141
2142 ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
2143 return 0;
2144}
2145
Takashi Iwai98274f02005-11-17 14:52:34 +01002146static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
2147 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002148{
Takashi Iwai98274f02005-11-17 14:52:34 +01002149 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002150 int change;
2151 int val;
2152
2153 if (!snd_hdspm_use_is_exclusive(hdspm))
2154 return -EBUSY;
2155 val = ucontrol->value.enumerated.item[0];
2156 if (val < 0)
2157 val = 0;
Remy Bruno65345992007-08-31 12:21:08 +02002158 if (val > 9)
2159 val = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002160 spin_lock_irq(&hdspm->lock);
2161 if (val != hdspm_clock_source(hdspm))
2162 change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
2163 else
2164 change = 0;
2165 spin_unlock_irq(&hdspm->lock);
2166 return change;
2167}
2168
Adrian Knoth0dca1792011-01-26 19:32:14 +01002169
Takashi Iwai763f3562005-06-03 11:25:34 +02002170#define HDSPM_PREF_SYNC_REF(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002171{.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2172 .name = xname, \
2173 .index = xindex, \
2174 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2175 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2176 .info = snd_hdspm_info_pref_sync_ref, \
2177 .get = snd_hdspm_get_pref_sync_ref, \
2178 .put = snd_hdspm_put_pref_sync_ref \
Takashi Iwai763f3562005-06-03 11:25:34 +02002179}
2180
Adrian Knoth0dca1792011-01-26 19:32:14 +01002181
2182/**
2183 * Returns the current preferred sync reference setting.
2184 * The semantics of the return value are depending on the
2185 * card, please see the comments for clarification.
2186 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002187static int hdspm_pref_sync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002188{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002189 switch (hdspm->io_type) {
2190 case AES32:
Remy Bruno3cee5a62006-10-16 12:46:32 +02002191 switch (hdspm->control_register & HDSPM_SyncRefMask) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002192 case 0: return 0; /* WC */
2193 case HDSPM_SyncRef0: return 1; /* AES 1 */
2194 case HDSPM_SyncRef1: return 2; /* AES 2 */
2195 case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; /* AES 3 */
2196 case HDSPM_SyncRef2: return 4; /* AES 4 */
2197 case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; /* AES 5 */
2198 case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; /* AES 6 */
2199 case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0:
2200 return 7; /* AES 7 */
2201 case HDSPM_SyncRef3: return 8; /* AES 8 */
2202 case HDSPM_SyncRef3+HDSPM_SyncRef0: return 9; /* TCO */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002203 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002204 break;
2205
2206 case MADI:
2207 case MADIface:
2208 if (hdspm->tco) {
2209 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2210 case 0: return 0; /* WC */
2211 case HDSPM_SyncRef0: return 1; /* MADI */
2212 case HDSPM_SyncRef1: return 2; /* TCO */
2213 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2214 return 3; /* SYNC_IN */
2215 }
2216 } else {
2217 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2218 case 0: return 0; /* WC */
2219 case HDSPM_SyncRef0: return 1; /* MADI */
2220 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2221 return 2; /* SYNC_IN */
2222 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02002223 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002224 break;
2225
2226 case RayDAT:
2227 if (hdspm->tco) {
2228 switch ((hdspm->settings_register &
2229 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2230 case 0: return 0; /* WC */
2231 case 3: return 1; /* ADAT 1 */
2232 case 4: return 2; /* ADAT 2 */
2233 case 5: return 3; /* ADAT 3 */
2234 case 6: return 4; /* ADAT 4 */
2235 case 1: return 5; /* AES */
2236 case 2: return 6; /* SPDIF */
2237 case 9: return 7; /* TCO */
2238 case 10: return 8; /* SYNC_IN */
2239 }
2240 } else {
2241 switch ((hdspm->settings_register &
2242 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2243 case 0: return 0; /* WC */
2244 case 3: return 1; /* ADAT 1 */
2245 case 4: return 2; /* ADAT 2 */
2246 case 5: return 3; /* ADAT 3 */
2247 case 6: return 4; /* ADAT 4 */
2248 case 1: return 5; /* AES */
2249 case 2: return 6; /* SPDIF */
2250 case 10: return 7; /* SYNC_IN */
2251 }
2252 }
2253
2254 break;
2255
2256 case AIO:
2257 if (hdspm->tco) {
2258 switch ((hdspm->settings_register &
2259 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2260 case 0: return 0; /* WC */
2261 case 3: return 1; /* ADAT */
2262 case 1: return 2; /* AES */
2263 case 2: return 3; /* SPDIF */
2264 case 9: return 4; /* TCO */
2265 case 10: return 5; /* SYNC_IN */
2266 }
2267 } else {
2268 switch ((hdspm->settings_register &
2269 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2270 case 0: return 0; /* WC */
2271 case 3: return 1; /* ADAT */
2272 case 1: return 2; /* AES */
2273 case 2: return 3; /* SPDIF */
2274 case 10: return 4; /* SYNC_IN */
2275 }
2276 }
2277
2278 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002279 }
2280
Adrian Knoth0dca1792011-01-26 19:32:14 +01002281 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002282}
2283
Adrian Knoth0dca1792011-01-26 19:32:14 +01002284
2285/**
2286 * Set the preferred sync reference to <pref>. The semantics
2287 * of <pref> are depending on the card type, see the comments
2288 * for clarification.
2289 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002290static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
Takashi Iwai763f3562005-06-03 11:25:34 +02002291{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002292 int p = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002293
Adrian Knoth0dca1792011-01-26 19:32:14 +01002294 switch (hdspm->io_type) {
2295 case AES32:
2296 hdspm->control_register &= ~HDSPM_SyncRefMask;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002297 switch (pref) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002298 case 0: /* WC */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002299 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002300 case 1: /* AES 1 */
2301 hdspm->control_register |= HDSPM_SyncRef0;
2302 break;
2303 case 2: /* AES 2 */
2304 hdspm->control_register |= HDSPM_SyncRef1;
2305 break;
2306 case 3: /* AES 3 */
2307 hdspm->control_register |=
2308 HDSPM_SyncRef1+HDSPM_SyncRef0;
2309 break;
2310 case 4: /* AES 4 */
2311 hdspm->control_register |= HDSPM_SyncRef2;
2312 break;
2313 case 5: /* AES 5 */
2314 hdspm->control_register |=
2315 HDSPM_SyncRef2+HDSPM_SyncRef0;
2316 break;
2317 case 6: /* AES 6 */
2318 hdspm->control_register |=
2319 HDSPM_SyncRef2+HDSPM_SyncRef1;
2320 break;
2321 case 7: /* AES 7 */
2322 hdspm->control_register |=
2323 HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
2324 break;
2325 case 8: /* AES 8 */
2326 hdspm->control_register |= HDSPM_SyncRef3;
2327 break;
2328 case 9: /* TCO */
2329 hdspm->control_register |=
2330 HDSPM_SyncRef3+HDSPM_SyncRef0;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002331 break;
2332 default:
2333 return -1;
2334 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002335
2336 break;
2337
2338 case MADI:
2339 case MADIface:
2340 hdspm->control_register &= ~HDSPM_SyncRefMask;
2341 if (hdspm->tco) {
2342 switch (pref) {
2343 case 0: /* WC */
2344 break;
2345 case 1: /* MADI */
2346 hdspm->control_register |= HDSPM_SyncRef0;
2347 break;
2348 case 2: /* TCO */
2349 hdspm->control_register |= HDSPM_SyncRef1;
2350 break;
2351 case 3: /* SYNC_IN */
2352 hdspm->control_register |=
2353 HDSPM_SyncRef0+HDSPM_SyncRef1;
2354 break;
2355 default:
2356 return -1;
2357 }
2358 } else {
2359 switch (pref) {
2360 case 0: /* WC */
2361 break;
2362 case 1: /* MADI */
2363 hdspm->control_register |= HDSPM_SyncRef0;
2364 break;
2365 case 2: /* SYNC_IN */
2366 hdspm->control_register |=
2367 HDSPM_SyncRef0+HDSPM_SyncRef1;
2368 break;
2369 default:
2370 return -1;
2371 }
2372 }
2373
2374 break;
2375
2376 case RayDAT:
2377 if (hdspm->tco) {
2378 switch (pref) {
2379 case 0: p = 0; break; /* WC */
2380 case 1: p = 3; break; /* ADAT 1 */
2381 case 2: p = 4; break; /* ADAT 2 */
2382 case 3: p = 5; break; /* ADAT 3 */
2383 case 4: p = 6; break; /* ADAT 4 */
2384 case 5: p = 1; break; /* AES */
2385 case 6: p = 2; break; /* SPDIF */
2386 case 7: p = 9; break; /* TCO */
2387 case 8: p = 10; break; /* SYNC_IN */
2388 default: return -1;
2389 }
2390 } else {
2391 switch (pref) {
2392 case 0: p = 0; break; /* WC */
2393 case 1: p = 3; break; /* ADAT 1 */
2394 case 2: p = 4; break; /* ADAT 2 */
2395 case 3: p = 5; break; /* ADAT 3 */
2396 case 4: p = 6; break; /* ADAT 4 */
2397 case 5: p = 1; break; /* AES */
2398 case 6: p = 2; break; /* SPDIF */
2399 case 7: p = 10; break; /* SYNC_IN */
2400 default: return -1;
2401 }
2402 }
2403 break;
2404
2405 case AIO:
2406 if (hdspm->tco) {
2407 switch (pref) {
2408 case 0: p = 0; break; /* WC */
2409 case 1: p = 3; break; /* ADAT */
2410 case 2: p = 1; break; /* AES */
2411 case 3: p = 2; break; /* SPDIF */
2412 case 4: p = 9; break; /* TCO */
2413 case 5: p = 10; break; /* SYNC_IN */
2414 default: return -1;
2415 }
2416 } else {
2417 switch (pref) {
2418 case 0: p = 0; break; /* WC */
2419 case 1: p = 3; break; /* ADAT */
2420 case 2: p = 1; break; /* AES */
2421 case 3: p = 2; break; /* SPDIF */
2422 case 4: p = 10; break; /* SYNC_IN */
2423 default: return -1;
2424 }
2425 }
2426 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002427 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002428
2429 switch (hdspm->io_type) {
2430 case RayDAT:
2431 case AIO:
2432 hdspm->settings_register &= ~HDSPM_c0_SyncRefMask;
2433 hdspm->settings_register |= HDSPM_c0_SyncRef0 * p;
2434 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2435 break;
2436
2437 case MADI:
2438 case MADIface:
2439 case AES32:
2440 hdspm_write(hdspm, HDSPM_controlRegister,
2441 hdspm->control_register);
2442 }
2443
Takashi Iwai763f3562005-06-03 11:25:34 +02002444 return 0;
2445}
2446
Adrian Knoth0dca1792011-01-26 19:32:14 +01002447
Takashi Iwai98274f02005-11-17 14:52:34 +01002448static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
2449 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002450{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002451 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002452
Adrian Knoth0dca1792011-01-26 19:32:14 +01002453 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2454 uinfo->count = 1;
2455 uinfo->value.enumerated.items = hdspm->texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +02002456
Adrian Knoth0dca1792011-01-26 19:32:14 +01002457 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2458 uinfo->value.enumerated.item =
2459 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002460
Adrian Knoth0dca1792011-01-26 19:32:14 +01002461 strcpy(uinfo->value.enumerated.name,
2462 hdspm->texts_autosync[uinfo->value.enumerated.item]);
Remy Bruno3cee5a62006-10-16 12:46:32 +02002463
Takashi Iwai763f3562005-06-03 11:25:34 +02002464 return 0;
2465}
2466
Takashi Iwai98274f02005-11-17 14:52:34 +01002467static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
2468 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002469{
Takashi Iwai98274f02005-11-17 14:52:34 +01002470 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002471 int psf = hdspm_pref_sync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002472
Adrian Knoth0dca1792011-01-26 19:32:14 +01002473 if (psf >= 0) {
2474 ucontrol->value.enumerated.item[0] = psf;
2475 return 0;
2476 }
2477
2478 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002479}
2480
Takashi Iwai98274f02005-11-17 14:52:34 +01002481static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
2482 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002483{
Takashi Iwai98274f02005-11-17 14:52:34 +01002484 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002485 int val, change = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002486
2487 if (!snd_hdspm_use_is_exclusive(hdspm))
2488 return -EBUSY;
2489
Adrian Knoth0dca1792011-01-26 19:32:14 +01002490 val = ucontrol->value.enumerated.item[0];
2491
2492 if (val < 0)
2493 val = 0;
2494 else if (val >= hdspm->texts_autosync_items)
2495 val = hdspm->texts_autosync_items-1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002496
2497 spin_lock_irq(&hdspm->lock);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002498 if (val != hdspm_pref_sync_ref(hdspm))
2499 change = (0 == hdspm_set_pref_sync_ref(hdspm, val)) ? 1 : 0;
2500
Takashi Iwai763f3562005-06-03 11:25:34 +02002501 spin_unlock_irq(&hdspm->lock);
2502 return change;
2503}
2504
Adrian Knoth0dca1792011-01-26 19:32:14 +01002505
Takashi Iwai763f3562005-06-03 11:25:34 +02002506#define HDSPM_AUTOSYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002507{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002508 .name = xname, \
2509 .index = xindex, \
2510 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2511 .info = snd_hdspm_info_autosync_ref, \
2512 .get = snd_hdspm_get_autosync_ref, \
2513}
2514
Adrian Knoth0dca1792011-01-26 19:32:14 +01002515static int hdspm_autosync_ref(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002516{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002517 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002518 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002519 unsigned int syncref =
2520 (status >> HDSPM_AES32_syncref_bit) & 0xF;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002521 if (syncref == 0)
2522 return HDSPM_AES32_AUTOSYNC_FROM_WORD;
2523 if (syncref <= 8)
2524 return syncref;
2525 return HDSPM_AES32_AUTOSYNC_FROM_NONE;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002526 } else if (MADI == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002527 /* This looks at the autosync selected sync reference */
2528 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Takashi Iwai763f3562005-06-03 11:25:34 +02002529
Remy Bruno3cee5a62006-10-16 12:46:32 +02002530 switch (status2 & HDSPM_SelSyncRefMask) {
2531 case HDSPM_SelSyncRef_WORD:
2532 return HDSPM_AUTOSYNC_FROM_WORD;
2533 case HDSPM_SelSyncRef_MADI:
2534 return HDSPM_AUTOSYNC_FROM_MADI;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002535 case HDSPM_SelSyncRef_TCO:
2536 return HDSPM_AUTOSYNC_FROM_TCO;
2537 case HDSPM_SelSyncRef_SyncIn:
2538 return HDSPM_AUTOSYNC_FROM_SYNC_IN;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002539 case HDSPM_SelSyncRef_NVALID:
2540 return HDSPM_AUTOSYNC_FROM_NONE;
2541 default:
2542 return 0;
2543 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002544
Takashi Iwai763f3562005-06-03 11:25:34 +02002545 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002546 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002547}
2548
Adrian Knoth0dca1792011-01-26 19:32:14 +01002549
Takashi Iwai98274f02005-11-17 14:52:34 +01002550static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
2551 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002552{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002553 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002554
Adrian Knoth0dca1792011-01-26 19:32:14 +01002555 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002556 static char *texts[] = { "WordClock", "AES1", "AES2", "AES3",
2557 "AES4", "AES5", "AES6", "AES7", "AES8", "None"};
2558
2559 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2560 uinfo->count = 1;
2561 uinfo->value.enumerated.items = 10;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002562 if (uinfo->value.enumerated.item >=
2563 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002564 uinfo->value.enumerated.item =
2565 uinfo->value.enumerated.items - 1;
2566 strcpy(uinfo->value.enumerated.name,
2567 texts[uinfo->value.enumerated.item]);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002568 } else if (MADI == hdspm->io_type) {
2569 static char *texts[] = {"Word Clock", "MADI", "TCO",
2570 "Sync In", "None" };
Remy Bruno3cee5a62006-10-16 12:46:32 +02002571
2572 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2573 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002574 uinfo->value.enumerated.items = 5;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002575 if (uinfo->value.enumerated.item >=
Adrian Knoth0dca1792011-01-26 19:32:14 +01002576 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002577 uinfo->value.enumerated.item =
2578 uinfo->value.enumerated.items - 1;
2579 strcpy(uinfo->value.enumerated.name,
2580 texts[uinfo->value.enumerated.item]);
2581 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002582 return 0;
2583}
2584
Takashi Iwai98274f02005-11-17 14:52:34 +01002585static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
2586 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002587{
Takashi Iwai98274f02005-11-17 14:52:34 +01002588 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002589
Remy Bruno65345992007-08-31 12:21:08 +02002590 ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002591 return 0;
2592}
2593
Adrian Knoth0dca1792011-01-26 19:32:14 +01002594
Takashi Iwai763f3562005-06-03 11:25:34 +02002595#define HDSPM_LINE_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002596{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002597 .name = xname, \
2598 .index = xindex, \
2599 .info = snd_hdspm_info_line_out, \
2600 .get = snd_hdspm_get_line_out, \
2601 .put = snd_hdspm_put_line_out \
2602}
2603
Takashi Iwai98274f02005-11-17 14:52:34 +01002604static int hdspm_line_out(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002605{
2606 return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0;
2607}
2608
2609
Takashi Iwai98274f02005-11-17 14:52:34 +01002610static int hdspm_set_line_output(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002611{
2612 if (out)
2613 hdspm->control_register |= HDSPM_LineOut;
2614 else
2615 hdspm->control_register &= ~HDSPM_LineOut;
2616 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2617
2618 return 0;
2619}
2620
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002621#define snd_hdspm_info_line_out snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002622
Takashi Iwai98274f02005-11-17 14:52:34 +01002623static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol,
2624 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002625{
Takashi Iwai98274f02005-11-17 14:52:34 +01002626 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002627
2628 spin_lock_irq(&hdspm->lock);
2629 ucontrol->value.integer.value[0] = hdspm_line_out(hdspm);
2630 spin_unlock_irq(&hdspm->lock);
2631 return 0;
2632}
2633
Takashi Iwai98274f02005-11-17 14:52:34 +01002634static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
2635 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002636{
Takashi Iwai98274f02005-11-17 14:52:34 +01002637 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002638 int change;
2639 unsigned int val;
2640
2641 if (!snd_hdspm_use_is_exclusive(hdspm))
2642 return -EBUSY;
2643 val = ucontrol->value.integer.value[0] & 1;
2644 spin_lock_irq(&hdspm->lock);
2645 change = (int) val != hdspm_line_out(hdspm);
2646 hdspm_set_line_output(hdspm, val);
2647 spin_unlock_irq(&hdspm->lock);
2648 return change;
2649}
2650
Adrian Knoth0dca1792011-01-26 19:32:14 +01002651
Takashi Iwai763f3562005-06-03 11:25:34 +02002652#define HDSPM_TX_64(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002653{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002654 .name = xname, \
2655 .index = xindex, \
2656 .info = snd_hdspm_info_tx_64, \
2657 .get = snd_hdspm_get_tx_64, \
2658 .put = snd_hdspm_put_tx_64 \
2659}
2660
Takashi Iwai98274f02005-11-17 14:52:34 +01002661static int hdspm_tx_64(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002662{
2663 return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0;
2664}
2665
Takashi Iwai98274f02005-11-17 14:52:34 +01002666static int hdspm_set_tx_64(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002667{
2668 if (out)
2669 hdspm->control_register |= HDSPM_TX_64ch;
2670 else
2671 hdspm->control_register &= ~HDSPM_TX_64ch;
2672 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2673
2674 return 0;
2675}
2676
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002677#define snd_hdspm_info_tx_64 snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002678
Takashi Iwai98274f02005-11-17 14:52:34 +01002679static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol,
2680 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002681{
Takashi Iwai98274f02005-11-17 14:52:34 +01002682 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002683
2684 spin_lock_irq(&hdspm->lock);
2685 ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm);
2686 spin_unlock_irq(&hdspm->lock);
2687 return 0;
2688}
2689
Takashi Iwai98274f02005-11-17 14:52:34 +01002690static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
2691 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002692{
Takashi Iwai98274f02005-11-17 14:52:34 +01002693 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002694 int change;
2695 unsigned int val;
2696
2697 if (!snd_hdspm_use_is_exclusive(hdspm))
2698 return -EBUSY;
2699 val = ucontrol->value.integer.value[0] & 1;
2700 spin_lock_irq(&hdspm->lock);
2701 change = (int) val != hdspm_tx_64(hdspm);
2702 hdspm_set_tx_64(hdspm, val);
2703 spin_unlock_irq(&hdspm->lock);
2704 return change;
2705}
2706
Adrian Knoth0dca1792011-01-26 19:32:14 +01002707
Takashi Iwai763f3562005-06-03 11:25:34 +02002708#define HDSPM_C_TMS(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002709{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002710 .name = xname, \
2711 .index = xindex, \
2712 .info = snd_hdspm_info_c_tms, \
2713 .get = snd_hdspm_get_c_tms, \
2714 .put = snd_hdspm_put_c_tms \
2715}
2716
Takashi Iwai98274f02005-11-17 14:52:34 +01002717static int hdspm_c_tms(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002718{
2719 return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0;
2720}
2721
Takashi Iwai98274f02005-11-17 14:52:34 +01002722static int hdspm_set_c_tms(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002723{
2724 if (out)
2725 hdspm->control_register |= HDSPM_clr_tms;
2726 else
2727 hdspm->control_register &= ~HDSPM_clr_tms;
2728 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2729
2730 return 0;
2731}
2732
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002733#define snd_hdspm_info_c_tms snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002734
Takashi Iwai98274f02005-11-17 14:52:34 +01002735static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol,
2736 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002737{
Takashi Iwai98274f02005-11-17 14:52:34 +01002738 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002739
2740 spin_lock_irq(&hdspm->lock);
2741 ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm);
2742 spin_unlock_irq(&hdspm->lock);
2743 return 0;
2744}
2745
Takashi Iwai98274f02005-11-17 14:52:34 +01002746static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,
2747 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002748{
Takashi Iwai98274f02005-11-17 14:52:34 +01002749 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002750 int change;
2751 unsigned int val;
2752
2753 if (!snd_hdspm_use_is_exclusive(hdspm))
2754 return -EBUSY;
2755 val = ucontrol->value.integer.value[0] & 1;
2756 spin_lock_irq(&hdspm->lock);
2757 change = (int) val != hdspm_c_tms(hdspm);
2758 hdspm_set_c_tms(hdspm, val);
2759 spin_unlock_irq(&hdspm->lock);
2760 return change;
2761}
2762
Adrian Knoth0dca1792011-01-26 19:32:14 +01002763
Takashi Iwai763f3562005-06-03 11:25:34 +02002764#define HDSPM_SAFE_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002765{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002766 .name = xname, \
2767 .index = xindex, \
2768 .info = snd_hdspm_info_safe_mode, \
2769 .get = snd_hdspm_get_safe_mode, \
2770 .put = snd_hdspm_put_safe_mode \
2771}
2772
Takashi Iwai98274f02005-11-17 14:52:34 +01002773static int hdspm_safe_mode(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002774{
2775 return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0;
2776}
2777
Takashi Iwai98274f02005-11-17 14:52:34 +01002778static int hdspm_set_safe_mode(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002779{
2780 if (out)
2781 hdspm->control_register |= HDSPM_AutoInp;
2782 else
2783 hdspm->control_register &= ~HDSPM_AutoInp;
2784 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2785
2786 return 0;
2787}
2788
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002789#define snd_hdspm_info_safe_mode snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002790
Takashi Iwai98274f02005-11-17 14:52:34 +01002791static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol,
2792 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002793{
Takashi Iwai98274f02005-11-17 14:52:34 +01002794 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002795
2796 spin_lock_irq(&hdspm->lock);
2797 ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm);
2798 spin_unlock_irq(&hdspm->lock);
2799 return 0;
2800}
2801
Takashi Iwai98274f02005-11-17 14:52:34 +01002802static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
2803 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002804{
Takashi Iwai98274f02005-11-17 14:52:34 +01002805 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002806 int change;
2807 unsigned int val;
2808
2809 if (!snd_hdspm_use_is_exclusive(hdspm))
2810 return -EBUSY;
2811 val = ucontrol->value.integer.value[0] & 1;
2812 spin_lock_irq(&hdspm->lock);
2813 change = (int) val != hdspm_safe_mode(hdspm);
2814 hdspm_set_safe_mode(hdspm, val);
2815 spin_unlock_irq(&hdspm->lock);
2816 return change;
2817}
2818
Adrian Knoth0dca1792011-01-26 19:32:14 +01002819
Remy Bruno3cee5a62006-10-16 12:46:32 +02002820#define HDSPM_EMPHASIS(xname, xindex) \
2821{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2822 .name = xname, \
2823 .index = xindex, \
2824 .info = snd_hdspm_info_emphasis, \
2825 .get = snd_hdspm_get_emphasis, \
2826 .put = snd_hdspm_put_emphasis \
2827}
2828
2829static int hdspm_emphasis(struct hdspm * hdspm)
2830{
2831 return (hdspm->control_register & HDSPM_Emphasis) ? 1 : 0;
2832}
2833
2834static int hdspm_set_emphasis(struct hdspm * hdspm, int emp)
2835{
2836 if (emp)
2837 hdspm->control_register |= HDSPM_Emphasis;
2838 else
2839 hdspm->control_register &= ~HDSPM_Emphasis;
2840 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2841
2842 return 0;
2843}
2844
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002845#define snd_hdspm_info_emphasis snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02002846
2847static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol,
2848 struct snd_ctl_elem_value *ucontrol)
2849{
2850 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2851
2852 spin_lock_irq(&hdspm->lock);
2853 ucontrol->value.enumerated.item[0] = hdspm_emphasis(hdspm);
2854 spin_unlock_irq(&hdspm->lock);
2855 return 0;
2856}
2857
2858static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
2859 struct snd_ctl_elem_value *ucontrol)
2860{
2861 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2862 int change;
2863 unsigned int val;
2864
2865 if (!snd_hdspm_use_is_exclusive(hdspm))
2866 return -EBUSY;
2867 val = ucontrol->value.integer.value[0] & 1;
2868 spin_lock_irq(&hdspm->lock);
2869 change = (int) val != hdspm_emphasis(hdspm);
2870 hdspm_set_emphasis(hdspm, val);
2871 spin_unlock_irq(&hdspm->lock);
2872 return change;
2873}
2874
Adrian Knoth0dca1792011-01-26 19:32:14 +01002875
Remy Bruno3cee5a62006-10-16 12:46:32 +02002876#define HDSPM_DOLBY(xname, xindex) \
2877{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2878 .name = xname, \
2879 .index = xindex, \
2880 .info = snd_hdspm_info_dolby, \
2881 .get = snd_hdspm_get_dolby, \
2882 .put = snd_hdspm_put_dolby \
2883}
2884
2885static int hdspm_dolby(struct hdspm * hdspm)
2886{
2887 return (hdspm->control_register & HDSPM_Dolby) ? 1 : 0;
2888}
2889
2890static int hdspm_set_dolby(struct hdspm * hdspm, int dol)
2891{
2892 if (dol)
2893 hdspm->control_register |= HDSPM_Dolby;
2894 else
2895 hdspm->control_register &= ~HDSPM_Dolby;
2896 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2897
2898 return 0;
2899}
2900
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002901#define snd_hdspm_info_dolby snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02002902
2903static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol,
2904 struct snd_ctl_elem_value *ucontrol)
2905{
2906 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2907
2908 spin_lock_irq(&hdspm->lock);
2909 ucontrol->value.enumerated.item[0] = hdspm_dolby(hdspm);
2910 spin_unlock_irq(&hdspm->lock);
2911 return 0;
2912}
2913
2914static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
2915 struct snd_ctl_elem_value *ucontrol)
2916{
2917 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2918 int change;
2919 unsigned int val;
2920
2921 if (!snd_hdspm_use_is_exclusive(hdspm))
2922 return -EBUSY;
2923 val = ucontrol->value.integer.value[0] & 1;
2924 spin_lock_irq(&hdspm->lock);
2925 change = (int) val != hdspm_dolby(hdspm);
2926 hdspm_set_dolby(hdspm, val);
2927 spin_unlock_irq(&hdspm->lock);
2928 return change;
2929}
2930
Adrian Knoth0dca1792011-01-26 19:32:14 +01002931
Remy Bruno3cee5a62006-10-16 12:46:32 +02002932#define HDSPM_PROFESSIONAL(xname, xindex) \
2933{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2934 .name = xname, \
2935 .index = xindex, \
2936 .info = snd_hdspm_info_professional, \
2937 .get = snd_hdspm_get_professional, \
2938 .put = snd_hdspm_put_professional \
2939}
2940
2941static int hdspm_professional(struct hdspm * hdspm)
2942{
2943 return (hdspm->control_register & HDSPM_Professional) ? 1 : 0;
2944}
2945
2946static int hdspm_set_professional(struct hdspm * hdspm, int dol)
2947{
2948 if (dol)
2949 hdspm->control_register |= HDSPM_Professional;
2950 else
2951 hdspm->control_register &= ~HDSPM_Professional;
2952 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2953
2954 return 0;
2955}
2956
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002957#define snd_hdspm_info_professional snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02002958
2959static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol,
2960 struct snd_ctl_elem_value *ucontrol)
2961{
2962 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2963
2964 spin_lock_irq(&hdspm->lock);
2965 ucontrol->value.enumerated.item[0] = hdspm_professional(hdspm);
2966 spin_unlock_irq(&hdspm->lock);
2967 return 0;
2968}
2969
2970static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,
2971 struct snd_ctl_elem_value *ucontrol)
2972{
2973 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2974 int change;
2975 unsigned int val;
2976
2977 if (!snd_hdspm_use_is_exclusive(hdspm))
2978 return -EBUSY;
2979 val = ucontrol->value.integer.value[0] & 1;
2980 spin_lock_irq(&hdspm->lock);
2981 change = (int) val != hdspm_professional(hdspm);
2982 hdspm_set_professional(hdspm, val);
2983 spin_unlock_irq(&hdspm->lock);
2984 return change;
2985}
2986
Takashi Iwai763f3562005-06-03 11:25:34 +02002987#define HDSPM_INPUT_SELECT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002988{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002989 .name = xname, \
2990 .index = xindex, \
2991 .info = snd_hdspm_info_input_select, \
2992 .get = snd_hdspm_get_input_select, \
2993 .put = snd_hdspm_put_input_select \
2994}
2995
Takashi Iwai98274f02005-11-17 14:52:34 +01002996static int hdspm_input_select(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002997{
2998 return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
2999}
3000
Takashi Iwai98274f02005-11-17 14:52:34 +01003001static int hdspm_set_input_select(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02003002{
3003 if (out)
3004 hdspm->control_register |= HDSPM_InputSelect0;
3005 else
3006 hdspm->control_register &= ~HDSPM_InputSelect0;
3007 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3008
3009 return 0;
3010}
3011
Takashi Iwai98274f02005-11-17 14:52:34 +01003012static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
3013 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003014{
3015 static char *texts[] = { "optical", "coaxial" };
3016
3017 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3018 uinfo->count = 1;
3019 uinfo->value.enumerated.items = 2;
3020
3021 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3022 uinfo->value.enumerated.item =
3023 uinfo->value.enumerated.items - 1;
3024 strcpy(uinfo->value.enumerated.name,
3025 texts[uinfo->value.enumerated.item]);
3026
3027 return 0;
3028}
3029
Takashi Iwai98274f02005-11-17 14:52:34 +01003030static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
3031 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003032{
Takashi Iwai98274f02005-11-17 14:52:34 +01003033 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003034
3035 spin_lock_irq(&hdspm->lock);
3036 ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
3037 spin_unlock_irq(&hdspm->lock);
3038 return 0;
3039}
3040
Takashi Iwai98274f02005-11-17 14:52:34 +01003041static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
3042 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003043{
Takashi Iwai98274f02005-11-17 14:52:34 +01003044 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003045 int change;
3046 unsigned int val;
3047
3048 if (!snd_hdspm_use_is_exclusive(hdspm))
3049 return -EBUSY;
3050 val = ucontrol->value.integer.value[0] & 1;
3051 spin_lock_irq(&hdspm->lock);
3052 change = (int) val != hdspm_input_select(hdspm);
3053 hdspm_set_input_select(hdspm, val);
3054 spin_unlock_irq(&hdspm->lock);
3055 return change;
3056}
3057
Adrian Knoth0dca1792011-01-26 19:32:14 +01003058
Remy Bruno3cee5a62006-10-16 12:46:32 +02003059#define HDSPM_DS_WIRE(xname, xindex) \
3060{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3061 .name = xname, \
3062 .index = xindex, \
3063 .info = snd_hdspm_info_ds_wire, \
3064 .get = snd_hdspm_get_ds_wire, \
3065 .put = snd_hdspm_put_ds_wire \
3066}
3067
3068static int hdspm_ds_wire(struct hdspm * hdspm)
3069{
3070 return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
3071}
3072
3073static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
3074{
3075 if (ds)
3076 hdspm->control_register |= HDSPM_DS_DoubleWire;
3077 else
3078 hdspm->control_register &= ~HDSPM_DS_DoubleWire;
3079 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3080
3081 return 0;
3082}
3083
3084static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
3085 struct snd_ctl_elem_info *uinfo)
3086{
3087 static char *texts[] = { "Single", "Double" };
3088
3089 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3090 uinfo->count = 1;
3091 uinfo->value.enumerated.items = 2;
3092
3093 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3094 uinfo->value.enumerated.item =
3095 uinfo->value.enumerated.items - 1;
3096 strcpy(uinfo->value.enumerated.name,
3097 texts[uinfo->value.enumerated.item]);
3098
3099 return 0;
3100}
3101
3102static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
3103 struct snd_ctl_elem_value *ucontrol)
3104{
3105 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3106
3107 spin_lock_irq(&hdspm->lock);
3108 ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
3109 spin_unlock_irq(&hdspm->lock);
3110 return 0;
3111}
3112
3113static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
3114 struct snd_ctl_elem_value *ucontrol)
3115{
3116 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3117 int change;
3118 unsigned int val;
3119
3120 if (!snd_hdspm_use_is_exclusive(hdspm))
3121 return -EBUSY;
3122 val = ucontrol->value.integer.value[0] & 1;
3123 spin_lock_irq(&hdspm->lock);
3124 change = (int) val != hdspm_ds_wire(hdspm);
3125 hdspm_set_ds_wire(hdspm, val);
3126 spin_unlock_irq(&hdspm->lock);
3127 return change;
3128}
3129
Adrian Knoth0dca1792011-01-26 19:32:14 +01003130
Remy Bruno3cee5a62006-10-16 12:46:32 +02003131#define HDSPM_QS_WIRE(xname, xindex) \
3132{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3133 .name = xname, \
3134 .index = xindex, \
3135 .info = snd_hdspm_info_qs_wire, \
3136 .get = snd_hdspm_get_qs_wire, \
3137 .put = snd_hdspm_put_qs_wire \
3138}
3139
3140static int hdspm_qs_wire(struct hdspm * hdspm)
3141{
3142 if (hdspm->control_register & HDSPM_QS_DoubleWire)
3143 return 1;
3144 if (hdspm->control_register & HDSPM_QS_QuadWire)
3145 return 2;
3146 return 0;
3147}
3148
3149static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
3150{
3151 hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
3152 switch (mode) {
3153 case 0:
3154 break;
3155 case 1:
3156 hdspm->control_register |= HDSPM_QS_DoubleWire;
3157 break;
3158 case 2:
3159 hdspm->control_register |= HDSPM_QS_QuadWire;
3160 break;
3161 }
3162 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3163
3164 return 0;
3165}
3166
3167static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
3168 struct snd_ctl_elem_info *uinfo)
3169{
3170 static char *texts[] = { "Single", "Double", "Quad" };
3171
3172 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3173 uinfo->count = 1;
3174 uinfo->value.enumerated.items = 3;
3175
3176 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3177 uinfo->value.enumerated.item =
3178 uinfo->value.enumerated.items - 1;
3179 strcpy(uinfo->value.enumerated.name,
3180 texts[uinfo->value.enumerated.item]);
3181
3182 return 0;
3183}
3184
3185static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
3186 struct snd_ctl_elem_value *ucontrol)
3187{
3188 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3189
3190 spin_lock_irq(&hdspm->lock);
3191 ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
3192 spin_unlock_irq(&hdspm->lock);
3193 return 0;
3194}
3195
3196static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
3197 struct snd_ctl_elem_value *ucontrol)
3198{
3199 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3200 int change;
3201 int val;
3202
3203 if (!snd_hdspm_use_is_exclusive(hdspm))
3204 return -EBUSY;
3205 val = ucontrol->value.integer.value[0];
3206 if (val < 0)
3207 val = 0;
3208 if (val > 2)
3209 val = 2;
3210 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003211 change = val != hdspm_qs_wire(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003212 hdspm_set_qs_wire(hdspm, val);
3213 spin_unlock_irq(&hdspm->lock);
3214 return change;
3215}
3216
Takashi Iwai763f3562005-06-03 11:25:34 +02003217
3218#define HDSPM_MIXER(xname, xindex) \
3219{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
3220 .name = xname, \
3221 .index = xindex, \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003222 .device = 0, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003223 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
3224 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3225 .info = snd_hdspm_info_mixer, \
3226 .get = snd_hdspm_get_mixer, \
3227 .put = snd_hdspm_put_mixer \
3228}
3229
Takashi Iwai98274f02005-11-17 14:52:34 +01003230static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
3231 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003232{
3233 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3234 uinfo->count = 3;
3235 uinfo->value.integer.min = 0;
3236 uinfo->value.integer.max = 65535;
3237 uinfo->value.integer.step = 1;
3238 return 0;
3239}
3240
Takashi Iwai98274f02005-11-17 14:52:34 +01003241static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
3242 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003243{
Takashi Iwai98274f02005-11-17 14:52:34 +01003244 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003245 int source;
3246 int destination;
3247
3248 source = ucontrol->value.integer.value[0];
3249 if (source < 0)
3250 source = 0;
3251 else if (source >= 2 * HDSPM_MAX_CHANNELS)
3252 source = 2 * HDSPM_MAX_CHANNELS - 1;
3253
3254 destination = ucontrol->value.integer.value[1];
3255 if (destination < 0)
3256 destination = 0;
3257 else if (destination >= HDSPM_MAX_CHANNELS)
3258 destination = HDSPM_MAX_CHANNELS - 1;
3259
3260 spin_lock_irq(&hdspm->lock);
3261 if (source >= HDSPM_MAX_CHANNELS)
3262 ucontrol->value.integer.value[2] =
3263 hdspm_read_pb_gain(hdspm, destination,
3264 source - HDSPM_MAX_CHANNELS);
3265 else
3266 ucontrol->value.integer.value[2] =
3267 hdspm_read_in_gain(hdspm, destination, source);
3268
3269 spin_unlock_irq(&hdspm->lock);
3270
3271 return 0;
3272}
3273
Takashi Iwai98274f02005-11-17 14:52:34 +01003274static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
3275 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003276{
Takashi Iwai98274f02005-11-17 14:52:34 +01003277 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003278 int change;
3279 int source;
3280 int destination;
3281 int gain;
3282
3283 if (!snd_hdspm_use_is_exclusive(hdspm))
3284 return -EBUSY;
3285
3286 source = ucontrol->value.integer.value[0];
3287 destination = ucontrol->value.integer.value[1];
3288
3289 if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
3290 return -1;
3291 if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
3292 return -1;
3293
3294 gain = ucontrol->value.integer.value[2];
3295
3296 spin_lock_irq(&hdspm->lock);
3297
3298 if (source >= HDSPM_MAX_CHANNELS)
3299 change = gain != hdspm_read_pb_gain(hdspm, destination,
3300 source -
3301 HDSPM_MAX_CHANNELS);
3302 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003303 change = gain != hdspm_read_in_gain(hdspm, destination,
3304 source);
Takashi Iwai763f3562005-06-03 11:25:34 +02003305
3306 if (change) {
3307 if (source >= HDSPM_MAX_CHANNELS)
3308 hdspm_write_pb_gain(hdspm, destination,
3309 source - HDSPM_MAX_CHANNELS,
3310 gain);
3311 else
3312 hdspm_write_in_gain(hdspm, destination, source,
3313 gain);
3314 }
3315 spin_unlock_irq(&hdspm->lock);
3316
3317 return change;
3318}
3319
3320/* The simple mixer control(s) provide gain control for the
3321 basic 1:1 mappings of playback streams to output
Adrian Knoth0dca1792011-01-26 19:32:14 +01003322 streams.
Takashi Iwai763f3562005-06-03 11:25:34 +02003323*/
3324
3325#define HDSPM_PLAYBACK_MIXER \
3326{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3327 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
3328 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3329 .info = snd_hdspm_info_playback_mixer, \
3330 .get = snd_hdspm_get_playback_mixer, \
3331 .put = snd_hdspm_put_playback_mixer \
3332}
3333
Takashi Iwai98274f02005-11-17 14:52:34 +01003334static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
3335 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003336{
3337 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3338 uinfo->count = 1;
3339 uinfo->value.integer.min = 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003340 uinfo->value.integer.max = 64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003341 uinfo->value.integer.step = 1;
3342 return 0;
3343}
3344
Takashi Iwai98274f02005-11-17 14:52:34 +01003345static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
3346 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003347{
Takashi Iwai98274f02005-11-17 14:52:34 +01003348 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003349 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003350
3351 channel = ucontrol->id.index - 1;
3352
Takashi Iwaida3cec32008-08-08 17:12:14 +02003353 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3354 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003355
Takashi Iwai763f3562005-06-03 11:25:34 +02003356 spin_lock_irq(&hdspm->lock);
3357 ucontrol->value.integer.value[0] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003358 (hdspm_read_pb_gain(hdspm, channel, channel)*64)/UNITY_GAIN;
Takashi Iwai763f3562005-06-03 11:25:34 +02003359 spin_unlock_irq(&hdspm->lock);
3360
Takashi Iwai763f3562005-06-03 11:25:34 +02003361 return 0;
3362}
3363
Takashi Iwai98274f02005-11-17 14:52:34 +01003364static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
3365 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003366{
Takashi Iwai98274f02005-11-17 14:52:34 +01003367 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003368 int change;
3369 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003370 int gain;
3371
3372 if (!snd_hdspm_use_is_exclusive(hdspm))
3373 return -EBUSY;
3374
3375 channel = ucontrol->id.index - 1;
3376
Takashi Iwaida3cec32008-08-08 17:12:14 +02003377 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3378 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003379
Adrian Knoth0dca1792011-01-26 19:32:14 +01003380 gain = ucontrol->value.integer.value[0]*UNITY_GAIN/64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003381
3382 spin_lock_irq(&hdspm->lock);
3383 change =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003384 gain != hdspm_read_pb_gain(hdspm, channel,
3385 channel);
Takashi Iwai763f3562005-06-03 11:25:34 +02003386 if (change)
Adrian Knoth0dca1792011-01-26 19:32:14 +01003387 hdspm_write_pb_gain(hdspm, channel, channel,
Takashi Iwai763f3562005-06-03 11:25:34 +02003388 gain);
3389 spin_unlock_irq(&hdspm->lock);
3390 return change;
3391}
3392
Adrian Knoth0dca1792011-01-26 19:32:14 +01003393#define HDSPM_SYNC_CHECK(xname, xindex) \
3394{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3395 .name = xname, \
3396 .private_value = xindex, \
3397 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3398 .info = snd_hdspm_info_sync_check, \
3399 .get = snd_hdspm_get_sync_check \
Takashi Iwai763f3562005-06-03 11:25:34 +02003400}
3401
Adrian Knoth0dca1792011-01-26 19:32:14 +01003402
Takashi Iwai98274f02005-11-17 14:52:34 +01003403static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
3404 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003405{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003406 static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" };
Takashi Iwai763f3562005-06-03 11:25:34 +02003407 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3408 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003409 uinfo->value.enumerated.items = 4;
Takashi Iwai763f3562005-06-03 11:25:34 +02003410 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3411 uinfo->value.enumerated.item =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003412 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02003413 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01003414 texts[uinfo->value.enumerated.item]);
Takashi Iwai763f3562005-06-03 11:25:34 +02003415 return 0;
3416}
3417
Adrian Knoth0dca1792011-01-26 19:32:14 +01003418static int hdspm_wc_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003419{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003420 int status, status2;
3421
3422 switch (hdspm->io_type) {
3423 case AES32:
3424 status = hdspm_read(hdspm, HDSPM_statusRegister);
3425 if (status & HDSPM_wcSync)
Takashi Iwai763f3562005-06-03 11:25:34 +02003426 return 2;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003427 else if (status & HDSPM_wcLock)
3428 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003429 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003430 break;
3431
3432 case MADI:
3433 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003434 if (status2 & HDSPM_wcLock) {
3435 if (status2 & HDSPM_wcSync)
3436 return 2;
3437 else
3438 return 1;
3439 }
3440 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003441 break;
3442
3443 case RayDAT:
3444 case AIO:
3445 status = hdspm_read(hdspm, HDSPM_statusRegister);
3446
3447 if (status & 0x2000000)
3448 return 2;
3449 else if (status & 0x1000000)
3450 return 1;
3451 return 0;
3452
3453 break;
3454
3455 case MADIface:
3456 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02003457 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003458
Takashi Iwai763f3562005-06-03 11:25:34 +02003459
Adrian Knoth0dca1792011-01-26 19:32:14 +01003460 return 3;
Takashi Iwai763f3562005-06-03 11:25:34 +02003461}
3462
3463
Adrian Knoth0dca1792011-01-26 19:32:14 +01003464static int hdspm_madi_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003465{
3466 int status = hdspm_read(hdspm, HDSPM_statusRegister);
3467 if (status & HDSPM_madiLock) {
3468 if (status & HDSPM_madiSync)
3469 return 2;
3470 else
3471 return 1;
3472 }
3473 return 0;
3474}
3475
Adrian Knoth0dca1792011-01-26 19:32:14 +01003476
3477static int hdspm_s1_sync_check(struct hdspm *hdspm, int idx)
3478{
3479 int status, lock, sync;
3480
3481 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3482
3483 lock = (status & (0x1<<idx)) ? 1 : 0;
3484 sync = (status & (0x100<<idx)) ? 1 : 0;
3485
3486 if (lock && sync)
3487 return 2;
3488 else if (lock)
3489 return 1;
3490 return 0;
3491}
3492
3493
3494static int hdspm_sync_in_sync_check(struct hdspm *hdspm)
3495{
3496 int status, lock = 0, sync = 0;
3497
3498 switch (hdspm->io_type) {
3499 case RayDAT:
3500 case AIO:
3501 status = hdspm_read(hdspm, HDSPM_RD_STATUS_3);
3502 lock = (status & 0x400) ? 1 : 0;
3503 sync = (status & 0x800) ? 1 : 0;
3504 break;
3505
3506 case MADI:
3507 case AES32:
3508 status = hdspm_read(hdspm, HDSPM_statusRegister2);
3509 lock = (status & 0x400000) ? 1 : 0;
3510 sync = (status & 0x800000) ? 1 : 0;
3511 break;
3512
3513 case MADIface:
3514 break;
3515 }
3516
3517 if (lock && sync)
3518 return 2;
3519 else if (lock)
3520 return 1;
3521
3522 return 0;
3523}
3524
3525static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx)
3526{
3527 int status2, lock, sync;
3528 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
3529
3530 lock = (status2 & (0x0080 >> idx)) ? 1 : 0;
3531 sync = (status2 & (0x8000 >> idx)) ? 1 : 0;
3532
3533 if (sync)
3534 return 2;
3535 else if (lock)
3536 return 1;
3537 return 0;
3538}
3539
3540
3541static int hdspm_tco_sync_check(struct hdspm *hdspm)
3542{
3543 int status;
3544
3545 if (hdspm->tco) {
3546 switch (hdspm->io_type) {
3547 case MADI:
3548 case AES32:
3549 status = hdspm_read(hdspm, HDSPM_statusRegister);
3550 if (status & HDSPM_tcoLock) {
3551 if (status & HDSPM_tcoSync)
3552 return 2;
3553 else
3554 return 1;
3555 }
3556 return 0;
3557
3558 break;
3559
3560 case RayDAT:
3561 case AIO:
3562 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3563
3564 if (status & 0x8000000)
3565 return 2; /* Sync */
3566 if (status & 0x4000000)
3567 return 1; /* Lock */
3568 return 0; /* No signal */
3569 break;
3570
3571 default:
3572 break;
3573 }
3574 }
3575
3576 return 3; /* N/A */
3577}
3578
3579
3580static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
3581 struct snd_ctl_elem_value *ucontrol)
3582{
3583 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3584 int val = -1;
3585
3586 switch (hdspm->io_type) {
3587 case RayDAT:
3588 switch (kcontrol->private_value) {
3589 case 0: /* WC */
3590 val = hdspm_wc_sync_check(hdspm); break;
3591 case 7: /* TCO */
3592 val = hdspm_tco_sync_check(hdspm); break;
3593 case 8: /* SYNC IN */
3594 val = hdspm_sync_in_sync_check(hdspm); break;
3595 default:
3596 val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
3597 }
3598
3599 case AIO:
3600 switch (kcontrol->private_value) {
3601 case 0: /* WC */
3602 val = hdspm_wc_sync_check(hdspm); break;
3603 case 4: /* TCO */
3604 val = hdspm_tco_sync_check(hdspm); break;
3605 case 5: /* SYNC IN */
3606 val = hdspm_sync_in_sync_check(hdspm); break;
3607 default:
3608 val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
3609 }
3610
3611 case MADI:
3612 switch (kcontrol->private_value) {
3613 case 0: /* WC */
3614 val = hdspm_wc_sync_check(hdspm); break;
3615 case 1: /* MADI */
3616 val = hdspm_madi_sync_check(hdspm); break;
3617 case 2: /* TCO */
3618 val = hdspm_tco_sync_check(hdspm); break;
3619 case 3: /* SYNC_IN */
3620 val = hdspm_sync_in_sync_check(hdspm); break;
3621 }
3622
3623 case MADIface:
3624 val = hdspm_madi_sync_check(hdspm); /* MADI */
3625 break;
3626
3627 case AES32:
3628 switch (kcontrol->private_value) {
3629 case 0: /* WC */
3630 val = hdspm_wc_sync_check(hdspm); break;
3631 case 9: /* TCO */
3632 val = hdspm_tco_sync_check(hdspm); break;
3633 case 10 /* SYNC IN */:
3634 val = hdspm_sync_in_sync_check(hdspm); break;
3635 default:
3636 val = hdspm_aes_sync_check(hdspm,
3637 ucontrol->id.index-1);
3638 }
3639
3640 }
3641
3642 if (-1 == val)
3643 val = 3;
3644
3645 ucontrol->value.enumerated.item[0] = val;
3646 return 0;
3647}
3648
3649
3650
3651/**
3652 * TCO controls
3653 **/
3654static void hdspm_tco_write(struct hdspm *hdspm)
3655{
3656 unsigned int tc[4] = { 0, 0, 0, 0};
3657
3658 switch (hdspm->tco->input) {
3659 case 0:
3660 tc[2] |= HDSPM_TCO2_set_input_MSB;
3661 break;
3662 case 1:
3663 tc[2] |= HDSPM_TCO2_set_input_LSB;
3664 break;
3665 default:
3666 break;
3667 }
3668
3669 switch (hdspm->tco->framerate) {
3670 case 1:
3671 tc[1] |= HDSPM_TCO1_LTC_Format_LSB;
3672 break;
3673 case 2:
3674 tc[1] |= HDSPM_TCO1_LTC_Format_MSB;
3675 break;
3676 case 3:
3677 tc[1] |= HDSPM_TCO1_LTC_Format_MSB +
3678 HDSPM_TCO1_set_drop_frame_flag;
3679 break;
3680 case 4:
3681 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
3682 HDSPM_TCO1_LTC_Format_MSB;
3683 break;
3684 case 5:
3685 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
3686 HDSPM_TCO1_LTC_Format_MSB +
3687 HDSPM_TCO1_set_drop_frame_flag;
3688 break;
3689 default:
3690 break;
3691 }
3692
3693 switch (hdspm->tco->wordclock) {
3694 case 1:
3695 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_LSB;
3696 break;
3697 case 2:
3698 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_MSB;
3699 break;
3700 default:
3701 break;
3702 }
3703
3704 switch (hdspm->tco->samplerate) {
3705 case 1:
3706 tc[2] |= HDSPM_TCO2_set_freq;
3707 break;
3708 case 2:
3709 tc[2] |= HDSPM_TCO2_set_freq_from_app;
3710 break;
3711 default:
3712 break;
3713 }
3714
3715 switch (hdspm->tco->pull) {
3716 case 1:
3717 tc[2] |= HDSPM_TCO2_set_pull_up;
3718 break;
3719 case 2:
3720 tc[2] |= HDSPM_TCO2_set_pull_down;
3721 break;
3722 case 3:
3723 tc[2] |= HDSPM_TCO2_set_pull_up + HDSPM_TCO2_set_01_4;
3724 break;
3725 case 4:
3726 tc[2] |= HDSPM_TCO2_set_pull_down + HDSPM_TCO2_set_01_4;
3727 break;
3728 default:
3729 break;
3730 }
3731
3732 if (1 == hdspm->tco->term) {
3733 tc[2] |= HDSPM_TCO2_set_term_75R;
3734 }
3735
3736 hdspm_write(hdspm, HDSPM_WR_TCO, tc[0]);
3737 hdspm_write(hdspm, HDSPM_WR_TCO+4, tc[1]);
3738 hdspm_write(hdspm, HDSPM_WR_TCO+8, tc[2]);
3739 hdspm_write(hdspm, HDSPM_WR_TCO+12, tc[3]);
3740}
3741
3742
3743#define HDSPM_TCO_SAMPLE_RATE(xname, xindex) \
3744{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3745 .name = xname, \
3746 .index = xindex, \
3747 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
3748 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3749 .info = snd_hdspm_info_tco_sample_rate, \
3750 .get = snd_hdspm_get_tco_sample_rate, \
3751 .put = snd_hdspm_put_tco_sample_rate \
3752}
3753
3754static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol,
3755 struct snd_ctl_elem_info *uinfo)
3756{
3757 static char *texts[] = { "44.1 kHz", "48 kHz" };
3758 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3759 uinfo->count = 1;
3760 uinfo->value.enumerated.items = 2;
3761
3762 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3763 uinfo->value.enumerated.item =
3764 uinfo->value.enumerated.items - 1;
3765
3766 strcpy(uinfo->value.enumerated.name,
3767 texts[uinfo->value.enumerated.item]);
3768
3769 return 0;
3770}
3771
3772static int snd_hdspm_get_tco_sample_rate(struct snd_kcontrol *kcontrol,
3773 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003774{
Takashi Iwai98274f02005-11-17 14:52:34 +01003775 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003776
Adrian Knoth0dca1792011-01-26 19:32:14 +01003777 ucontrol->value.enumerated.item[0] = hdspm->tco->samplerate;
3778
Takashi Iwai763f3562005-06-03 11:25:34 +02003779 return 0;
3780}
3781
Adrian Knoth0dca1792011-01-26 19:32:14 +01003782static int snd_hdspm_put_tco_sample_rate(struct snd_kcontrol *kcontrol,
3783 struct snd_ctl_elem_value *ucontrol)
Remy Bruno3cee5a62006-10-16 12:46:32 +02003784{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003785 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3786
3787 if (hdspm->tco->samplerate != ucontrol->value.enumerated.item[0]) {
3788 hdspm->tco->samplerate = ucontrol->value.enumerated.item[0];
3789
3790 hdspm_tco_write(hdspm);
3791
3792 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003793 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01003794
Remy Bruno3cee5a62006-10-16 12:46:32 +02003795 return 0;
3796}
3797
Adrian Knoth0dca1792011-01-26 19:32:14 +01003798
3799#define HDSPM_TCO_PULL(xname, xindex) \
3800{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3801 .name = xname, \
3802 .index = xindex, \
3803 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
3804 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3805 .info = snd_hdspm_info_tco_pull, \
3806 .get = snd_hdspm_get_tco_pull, \
3807 .put = snd_hdspm_put_tco_pull \
3808}
3809
3810static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol,
3811 struct snd_ctl_elem_info *uinfo)
3812{
3813 static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" };
3814 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3815 uinfo->count = 1;
3816 uinfo->value.enumerated.items = 5;
3817
3818 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3819 uinfo->value.enumerated.item =
3820 uinfo->value.enumerated.items - 1;
3821
3822 strcpy(uinfo->value.enumerated.name,
3823 texts[uinfo->value.enumerated.item]);
3824
3825 return 0;
3826}
3827
3828static int snd_hdspm_get_tco_pull(struct snd_kcontrol *kcontrol,
3829 struct snd_ctl_elem_value *ucontrol)
3830{
3831 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3832
3833 ucontrol->value.enumerated.item[0] = hdspm->tco->pull;
3834
3835 return 0;
3836}
3837
3838static int snd_hdspm_put_tco_pull(struct snd_kcontrol *kcontrol,
3839 struct snd_ctl_elem_value *ucontrol)
3840{
3841 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3842
3843 if (hdspm->tco->pull != ucontrol->value.enumerated.item[0]) {
3844 hdspm->tco->pull = ucontrol->value.enumerated.item[0];
3845
3846 hdspm_tco_write(hdspm);
3847
3848 return 1;
3849 }
3850
3851 return 0;
3852}
3853
3854#define HDSPM_TCO_WCK_CONVERSION(xname, xindex) \
3855{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3856 .name = xname, \
3857 .index = xindex, \
3858 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
3859 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3860 .info = snd_hdspm_info_tco_wck_conversion, \
3861 .get = snd_hdspm_get_tco_wck_conversion, \
3862 .put = snd_hdspm_put_tco_wck_conversion \
3863}
3864
3865static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol,
3866 struct snd_ctl_elem_info *uinfo)
3867{
3868 static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
3869 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3870 uinfo->count = 1;
3871 uinfo->value.enumerated.items = 3;
3872
3873 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3874 uinfo->value.enumerated.item =
3875 uinfo->value.enumerated.items - 1;
3876
3877 strcpy(uinfo->value.enumerated.name,
3878 texts[uinfo->value.enumerated.item]);
3879
3880 return 0;
3881}
3882
3883static int snd_hdspm_get_tco_wck_conversion(struct snd_kcontrol *kcontrol,
3884 struct snd_ctl_elem_value *ucontrol)
3885{
3886 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3887
3888 ucontrol->value.enumerated.item[0] = hdspm->tco->wordclock;
3889
3890 return 0;
3891}
3892
3893static int snd_hdspm_put_tco_wck_conversion(struct snd_kcontrol *kcontrol,
3894 struct snd_ctl_elem_value *ucontrol)
3895{
3896 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3897
3898 if (hdspm->tco->wordclock != ucontrol->value.enumerated.item[0]) {
3899 hdspm->tco->wordclock = ucontrol->value.enumerated.item[0];
3900
3901 hdspm_tco_write(hdspm);
3902
3903 return 1;
3904 }
3905
3906 return 0;
3907}
3908
3909
3910#define HDSPM_TCO_FRAME_RATE(xname, xindex) \
3911{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3912 .name = xname, \
3913 .index = xindex, \
3914 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
3915 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3916 .info = snd_hdspm_info_tco_frame_rate, \
3917 .get = snd_hdspm_get_tco_frame_rate, \
3918 .put = snd_hdspm_put_tco_frame_rate \
3919}
3920
3921static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol,
3922 struct snd_ctl_elem_info *uinfo)
3923{
3924 static char *texts[] = { "24 fps", "25 fps", "29.97fps",
3925 "29.97 dfps", "30 fps", "30 dfps" };
3926 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3927 uinfo->count = 1;
3928 uinfo->value.enumerated.items = 6;
3929
3930 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3931 uinfo->value.enumerated.item =
3932 uinfo->value.enumerated.items - 1;
3933
3934 strcpy(uinfo->value.enumerated.name,
3935 texts[uinfo->value.enumerated.item]);
3936
3937 return 0;
3938}
3939
3940static int snd_hdspm_get_tco_frame_rate(struct snd_kcontrol *kcontrol,
Remy Bruno3cee5a62006-10-16 12:46:32 +02003941 struct snd_ctl_elem_value *ucontrol)
3942{
Remy Bruno3cee5a62006-10-16 12:46:32 +02003943 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3944
Adrian Knoth0dca1792011-01-26 19:32:14 +01003945 ucontrol->value.enumerated.item[0] = hdspm->tco->framerate;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003946
Remy Bruno3cee5a62006-10-16 12:46:32 +02003947 return 0;
3948}
Takashi Iwai763f3562005-06-03 11:25:34 +02003949
Adrian Knoth0dca1792011-01-26 19:32:14 +01003950static int snd_hdspm_put_tco_frame_rate(struct snd_kcontrol *kcontrol,
3951 struct snd_ctl_elem_value *ucontrol)
3952{
3953 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3954
3955 if (hdspm->tco->framerate != ucontrol->value.enumerated.item[0]) {
3956 hdspm->tco->framerate = ucontrol->value.enumerated.item[0];
3957
3958 hdspm_tco_write(hdspm);
3959
3960 return 1;
3961 }
3962
3963 return 0;
3964}
3965
3966
3967#define HDSPM_TCO_SYNC_SOURCE(xname, xindex) \
3968{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3969 .name = xname, \
3970 .index = xindex, \
3971 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
3972 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3973 .info = snd_hdspm_info_tco_sync_source, \
3974 .get = snd_hdspm_get_tco_sync_source, \
3975 .put = snd_hdspm_put_tco_sync_source \
3976}
3977
3978static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol,
3979 struct snd_ctl_elem_info *uinfo)
3980{
3981 static char *texts[] = { "LTC", "Video", "WCK" };
3982 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3983 uinfo->count = 1;
3984 uinfo->value.enumerated.items = 3;
3985
3986 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3987 uinfo->value.enumerated.item =
3988 uinfo->value.enumerated.items - 1;
3989
3990 strcpy(uinfo->value.enumerated.name,
3991 texts[uinfo->value.enumerated.item]);
3992
3993 return 0;
3994}
3995
3996static int snd_hdspm_get_tco_sync_source(struct snd_kcontrol *kcontrol,
3997 struct snd_ctl_elem_value *ucontrol)
3998{
3999 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4000
4001 ucontrol->value.enumerated.item[0] = hdspm->tco->input;
4002
4003 return 0;
4004}
4005
4006static int snd_hdspm_put_tco_sync_source(struct snd_kcontrol *kcontrol,
4007 struct snd_ctl_elem_value *ucontrol)
4008{
4009 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4010
4011 if (hdspm->tco->input != ucontrol->value.enumerated.item[0]) {
4012 hdspm->tco->input = ucontrol->value.enumerated.item[0];
4013
4014 hdspm_tco_write(hdspm);
4015
4016 return 1;
4017 }
4018
4019 return 0;
4020}
4021
4022
4023#define HDSPM_TCO_WORD_TERM(xname, xindex) \
4024{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4025 .name = xname, \
4026 .index = xindex, \
4027 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4028 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4029 .info = snd_hdspm_info_tco_word_term, \
4030 .get = snd_hdspm_get_tco_word_term, \
4031 .put = snd_hdspm_put_tco_word_term \
4032}
4033
4034static int snd_hdspm_info_tco_word_term(struct snd_kcontrol *kcontrol,
4035 struct snd_ctl_elem_info *uinfo)
4036{
4037 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
4038 uinfo->count = 1;
4039 uinfo->value.integer.min = 0;
4040 uinfo->value.integer.max = 1;
4041
4042 return 0;
4043}
4044
4045
4046static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol,
4047 struct snd_ctl_elem_value *ucontrol)
4048{
4049 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4050
4051 ucontrol->value.enumerated.item[0] = hdspm->tco->term;
4052
4053 return 0;
4054}
4055
4056
4057static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol,
4058 struct snd_ctl_elem_value *ucontrol)
4059{
4060 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4061
4062 if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) {
4063 hdspm->tco->term = ucontrol->value.enumerated.item[0];
4064
4065 hdspm_tco_write(hdspm);
4066
4067 return 1;
4068 }
4069
4070 return 0;
4071}
4072
4073
4074
Takashi Iwai763f3562005-06-03 11:25:34 +02004075
Remy Bruno3cee5a62006-10-16 12:46:32 +02004076static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004077 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004078 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Takashi Iwai763f3562005-06-03 11:25:34 +02004079 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4080 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4081 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4082 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004083 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4084 HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
4085 HDSPM_SYNC_CHECK("TCO SyncCHeck", 2),
4086 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
Takashi Iwai763f3562005-06-03 11:25:34 +02004087 HDSPM_LINE_OUT("Line Out", 0),
4088 HDSPM_TX_64("TX 64 channels mode", 0),
4089 HDSPM_C_TMS("Clear Track Marker", 0),
4090 HDSPM_SAFE_MODE("Safe Mode", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004091 HDSPM_INPUT_SELECT("Input Select", 0)
4092};
4093
4094
4095static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
4096 HDSPM_MIXER("Mixer", 0),
4097 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4098 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4099 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4100 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4101 HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
4102 HDSPM_TX_64("TX 64 channels mode", 0),
4103 HDSPM_C_TMS("Clear Track Marker", 0),
4104 HDSPM_SAFE_MODE("Safe Mode", 0),
Takashi Iwai763f3562005-06-03 11:25:34 +02004105 HDSPM_INPUT_SELECT("Input Select", 0),
4106};
4107
Adrian Knoth0dca1792011-01-26 19:32:14 +01004108static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004109 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004110 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004111 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4112 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4113 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4114 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004115 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004116 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4117 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4118 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4119 HDSPM_SYNC_CHECK("ADAT SyncCheck", 3),
4120 HDSPM_SYNC_CHECK("TCO SyncCheck", 4),
4121 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 5),
4122 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4123 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4124 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4125 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT Frequency", 3),
4126 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 4),
4127 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5)
4128
4129 /*
4130 HDSPM_INPUT_SELECT("Input Select", 0),
4131 HDSPM_SPDIF_OPTICAL("SPDIF Out Optical", 0),
4132 HDSPM_PROFESSIONAL("SPDIF Out Professional", 0);
4133 HDSPM_SPDIF_IN("SPDIF In", 0);
4134 HDSPM_BREAKOUT_CABLE("Breakout Cable", 0);
4135 HDSPM_INPUT_LEVEL("Input Level", 0);
4136 HDSPM_OUTPUT_LEVEL("Output Level", 0);
4137 HDSPM_PHONES("Phones", 0);
4138 */
4139};
4140
4141static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = {
4142 HDSPM_MIXER("Mixer", 0),
4143 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4144 HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0),
4145 HDSPM_PREF_SYNC_REF("Pref Sync Ref", 0),
4146 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4147 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4148 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4149 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4150 HDSPM_SYNC_CHECK("ADAT1 SyncCheck", 3),
4151 HDSPM_SYNC_CHECK("ADAT2 SyncCheck", 4),
4152 HDSPM_SYNC_CHECK("ADAT3 SyncCheck", 5),
4153 HDSPM_SYNC_CHECK("ADAT4 SyncCheck", 6),
4154 HDSPM_SYNC_CHECK("TCO SyncCheck", 7),
4155 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 8),
4156 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4157 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4158 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4159 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT1 Frequency", 3),
4160 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT2 Frequency", 4),
4161 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT3 Frequency", 5),
4162 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT4 Frequency", 6),
4163 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 7),
4164 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8)
4165};
4166
4167static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
4168 HDSPM_MIXER("Mixer", 0),
4169 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4170 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4171 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4172 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4173 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4174 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4175 HDSPM_SYNC_CHECK("WC Sync Check", 0),
4176 HDSPM_SYNC_CHECK("AES1 Sync Check", 1),
4177 HDSPM_SYNC_CHECK("AES2 Sync Check", 2),
4178 HDSPM_SYNC_CHECK("AES3 Sync Check", 3),
4179 HDSPM_SYNC_CHECK("AES4 Sync Check", 4),
4180 HDSPM_SYNC_CHECK("AES5 Sync Check", 5),
4181 HDSPM_SYNC_CHECK("AES6 Sync Check", 6),
4182 HDSPM_SYNC_CHECK("AES7 Sync Check", 7),
4183 HDSPM_SYNC_CHECK("AES8 Sync Check", 8),
4184 HDSPM_SYNC_CHECK("TCO Sync Check", 9),
4185 HDSPM_SYNC_CHECK("SYNC IN Sync Check", 10),
4186 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4187 HDSPM_AUTOSYNC_SAMPLE_RATE("AES1 Frequency", 1),
4188 HDSPM_AUTOSYNC_SAMPLE_RATE("AES2 Frequency", 2),
4189 HDSPM_AUTOSYNC_SAMPLE_RATE("AES3 Frequency", 3),
4190 HDSPM_AUTOSYNC_SAMPLE_RATE("AES4 Frequency", 4),
4191 HDSPM_AUTOSYNC_SAMPLE_RATE("AES5 Frequency", 5),
4192 HDSPM_AUTOSYNC_SAMPLE_RATE("AES6 Frequency", 6),
4193 HDSPM_AUTOSYNC_SAMPLE_RATE("AES7 Frequency", 7),
4194 HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8),
4195 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9),
4196 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004197 HDSPM_LINE_OUT("Line Out", 0),
4198 HDSPM_EMPHASIS("Emphasis", 0),
4199 HDSPM_DOLBY("Non Audio", 0),
4200 HDSPM_PROFESSIONAL("Professional", 0),
4201 HDSPM_C_TMS("Clear Track Marker", 0),
4202 HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
4203 HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
4204};
4205
Adrian Knoth0dca1792011-01-26 19:32:14 +01004206
4207
4208/* Control elements for the optional TCO module */
4209static struct snd_kcontrol_new snd_hdspm_controls_tco[] = {
4210 HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0),
4211 HDSPM_TCO_PULL("TCO Pull", 0),
4212 HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0),
4213 HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0),
4214 HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0),
4215 HDSPM_TCO_WORD_TERM("TCO Word Term", 0)
4216};
4217
4218
Takashi Iwai98274f02005-11-17 14:52:34 +01004219static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
Takashi Iwai763f3562005-06-03 11:25:34 +02004220
4221
Takashi Iwai98274f02005-11-17 14:52:34 +01004222static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004223{
4224 int i;
4225
Adrian Knoth0dca1792011-01-26 19:32:14 +01004226 for (i = hdspm->ds_out_channels; i < hdspm->ss_out_channels; ++i) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004227 if (hdspm->system_sample_rate > 48000) {
4228 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004229 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
4230 SNDRV_CTL_ELEM_ACCESS_READ |
4231 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004232 } else {
4233 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004234 SNDRV_CTL_ELEM_ACCESS_READWRITE |
4235 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004236 }
4237 snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
Adrian Knoth0dca1792011-01-26 19:32:14 +01004238 SNDRV_CTL_EVENT_MASK_INFO,
4239 &hdspm->playback_mixer_ctls[i]->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02004240 }
4241
4242 return 0;
4243}
4244
4245
Adrian Knoth0dca1792011-01-26 19:32:14 +01004246static int snd_hdspm_create_controls(struct snd_card *card,
4247 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004248{
4249 unsigned int idx, limit;
4250 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01004251 struct snd_kcontrol *kctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004252 struct snd_kcontrol_new *list = NULL;
Takashi Iwai763f3562005-06-03 11:25:34 +02004253
Adrian Knoth0dca1792011-01-26 19:32:14 +01004254 switch (hdspm->io_type) {
4255 case MADI:
4256 list = snd_hdspm_controls_madi;
4257 limit = ARRAY_SIZE(snd_hdspm_controls_madi);
4258 break;
4259 case MADIface:
4260 list = snd_hdspm_controls_madiface;
4261 limit = ARRAY_SIZE(snd_hdspm_controls_madiface);
4262 break;
4263 case AIO:
4264 list = snd_hdspm_controls_aio;
4265 limit = ARRAY_SIZE(snd_hdspm_controls_aio);
4266 break;
4267 case RayDAT:
4268 list = snd_hdspm_controls_raydat;
4269 limit = ARRAY_SIZE(snd_hdspm_controls_raydat);
4270 break;
4271 case AES32:
4272 list = snd_hdspm_controls_aes32;
4273 limit = ARRAY_SIZE(snd_hdspm_controls_aes32);
4274 break;
4275 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004276
Adrian Knoth0dca1792011-01-26 19:32:14 +01004277 if (NULL != list) {
4278 for (idx = 0; idx < limit; idx++) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004279 err = snd_ctl_add(card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004280 snd_ctl_new1(&list[idx], hdspm));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004281 if (err < 0)
4282 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004283 }
4284 }
4285
Takashi Iwai763f3562005-06-03 11:25:34 +02004286
Adrian Knoth0dca1792011-01-26 19:32:14 +01004287 /* create simple 1:1 playback mixer controls */
Takashi Iwai763f3562005-06-03 11:25:34 +02004288 snd_hdspm_playback_mixer.name = "Chn";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004289 if (hdspm->system_sample_rate >= 128000) {
4290 limit = hdspm->qs_out_channels;
4291 } else if (hdspm->system_sample_rate >= 64000) {
4292 limit = hdspm->ds_out_channels;
4293 } else {
4294 limit = hdspm->ss_out_channels;
4295 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004296 for (idx = 0; idx < limit; ++idx) {
4297 snd_hdspm_playback_mixer.index = idx + 1;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004298 kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm);
4299 err = snd_ctl_add(card, kctl);
4300 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004301 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004302 hdspm->playback_mixer_ctls[idx] = kctl;
4303 }
4304
Adrian Knoth0dca1792011-01-26 19:32:14 +01004305
4306 if (hdspm->tco) {
4307 /* add tco control elements */
4308 list = snd_hdspm_controls_tco;
4309 limit = ARRAY_SIZE(snd_hdspm_controls_tco);
4310 for (idx = 0; idx < limit; idx++) {
4311 err = snd_ctl_add(card,
4312 snd_ctl_new1(&list[idx], hdspm));
4313 if (err < 0)
4314 return err;
4315 }
4316 }
4317
Takashi Iwai763f3562005-06-03 11:25:34 +02004318 return 0;
4319}
4320
4321/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01004322 /proc interface
Takashi Iwai763f3562005-06-03 11:25:34 +02004323 ------------------------------------------------------------*/
4324
4325static void
Remy Bruno3cee5a62006-10-16 12:46:32 +02004326snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
4327 struct snd_info_buffer *buffer)
Takashi Iwai763f3562005-06-03 11:25:34 +02004328{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004329 struct hdspm *hdspm = entry->private_data;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004330 unsigned int status, status2, control, freq;
4331
Takashi Iwai763f3562005-06-03 11:25:34 +02004332 char *pref_sync_ref;
4333 char *autosync_ref;
4334 char *system_clock_mode;
Takashi Iwai763f3562005-06-03 11:25:34 +02004335 char *insel;
Takashi Iwai763f3562005-06-03 11:25:34 +02004336 int x, x2;
4337
Adrian Knoth0dca1792011-01-26 19:32:14 +01004338 /* TCO stuff */
4339 int a, ltc, frames, seconds, minutes, hours;
4340 unsigned int period;
4341 u64 freq_const = 0;
4342 u32 rate;
4343
Takashi Iwai763f3562005-06-03 11:25:34 +02004344 status = hdspm_read(hdspm, HDSPM_statusRegister);
4345 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004346 control = hdspm->control_register;
4347 freq = hdspm_read(hdspm, HDSPM_timecodeRegister);
Takashi Iwai763f3562005-06-03 11:25:34 +02004348
4349 snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004350 hdspm->card_name, hdspm->card->number + 1,
4351 hdspm->firmware_rev,
4352 (status2 & HDSPM_version0) |
4353 (status2 & HDSPM_version1) | (status2 &
4354 HDSPM_version2));
4355
4356 snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n",
4357 (hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF,
4358 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF);
Takashi Iwai763f3562005-06-03 11:25:34 +02004359
4360 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004361 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
Takashi Iwai763f3562005-06-03 11:25:34 +02004362
4363 snd_iprintf(buffer, "--- System ---\n");
4364
4365 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004366 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4367 status & HDSPM_audioIRQPending,
4368 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4369 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4370 hdspm->irq_count);
Takashi Iwai763f3562005-06-03 11:25:34 +02004371 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004372 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4373 "estimated= %ld (bytes)\n",
4374 ((status & HDSPM_BufferID) ? 1 : 0),
4375 (status & HDSPM_BufferPositionMask),
4376 (status & HDSPM_BufferPositionMask) %
4377 (2 * (int)hdspm->period_bytes),
4378 ((status & HDSPM_BufferPositionMask) - 64) %
4379 (2 * (int)hdspm->period_bytes),
4380 (long) hdspm_hw_pointer(hdspm) * 4);
Takashi Iwai763f3562005-06-03 11:25:34 +02004381
4382 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004383 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4384 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4385 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4386 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4387 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
Takashi Iwai763f3562005-06-03 11:25:34 +02004388 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004389 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4390 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4391 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4392 snd_iprintf(buffer,
4393 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4394 "status2=0x%x\n",
4395 hdspm->control_register, hdspm->control2_register,
4396 status, status2);
4397 if (status & HDSPM_tco_detect) {
4398 snd_iprintf(buffer, "TCO module detected.\n");
4399 a = hdspm_read(hdspm, HDSPM_RD_TCO+4);
4400 if (a & HDSPM_TCO1_LTC_Input_valid) {
4401 snd_iprintf(buffer, " LTC valid, ");
4402 switch (a & (HDSPM_TCO1_LTC_Format_LSB |
4403 HDSPM_TCO1_LTC_Format_MSB)) {
4404 case 0:
4405 snd_iprintf(buffer, "24 fps, ");
4406 break;
4407 case HDSPM_TCO1_LTC_Format_LSB:
4408 snd_iprintf(buffer, "25 fps, ");
4409 break;
4410 case HDSPM_TCO1_LTC_Format_MSB:
4411 snd_iprintf(buffer, "29.97 fps, ");
4412 break;
4413 default:
4414 snd_iprintf(buffer, "30 fps, ");
4415 break;
4416 }
4417 if (a & HDSPM_TCO1_set_drop_frame_flag) {
4418 snd_iprintf(buffer, "drop frame\n");
4419 } else {
4420 snd_iprintf(buffer, "full frame\n");
4421 }
4422 } else {
4423 snd_iprintf(buffer, " no LTC\n");
4424 }
4425 if (a & HDSPM_TCO1_Video_Input_Format_NTSC) {
4426 snd_iprintf(buffer, " Video: NTSC\n");
4427 } else if (a & HDSPM_TCO1_Video_Input_Format_PAL) {
4428 snd_iprintf(buffer, " Video: PAL\n");
4429 } else {
4430 snd_iprintf(buffer, " No video\n");
4431 }
4432 if (a & HDSPM_TCO1_TCO_lock) {
4433 snd_iprintf(buffer, " Sync: lock\n");
4434 } else {
4435 snd_iprintf(buffer, " Sync: no lock\n");
4436 }
4437
4438 switch (hdspm->io_type) {
4439 case MADI:
4440 case AES32:
4441 freq_const = 110069313433624ULL;
4442 break;
4443 case RayDAT:
4444 case AIO:
4445 freq_const = 104857600000000ULL;
4446 break;
4447 case MADIface:
4448 break; /* no TCO possible */
4449 }
4450
4451 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
4452 snd_iprintf(buffer, " period: %u\n", period);
4453
4454
4455 /* rate = freq_const/period; */
4456 rate = div_u64(freq_const, period);
4457
4458 if (control & HDSPM_QuadSpeed) {
4459 rate *= 4;
4460 } else if (control & HDSPM_DoubleSpeed) {
4461 rate *= 2;
4462 }
4463
4464 snd_iprintf(buffer, " Frequency: %u Hz\n",
4465 (unsigned int) rate);
4466
4467 ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
4468 frames = ltc & 0xF;
4469 ltc >>= 4;
4470 frames += (ltc & 0x3) * 10;
4471 ltc >>= 4;
4472 seconds = ltc & 0xF;
4473 ltc >>= 4;
4474 seconds += (ltc & 0x7) * 10;
4475 ltc >>= 4;
4476 minutes = ltc & 0xF;
4477 ltc >>= 4;
4478 minutes += (ltc & 0x7) * 10;
4479 ltc >>= 4;
4480 hours = ltc & 0xF;
4481 ltc >>= 4;
4482 hours += (ltc & 0x3) * 10;
4483 snd_iprintf(buffer,
4484 " LTC In: %02d:%02d:%02d:%02d\n",
4485 hours, minutes, seconds, frames);
4486
4487 } else {
4488 snd_iprintf(buffer, "No TCO module detected.\n");
4489 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004490
4491 snd_iprintf(buffer, "--- Settings ---\n");
4492
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004493 x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
Adrian Knoth0dca1792011-01-26 19:32:14 +01004494 HDSPM_LatencyMask));
Takashi Iwai763f3562005-06-03 11:25:34 +02004495
4496 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004497 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4498 x, (unsigned long) hdspm->period_bytes);
Takashi Iwai763f3562005-06-03 11:25:34 +02004499
Adrian Knoth0dca1792011-01-26 19:32:14 +01004500 snd_iprintf(buffer, "Line out: %s\n",
4501 (hdspm->control_register & HDSPM_LineOut) ? "on " : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004502
4503 switch (hdspm->control_register & HDSPM_InputMask) {
4504 case HDSPM_InputOptical:
4505 insel = "Optical";
4506 break;
4507 case HDSPM_InputCoaxial:
4508 insel = "Coaxial";
4509 break;
4510 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01004511 insel = "Unkown";
Takashi Iwai763f3562005-06-03 11:25:34 +02004512 }
4513
Takashi Iwai763f3562005-06-03 11:25:34 +02004514 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004515 "ClearTrackMarker = %s, Transmit in %s Channel Mode, "
4516 "Auto Input %s\n",
4517 (hdspm->control_register & HDSPM_clr_tms) ? "on" : "off",
4518 (hdspm->control_register & HDSPM_TX_64ch) ? "64" : "56",
4519 (hdspm->control_register & HDSPM_AutoInp) ? "on" : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004520
Adrian Knoth0dca1792011-01-26 19:32:14 +01004521
Remy Bruno3cee5a62006-10-16 12:46:32 +02004522 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
Adrian Knoth0dca1792011-01-26 19:32:14 +01004523 system_clock_mode = "AutoSync";
Remy Bruno3cee5a62006-10-16 12:46:32 +02004524 else
Takashi Iwai763f3562005-06-03 11:25:34 +02004525 system_clock_mode = "Master";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004526 snd_iprintf(buffer, "AutoSync Reference: %s\n", system_clock_mode);
Takashi Iwai763f3562005-06-03 11:25:34 +02004527
4528 switch (hdspm_pref_sync_ref(hdspm)) {
4529 case HDSPM_SYNC_FROM_WORD:
4530 pref_sync_ref = "Word Clock";
4531 break;
4532 case HDSPM_SYNC_FROM_MADI:
4533 pref_sync_ref = "MADI Sync";
4534 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004535 case HDSPM_SYNC_FROM_TCO:
4536 pref_sync_ref = "TCO";
4537 break;
4538 case HDSPM_SYNC_FROM_SYNC_IN:
4539 pref_sync_ref = "Sync In";
4540 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004541 default:
4542 pref_sync_ref = "XXXX Clock";
4543 break;
4544 }
4545 snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004546 pref_sync_ref);
Takashi Iwai763f3562005-06-03 11:25:34 +02004547
4548 snd_iprintf(buffer, "System Clock Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004549 hdspm->system_sample_rate);
Takashi Iwai763f3562005-06-03 11:25:34 +02004550
4551
4552 snd_iprintf(buffer, "--- Status:\n");
4553
4554 x = status & HDSPM_madiSync;
4555 x2 = status2 & HDSPM_wcSync;
4556
4557 snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004558 (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
4559 "NoLock",
4560 (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
4561 "NoLock");
Takashi Iwai763f3562005-06-03 11:25:34 +02004562
4563 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004564 case HDSPM_AUTOSYNC_FROM_SYNC_IN:
4565 autosync_ref = "Sync In";
4566 break;
4567 case HDSPM_AUTOSYNC_FROM_TCO:
4568 autosync_ref = "TCO";
4569 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004570 case HDSPM_AUTOSYNC_FROM_WORD:
4571 autosync_ref = "Word Clock";
4572 break;
4573 case HDSPM_AUTOSYNC_FROM_MADI:
4574 autosync_ref = "MADI Sync";
4575 break;
4576 case HDSPM_AUTOSYNC_FROM_NONE:
4577 autosync_ref = "Input not valid";
4578 break;
4579 default:
4580 autosync_ref = "---";
4581 break;
4582 }
4583 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004584 "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
4585 autosync_ref, hdspm_external_sample_rate(hdspm),
4586 (status & HDSPM_madiFreqMask) >> 22,
4587 (status2 & HDSPM_wcFreqMask) >> 5);
Takashi Iwai763f3562005-06-03 11:25:34 +02004588
4589 snd_iprintf(buffer, "Input: %s, Mode=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004590 (status & HDSPM_AB_int) ? "Coax" : "Optical",
4591 (status & HDSPM_RX_64ch) ? "64 channels" :
4592 "56 channels");
Takashi Iwai763f3562005-06-03 11:25:34 +02004593
4594 snd_iprintf(buffer, "\n");
4595}
4596
Remy Bruno3cee5a62006-10-16 12:46:32 +02004597static void
4598snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
4599 struct snd_info_buffer *buffer)
4600{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004601 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004602 unsigned int status;
4603 unsigned int status2;
4604 unsigned int timecode;
4605 int pref_syncref;
4606 char *autosync_ref;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004607 int x;
4608
4609 status = hdspm_read(hdspm, HDSPM_statusRegister);
4610 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
4611 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
4612
4613 snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
4614 hdspm->card_name, hdspm->card->number + 1,
4615 hdspm->firmware_rev);
4616
4617 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
4618 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
4619
4620 snd_iprintf(buffer, "--- System ---\n");
4621
4622 snd_iprintf(buffer,
4623 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4624 status & HDSPM_audioIRQPending,
4625 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4626 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4627 hdspm->irq_count);
4628 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004629 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4630 "estimated= %ld (bytes)\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004631 ((status & HDSPM_BufferID) ? 1 : 0),
4632 (status & HDSPM_BufferPositionMask),
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004633 (status & HDSPM_BufferPositionMask) %
4634 (2 * (int)hdspm->period_bytes),
4635 ((status & HDSPM_BufferPositionMask) - 64) %
4636 (2 * (int)hdspm->period_bytes),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004637 (long) hdspm_hw_pointer(hdspm) * 4);
4638
4639 snd_iprintf(buffer,
4640 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4641 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4642 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4643 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4644 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
4645 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004646 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4647 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4648 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4649 snd_iprintf(buffer,
4650 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4651 "status2=0x%x\n",
4652 hdspm->control_register, hdspm->control2_register,
4653 status, status2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02004654
4655 snd_iprintf(buffer, "--- Settings ---\n");
4656
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004657 x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
Adrian Knoth0dca1792011-01-26 19:32:14 +01004658 HDSPM_LatencyMask));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004659
4660 snd_iprintf(buffer,
4661 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4662 x, (unsigned long) hdspm->period_bytes);
4663
Adrian Knoth0dca1792011-01-26 19:32:14 +01004664 snd_iprintf(buffer, "Line out: %s\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004665 (hdspm->
Adrian Knoth0dca1792011-01-26 19:32:14 +01004666 control_register & HDSPM_LineOut) ? "on " : "off");
Remy Bruno3cee5a62006-10-16 12:46:32 +02004667
4668 snd_iprintf(buffer,
4669 "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
4670 (hdspm->
4671 control_register & HDSPM_clr_tms) ? "on" : "off",
4672 (hdspm->
4673 control_register & HDSPM_Emphasis) ? "on" : "off",
4674 (hdspm->
4675 control_register & HDSPM_Dolby) ? "on" : "off");
4676
Remy Bruno3cee5a62006-10-16 12:46:32 +02004677
4678 pref_syncref = hdspm_pref_sync_ref(hdspm);
4679 if (pref_syncref == 0)
4680 snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
4681 else
4682 snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
4683 pref_syncref);
4684
4685 snd_iprintf(buffer, "System Clock Frequency: %d\n",
4686 hdspm->system_sample_rate);
4687
4688 snd_iprintf(buffer, "Double speed: %s\n",
4689 hdspm->control_register & HDSPM_DS_DoubleWire?
4690 "Double wire" : "Single wire");
4691 snd_iprintf(buffer, "Quad speed: %s\n",
4692 hdspm->control_register & HDSPM_QS_DoubleWire?
4693 "Double wire" :
4694 hdspm->control_register & HDSPM_QS_QuadWire?
4695 "Quad wire" : "Single wire");
4696
4697 snd_iprintf(buffer, "--- Status:\n");
4698
4699 snd_iprintf(buffer, "Word: %s Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004700 (status & HDSPM_AES32_wcLock) ? "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004701 HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004702
4703 for (x = 0; x < 8; x++) {
4704 snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004705 x+1,
4706 (status2 & (HDSPM_LockAES >> x)) ?
Adrian Knoth0dca1792011-01-26 19:32:14 +01004707 "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004708 HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004709 }
4710
4711 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004712 case HDSPM_AES32_AUTOSYNC_FROM_NONE:
4713 autosync_ref = "None"; break;
4714 case HDSPM_AES32_AUTOSYNC_FROM_WORD:
4715 autosync_ref = "Word Clock"; break;
4716 case HDSPM_AES32_AUTOSYNC_FROM_AES1:
4717 autosync_ref = "AES1"; break;
4718 case HDSPM_AES32_AUTOSYNC_FROM_AES2:
4719 autosync_ref = "AES2"; break;
4720 case HDSPM_AES32_AUTOSYNC_FROM_AES3:
4721 autosync_ref = "AES3"; break;
4722 case HDSPM_AES32_AUTOSYNC_FROM_AES4:
4723 autosync_ref = "AES4"; break;
4724 case HDSPM_AES32_AUTOSYNC_FROM_AES5:
4725 autosync_ref = "AES5"; break;
4726 case HDSPM_AES32_AUTOSYNC_FROM_AES6:
4727 autosync_ref = "AES6"; break;
4728 case HDSPM_AES32_AUTOSYNC_FROM_AES7:
4729 autosync_ref = "AES7"; break;
4730 case HDSPM_AES32_AUTOSYNC_FROM_AES8:
4731 autosync_ref = "AES8"; break;
4732 default:
4733 autosync_ref = "---"; break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004734 }
4735 snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
4736
4737 snd_iprintf(buffer, "\n");
4738}
4739
Adrian Knoth0dca1792011-01-26 19:32:14 +01004740static void
4741snd_hdspm_proc_read_raydat(struct snd_info_entry *entry,
4742 struct snd_info_buffer *buffer)
4743{
4744 struct hdspm *hdspm = entry->private_data;
4745 unsigned int status1, status2, status3, control, i;
4746 unsigned int lock, sync;
4747
4748 status1 = hdspm_read(hdspm, HDSPM_RD_STATUS_1); /* s1 */
4749 status2 = hdspm_read(hdspm, HDSPM_RD_STATUS_2); /* freq */
4750 status3 = hdspm_read(hdspm, HDSPM_RD_STATUS_3); /* s2 */
4751
4752 control = hdspm->control_register;
4753
4754 snd_iprintf(buffer, "STATUS1: 0x%08x\n", status1);
4755 snd_iprintf(buffer, "STATUS2: 0x%08x\n", status2);
4756 snd_iprintf(buffer, "STATUS3: 0x%08x\n", status3);
4757
4758
4759 snd_iprintf(buffer, "\n*** CLOCK MODE\n\n");
4760
4761 snd_iprintf(buffer, "Clock mode : %s\n",
4762 (hdspm_system_clock_mode(hdspm) == 0) ? "master" : "slave");
4763 snd_iprintf(buffer, "System frequency: %d Hz\n",
4764 hdspm_get_system_sample_rate(hdspm));
4765
4766 snd_iprintf(buffer, "\n*** INPUT STATUS\n\n");
4767
4768 lock = 0x1;
4769 sync = 0x100;
4770
4771 for (i = 0; i < 8; i++) {
4772 snd_iprintf(buffer, "s1_input %d: Lock %d, Sync %d, Freq %s\n",
4773 i,
4774 (status1 & lock) ? 1 : 0,
4775 (status1 & sync) ? 1 : 0,
4776 texts_freq[(status2 >> (i * 4)) & 0xF]);
4777
4778 lock = lock<<1;
4779 sync = sync<<1;
4780 }
4781
4782 snd_iprintf(buffer, "WC input: Lock %d, Sync %d, Freq %s\n",
4783 (status1 & 0x1000000) ? 1 : 0,
4784 (status1 & 0x2000000) ? 1 : 0,
4785 texts_freq[(status1 >> 16) & 0xF]);
4786
4787 snd_iprintf(buffer, "TCO input: Lock %d, Sync %d, Freq %s\n",
4788 (status1 & 0x4000000) ? 1 : 0,
4789 (status1 & 0x8000000) ? 1 : 0,
4790 texts_freq[(status1 >> 20) & 0xF]);
4791
4792 snd_iprintf(buffer, "SYNC IN: Lock %d, Sync %d, Freq %s\n",
4793 (status3 & 0x400) ? 1 : 0,
4794 (status3 & 0x800) ? 1 : 0,
4795 texts_freq[(status2 >> 12) & 0xF]);
4796
4797}
4798
Remy Bruno3cee5a62006-10-16 12:46:32 +02004799#ifdef CONFIG_SND_DEBUG
4800static void
Adrian Knoth0dca1792011-01-26 19:32:14 +01004801snd_hdspm_proc_read_debug(struct snd_info_entry *entry,
Remy Bruno3cee5a62006-10-16 12:46:32 +02004802 struct snd_info_buffer *buffer)
4803{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004804 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004805
4806 int j,i;
4807
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004808 for (i = 0; i < 256 /* 1024*64 */; i += j) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004809 snd_iprintf(buffer, "0x%08X: ", i);
4810 for (j = 0; j < 16; j += 4)
4811 snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
4812 snd_iprintf(buffer, "\n");
4813 }
4814}
4815#endif
4816
4817
Adrian Knoth0dca1792011-01-26 19:32:14 +01004818static void snd_hdspm_proc_ports_in(struct snd_info_entry *entry,
4819 struct snd_info_buffer *buffer)
4820{
4821 struct hdspm *hdspm = entry->private_data;
4822 int i;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004823
Adrian Knoth0dca1792011-01-26 19:32:14 +01004824 snd_iprintf(buffer, "# generated by hdspm\n");
4825
4826 for (i = 0; i < hdspm->max_channels_in; i++) {
4827 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_in[i]);
4828 }
4829}
4830
4831static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry,
4832 struct snd_info_buffer *buffer)
4833{
4834 struct hdspm *hdspm = entry->private_data;
4835 int i;
4836
4837 snd_iprintf(buffer, "# generated by hdspm\n");
4838
4839 for (i = 0; i < hdspm->max_channels_out; i++) {
4840 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_out[i]);
4841 }
4842}
4843
4844
4845static void __devinit snd_hdspm_proc_init(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004846{
Takashi Iwai98274f02005-11-17 14:52:34 +01004847 struct snd_info_entry *entry;
Takashi Iwai763f3562005-06-03 11:25:34 +02004848
Adrian Knoth0dca1792011-01-26 19:32:14 +01004849 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) {
4850 switch (hdspm->io_type) {
4851 case AES32:
4852 snd_info_set_text_ops(entry, hdspm,
4853 snd_hdspm_proc_read_aes32);
4854 break;
4855 case MADI:
4856 snd_info_set_text_ops(entry, hdspm,
4857 snd_hdspm_proc_read_madi);
4858 break;
4859 case MADIface:
4860 /* snd_info_set_text_ops(entry, hdspm,
4861 snd_hdspm_proc_read_madiface); */
4862 break;
4863 case RayDAT:
4864 snd_info_set_text_ops(entry, hdspm,
4865 snd_hdspm_proc_read_raydat);
4866 break;
4867 case AIO:
4868 break;
4869 }
4870 }
4871
4872 if (!snd_card_proc_new(hdspm->card, "ports.in", &entry)) {
4873 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_in);
4874 }
4875
4876 if (!snd_card_proc_new(hdspm->card, "ports.out", &entry)) {
4877 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_out);
4878 }
4879
Remy Bruno3cee5a62006-10-16 12:46:32 +02004880#ifdef CONFIG_SND_DEBUG
4881 /* debug file to read all hdspm registers */
4882 if (!snd_card_proc_new(hdspm->card, "debug", &entry))
4883 snd_info_set_text_ops(entry, hdspm,
4884 snd_hdspm_proc_read_debug);
4885#endif
Takashi Iwai763f3562005-06-03 11:25:34 +02004886}
4887
4888/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01004889 hdspm intitialize
Takashi Iwai763f3562005-06-03 11:25:34 +02004890 ------------------------------------------------------------*/
4891
Takashi Iwai98274f02005-11-17 14:52:34 +01004892static int snd_hdspm_set_defaults(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004893{
Takashi Iwai763f3562005-06-03 11:25:34 +02004894 /* ASSUMPTION: hdspm->lock is either held, or there is no need to
Joe Perches561de312007-12-18 13:13:47 +01004895 hold it (e.g. during module initialization).
Adrian Knoth0dca1792011-01-26 19:32:14 +01004896 */
Takashi Iwai763f3562005-06-03 11:25:34 +02004897
4898 /* set defaults: */
4899
Adrian Knoth0dca1792011-01-26 19:32:14 +01004900 hdspm->settings_register = 0;
4901
4902 switch (hdspm->io_type) {
4903 case MADI:
4904 case MADIface:
4905 hdspm->control_register =
4906 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
4907 break;
4908
4909 case RayDAT:
4910 case AIO:
4911 hdspm->settings_register = 0x1 + 0x1000;
4912 /* Magic values are: LAT_0, LAT_2, Master, freq1, tx64ch, inp_0,
4913 * line_out */
4914 hdspm->control_register =
4915 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
4916 break;
4917
4918 case AES32:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004919 hdspm->control_register =
4920 HDSPM_ClockModeMaster | /* Master Cloack Mode on */
Adrian Knoth0dca1792011-01-26 19:32:14 +01004921 hdspm_encode_latency(7) | /* latency max=8192samples */
Remy Bruno3cee5a62006-10-16 12:46:32 +02004922 HDSPM_SyncRef0 | /* AES1 is syncclock */
4923 HDSPM_LineOut | /* Analog output in */
4924 HDSPM_Professional; /* Professional mode */
Adrian Knoth0dca1792011-01-26 19:32:14 +01004925 break;
4926 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004927
4928 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
4929
Adrian Knoth0dca1792011-01-26 19:32:14 +01004930 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01004931 /* No control2 register for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +02004932#ifdef SNDRV_BIG_ENDIAN
Remy Brunoffb2c3c2007-03-07 19:08:46 +01004933 hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004934#else
Remy Brunoffb2c3c2007-03-07 19:08:46 +01004935 hdspm->control2_register = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02004936#endif
4937
Remy Brunoffb2c3c2007-03-07 19:08:46 +01004938 hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
4939 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004940 hdspm_compute_period_size(hdspm);
4941
4942 /* silence everything */
4943
4944 all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
4945
Adrian Knoth0dca1792011-01-26 19:32:14 +01004946 if (hdspm->io_type == AIO || hdspm->io_type == RayDAT) {
4947 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
Takashi Iwai763f3562005-06-03 11:25:34 +02004948 }
4949
4950 /* set a default rate so that the channel map is set up. */
Adrian Knoth0dca1792011-01-26 19:32:14 +01004951 hdspm_set_rate(hdspm, 48000, 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02004952
4953 return 0;
4954}
4955
4956
4957/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01004958 interrupt
Takashi Iwai763f3562005-06-03 11:25:34 +02004959 ------------------------------------------------------------*/
4960
David Howells7d12e782006-10-05 14:55:46 +01004961static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02004962{
Takashi Iwai98274f02005-11-17 14:52:34 +01004963 struct hdspm *hdspm = (struct hdspm *) dev_id;
Takashi Iwai763f3562005-06-03 11:25:34 +02004964 unsigned int status;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004965 int i, audio, midi, schedule = 0;
4966 /* cycles_t now; */
Takashi Iwai763f3562005-06-03 11:25:34 +02004967
4968 status = hdspm_read(hdspm, HDSPM_statusRegister);
4969
4970 audio = status & HDSPM_audioIRQPending;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004971 midi = status & (HDSPM_midi0IRQPending | HDSPM_midi1IRQPending |
4972 HDSPM_midi2IRQPending | HDSPM_midi3IRQPending);
Takashi Iwai763f3562005-06-03 11:25:34 +02004973
Adrian Knoth0dca1792011-01-26 19:32:14 +01004974 /* now = get_cycles(); */
4975 /**
4976 * LAT_2..LAT_0 period counter (win) counter (mac)
4977 * 6 4096 ~256053425 ~514672358
4978 * 5 2048 ~128024983 ~257373821
4979 * 4 1024 ~64023706 ~128718089
4980 * 3 512 ~32005945 ~64385999
4981 * 2 256 ~16003039 ~32260176
4982 * 1 128 ~7998738 ~16194507
4983 * 0 64 ~3998231 ~8191558
4984 **/
4985 /*
4986 snd_printk(KERN_INFO "snd_hdspm_interrupt %llu @ %llx\n",
4987 now-hdspm->last_interrupt, status & 0xFFC0);
4988 hdspm->last_interrupt = now;
4989 */
4990
4991 if (!audio && !midi)
Takashi Iwai763f3562005-06-03 11:25:34 +02004992 return IRQ_NONE;
4993
4994 hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
4995 hdspm->irq_count++;
4996
Takashi Iwai763f3562005-06-03 11:25:34 +02004997
4998 if (audio) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004999 if (hdspm->capture_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005000 snd_pcm_period_elapsed(hdspm->capture_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005001
5002 if (hdspm->playback_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005003 snd_pcm_period_elapsed(hdspm->playback_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005004 }
5005
Adrian Knoth0dca1792011-01-26 19:32:14 +01005006 if (midi) {
5007 i = 0;
5008 while (i < hdspm->midiPorts) {
5009 if ((hdspm_read(hdspm,
5010 hdspm->midi[i].statusIn) & 0xff) &&
5011 (status & hdspm->midi[i].irq)) {
5012 /* we disable interrupts for this input until
5013 * processing is done
5014 */
5015 hdspm->control_register &= ~hdspm->midi[i].ie;
5016 hdspm_write(hdspm, HDSPM_controlRegister,
5017 hdspm->control_register);
5018 hdspm->midi[i].pending = 1;
5019 schedule = 1;
5020 }
5021
5022 i++;
5023 }
5024
5025 if (schedule)
5026 tasklet_hi_schedule(&hdspm->midi_tasklet);
Takashi Iwai763f3562005-06-03 11:25:34 +02005027 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005028
Takashi Iwai763f3562005-06-03 11:25:34 +02005029 return IRQ_HANDLED;
5030}
5031
5032/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005033 pcm interface
Takashi Iwai763f3562005-06-03 11:25:34 +02005034 ------------------------------------------------------------*/
5035
5036
Adrian Knoth0dca1792011-01-26 19:32:14 +01005037static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream
5038 *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005039{
Takashi Iwai98274f02005-11-17 14:52:34 +01005040 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005041 return hdspm_hw_pointer(hdspm);
5042}
5043
Takashi Iwai763f3562005-06-03 11:25:34 +02005044
Takashi Iwai98274f02005-11-17 14:52:34 +01005045static int snd_hdspm_reset(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005046{
Takashi Iwai98274f02005-11-17 14:52:34 +01005047 struct snd_pcm_runtime *runtime = substream->runtime;
5048 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5049 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005050
5051 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5052 other = hdspm->capture_substream;
5053 else
5054 other = hdspm->playback_substream;
5055
5056 if (hdspm->running)
5057 runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
5058 else
5059 runtime->status->hw_ptr = 0;
5060 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005061 struct snd_pcm_substream *s;
5062 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01005063 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005064 if (s == other) {
5065 oruntime->status->hw_ptr =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005066 runtime->status->hw_ptr;
Takashi Iwai763f3562005-06-03 11:25:34 +02005067 break;
5068 }
5069 }
5070 }
5071 return 0;
5072}
5073
Takashi Iwai98274f02005-11-17 14:52:34 +01005074static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
5075 struct snd_pcm_hw_params *params)
Takashi Iwai763f3562005-06-03 11:25:34 +02005076{
Takashi Iwai98274f02005-11-17 14:52:34 +01005077 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005078 int err;
5079 int i;
5080 pid_t this_pid;
5081 pid_t other_pid;
Takashi Iwai763f3562005-06-03 11:25:34 +02005082
5083 spin_lock_irq(&hdspm->lock);
5084
5085 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5086 this_pid = hdspm->playback_pid;
5087 other_pid = hdspm->capture_pid;
5088 } else {
5089 this_pid = hdspm->capture_pid;
5090 other_pid = hdspm->playback_pid;
5091 }
5092
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005093 if (other_pid > 0 && this_pid != other_pid) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005094
5095 /* The other stream is open, and not by the same
5096 task as this one. Make sure that the parameters
5097 that matter are the same.
Adrian Knoth0dca1792011-01-26 19:32:14 +01005098 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005099
5100 if (params_rate(params) != hdspm->system_sample_rate) {
5101 spin_unlock_irq(&hdspm->lock);
5102 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005103 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005104 return -EBUSY;
5105 }
5106
5107 if (params_period_size(params) != hdspm->period_bytes / 4) {
5108 spin_unlock_irq(&hdspm->lock);
5109 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005110 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005111 return -EBUSY;
5112 }
5113
5114 }
5115 /* We're fine. */
5116 spin_unlock_irq(&hdspm->lock);
5117
5118 /* how to make sure that the rate matches an externally-set one ? */
5119
5120 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005121 err = hdspm_set_rate(hdspm, params_rate(params), 0);
5122 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005123 snd_printk(KERN_INFO "err on hdspm_set_rate: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005124 spin_unlock_irq(&hdspm->lock);
5125 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005126 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005127 return err;
5128 }
5129 spin_unlock_irq(&hdspm->lock);
5130
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005131 err = hdspm_set_interrupt_interval(hdspm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005132 params_period_size(params));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005133 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005134 snd_printk(KERN_INFO "err on hdspm_set_interrupt_interval: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005135 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005136 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005137 return err;
5138 }
5139
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005140 /* Memory allocation, takashi's method, dont know if we should
5141 * spinlock
5142 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005143 /* malloc all buffer even if not enabled to get sure */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005144 /* Update for MADI rev 204: we need to allocate for all channels,
5145 * otherwise it doesn't work at 96kHz */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005146
Takashi Iwai763f3562005-06-03 11:25:34 +02005147 err =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005148 snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
5149 if (err < 0) {
5150 snd_printk(KERN_INFO "err on snd_pcm_lib_malloc_pages: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005151 return err;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005152 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005153
Takashi Iwai763f3562005-06-03 11:25:34 +02005154 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5155
Takashi Iwai77a23f22008-08-21 13:00:13 +02005156 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferOut,
Takashi Iwai763f3562005-06-03 11:25:34 +02005157 params_channels(params));
5158
5159 for (i = 0; i < params_channels(params); ++i)
5160 snd_hdspm_enable_out(hdspm, i, 1);
5161
5162 hdspm->playback_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005163 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005164 snd_printdd("Allocated sample buffer for playback at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005165 hdspm->playback_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005166 } else {
Takashi Iwai77a23f22008-08-21 13:00:13 +02005167 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn,
Takashi Iwai763f3562005-06-03 11:25:34 +02005168 params_channels(params));
5169
5170 for (i = 0; i < params_channels(params); ++i)
5171 snd_hdspm_enable_in(hdspm, i, 1);
5172
5173 hdspm->capture_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005174 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005175 snd_printdd("Allocated sample buffer for capture at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005176 hdspm->capture_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005177 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005178
Remy Bruno3cee5a62006-10-16 12:46:32 +02005179 /*
5180 snd_printdd("Allocated sample buffer for %s at 0x%08X\n",
5181 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5182 "playback" : "capture",
Takashi Iwai77a23f22008-08-21 13:00:13 +02005183 snd_pcm_sgbuf_get_addr(substream, 0));
Adrian Knoth0dca1792011-01-26 19:32:14 +01005184 */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005185 /*
Adrian Knoth0dca1792011-01-26 19:32:14 +01005186 snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n",
5187 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5188 "playback" : "capture",
5189 params_rate(params), params_channels(params),
5190 params_buffer_size(params));
5191 */
5192
5193
5194 /* Switch to native float format if requested */
5195 if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) {
5196 if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT))
5197 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE float format.\n");
5198
5199 hdspm->control_register |= HDSPe_FLOAT_FORMAT;
5200 } else if (SNDRV_PCM_FORMAT_S32_LE == params_format(params)) {
5201 if (hdspm->control_register & HDSPe_FLOAT_FORMAT)
5202 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE integer format.\n");
5203
5204 hdspm->control_register &= ~HDSPe_FLOAT_FORMAT;
5205 }
5206 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5207
Takashi Iwai763f3562005-06-03 11:25:34 +02005208 return 0;
5209}
5210
Takashi Iwai98274f02005-11-17 14:52:34 +01005211static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005212{
5213 int i;
Takashi Iwai98274f02005-11-17 14:52:34 +01005214 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005215
5216 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5217
Adrian Knoth0dca1792011-01-26 19:32:14 +01005218 /* params_channels(params) should be enough,
Takashi Iwai763f3562005-06-03 11:25:34 +02005219 but to get sure in case of error */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005220 for (i = 0; i < hdspm->max_channels_out; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005221 snd_hdspm_enable_out(hdspm, i, 0);
5222
5223 hdspm->playback_buffer = NULL;
5224 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005225 for (i = 0; i < hdspm->max_channels_in; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005226 snd_hdspm_enable_in(hdspm, i, 0);
5227
5228 hdspm->capture_buffer = NULL;
5229
5230 }
5231
5232 snd_pcm_lib_free_pages(substream);
5233
5234 return 0;
5235}
5236
Adrian Knoth0dca1792011-01-26 19:32:14 +01005237
Takashi Iwai98274f02005-11-17 14:52:34 +01005238static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005239 struct snd_pcm_channel_info *info)
Takashi Iwai763f3562005-06-03 11:25:34 +02005240{
Takashi Iwai98274f02005-11-17 14:52:34 +01005241 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005242
Adrian Knoth0dca1792011-01-26 19:32:14 +01005243 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5244 if (snd_BUG_ON(info->channel >= hdspm->max_channels_out)) {
5245 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel out of range (%d)\n", info->channel);
5246 return -EINVAL;
5247 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005248
Adrian Knoth0dca1792011-01-26 19:32:14 +01005249 if (hdspm->channel_map_out[info->channel] < 0) {
5250 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel %d mapped out\n", info->channel);
5251 return -EINVAL;
5252 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005253
Adrian Knoth0dca1792011-01-26 19:32:14 +01005254 info->offset = hdspm->channel_map_out[info->channel] *
5255 HDSPM_CHANNEL_BUFFER_BYTES;
5256 } else {
5257 if (snd_BUG_ON(info->channel >= hdspm->max_channels_in)) {
5258 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel out of range (%d)\n", info->channel);
5259 return -EINVAL;
5260 }
5261
5262 if (hdspm->channel_map_in[info->channel] < 0) {
5263 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel %d mapped out\n", info->channel);
5264 return -EINVAL;
5265 }
5266
5267 info->offset = hdspm->channel_map_in[info->channel] *
5268 HDSPM_CHANNEL_BUFFER_BYTES;
5269 }
5270
Takashi Iwai763f3562005-06-03 11:25:34 +02005271 info->first = 0;
5272 info->step = 32;
5273 return 0;
5274}
5275
Adrian Knoth0dca1792011-01-26 19:32:14 +01005276
Takashi Iwai98274f02005-11-17 14:52:34 +01005277static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005278 unsigned int cmd, void *arg)
Takashi Iwai763f3562005-06-03 11:25:34 +02005279{
5280 switch (cmd) {
5281 case SNDRV_PCM_IOCTL1_RESET:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005282 return snd_hdspm_reset(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005283
5284 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Adrian Knoth0dca1792011-01-26 19:32:14 +01005285 {
5286 struct snd_pcm_channel_info *info = arg;
5287 return snd_hdspm_channel_info(substream, info);
5288 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005289 default:
5290 break;
5291 }
5292
5293 return snd_pcm_lib_ioctl(substream, cmd, arg);
5294}
5295
Takashi Iwai98274f02005-11-17 14:52:34 +01005296static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
Takashi Iwai763f3562005-06-03 11:25:34 +02005297{
Takashi Iwai98274f02005-11-17 14:52:34 +01005298 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5299 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005300 int running;
5301
5302 spin_lock(&hdspm->lock);
5303 running = hdspm->running;
5304 switch (cmd) {
5305 case SNDRV_PCM_TRIGGER_START:
5306 running |= 1 << substream->stream;
5307 break;
5308 case SNDRV_PCM_TRIGGER_STOP:
5309 running &= ~(1 << substream->stream);
5310 break;
5311 default:
5312 snd_BUG();
5313 spin_unlock(&hdspm->lock);
5314 return -EINVAL;
5315 }
5316 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5317 other = hdspm->capture_substream;
5318 else
5319 other = hdspm->playback_substream;
5320
5321 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005322 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01005323 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005324 if (s == other) {
5325 snd_pcm_trigger_done(s, substream);
5326 if (cmd == SNDRV_PCM_TRIGGER_START)
5327 running |= 1 << s->stream;
5328 else
5329 running &= ~(1 << s->stream);
5330 goto _ok;
5331 }
5332 }
5333 if (cmd == SNDRV_PCM_TRIGGER_START) {
5334 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005335 && substream->stream ==
5336 SNDRV_PCM_STREAM_CAPTURE)
Takashi Iwai763f3562005-06-03 11:25:34 +02005337 hdspm_silence_playback(hdspm);
5338 } else {
5339 if (running &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01005340 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Takashi Iwai763f3562005-06-03 11:25:34 +02005341 hdspm_silence_playback(hdspm);
5342 }
5343 } else {
5344 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
5345 hdspm_silence_playback(hdspm);
5346 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005347_ok:
Takashi Iwai763f3562005-06-03 11:25:34 +02005348 snd_pcm_trigger_done(substream, substream);
5349 if (!hdspm->running && running)
5350 hdspm_start_audio(hdspm);
5351 else if (hdspm->running && !running)
5352 hdspm_stop_audio(hdspm);
5353 hdspm->running = running;
5354 spin_unlock(&hdspm->lock);
5355
5356 return 0;
5357}
5358
Takashi Iwai98274f02005-11-17 14:52:34 +01005359static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005360{
5361 return 0;
5362}
5363
Adrian Knoth0dca1792011-01-26 19:32:14 +01005364static unsigned int period_sizes_old[] = {
5365 64, 128, 256, 512, 1024, 2048, 4096
5366};
5367
5368static unsigned int period_sizes_new[] = {
5369 32, 64, 128, 256, 512, 1024, 2048, 4096
5370};
5371
5372/* RayDAT and AIO always have a buffer of 16384 samples per channel */
5373static unsigned int raydat_aio_buffer_sizes[] = {
5374 16384
5375};
Takashi Iwai763f3562005-06-03 11:25:34 +02005376
Takashi Iwai98274f02005-11-17 14:52:34 +01005377static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005378 .info = (SNDRV_PCM_INFO_MMAP |
5379 SNDRV_PCM_INFO_MMAP_VALID |
5380 SNDRV_PCM_INFO_NONINTERLEAVED |
5381 SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
5382 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5383 .rates = (SNDRV_PCM_RATE_32000 |
5384 SNDRV_PCM_RATE_44100 |
5385 SNDRV_PCM_RATE_48000 |
5386 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005387 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5388 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ),
Takashi Iwai763f3562005-06-03 11:25:34 +02005389 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005390 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005391 .channels_min = 1,
5392 .channels_max = HDSPM_MAX_CHANNELS,
5393 .buffer_bytes_max =
5394 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
5395 .period_bytes_min = (64 * 4),
Adrian Knoth0dca1792011-01-26 19:32:14 +01005396 .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005397 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005398 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005399 .fifo_size = 0
5400};
5401
Takashi Iwai98274f02005-11-17 14:52:34 +01005402static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005403 .info = (SNDRV_PCM_INFO_MMAP |
5404 SNDRV_PCM_INFO_MMAP_VALID |
5405 SNDRV_PCM_INFO_NONINTERLEAVED |
5406 SNDRV_PCM_INFO_SYNC_START),
5407 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5408 .rates = (SNDRV_PCM_RATE_32000 |
5409 SNDRV_PCM_RATE_44100 |
5410 SNDRV_PCM_RATE_48000 |
5411 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005412 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5413 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
Takashi Iwai763f3562005-06-03 11:25:34 +02005414 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005415 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005416 .channels_min = 1,
5417 .channels_max = HDSPM_MAX_CHANNELS,
5418 .buffer_bytes_max =
5419 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
5420 .period_bytes_min = (64 * 4),
Adrian Knoth0dca1792011-01-26 19:32:14 +01005421 .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005422 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005423 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005424 .fifo_size = 0
5425};
5426
Adrian Knoth0dca1792011-01-26 19:32:14 +01005427static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_old = {
5428 .count = ARRAY_SIZE(period_sizes_old),
5429 .list = period_sizes_old,
Takashi Iwai763f3562005-06-03 11:25:34 +02005430 .mask = 0
5431};
5432
Adrian Knoth0dca1792011-01-26 19:32:14 +01005433static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_new = {
5434 .count = ARRAY_SIZE(period_sizes_new),
5435 .list = period_sizes_new,
5436 .mask = 0
5437};
Takashi Iwai763f3562005-06-03 11:25:34 +02005438
Adrian Knoth0dca1792011-01-26 19:32:14 +01005439static struct snd_pcm_hw_constraint_list hw_constraints_raydat_io_buffer = {
5440 .count = ARRAY_SIZE(raydat_aio_buffer_sizes),
5441 .list = raydat_aio_buffer_sizes,
5442 .mask = 0
5443};
5444
5445static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
5446 struct snd_pcm_hw_rule *rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005447{
Takashi Iwai98274f02005-11-17 14:52:34 +01005448 struct hdspm *hdspm = rule->private;
5449 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005450 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005451 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005452 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5453
Adrian Knoth0dca1792011-01-26 19:32:14 +01005454 if (r->min > 96000 && r->max <= 192000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005455 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005456 .min = hdspm->qs_in_channels,
5457 .max = hdspm->qs_in_channels,
5458 .integer = 1,
5459 };
5460 return snd_interval_refine(c, &t);
5461 } else if (r->min > 48000 && r->max <= 96000) {
5462 struct snd_interval t = {
5463 .min = hdspm->ds_in_channels,
5464 .max = hdspm->ds_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005465 .integer = 1,
5466 };
5467 return snd_interval_refine(c, &t);
5468 } else if (r->max < 64000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005469 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005470 .min = hdspm->ss_in_channels,
5471 .max = hdspm->ss_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005472 .integer = 1,
5473 };
5474 return snd_interval_refine(c, &t);
5475 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005476
Takashi Iwai763f3562005-06-03 11:25:34 +02005477 return 0;
5478}
5479
Adrian Knoth0dca1792011-01-26 19:32:14 +01005480static int snd_hdspm_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
Takashi Iwai98274f02005-11-17 14:52:34 +01005481 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005482{
Takashi Iwai98274f02005-11-17 14:52:34 +01005483 struct hdspm *hdspm = rule->private;
5484 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005485 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005486 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005487 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5488
Adrian Knoth0dca1792011-01-26 19:32:14 +01005489 if (r->min > 96000 && r->max <= 192000) {
5490 struct snd_interval t = {
5491 .min = hdspm->qs_out_channels,
5492 .max = hdspm->qs_out_channels,
5493 .integer = 1,
5494 };
5495 return snd_interval_refine(c, &t);
5496 } else if (r->min > 48000 && r->max <= 96000) {
5497 struct snd_interval t = {
5498 .min = hdspm->ds_out_channels,
5499 .max = hdspm->ds_out_channels,
5500 .integer = 1,
5501 };
5502 return snd_interval_refine(c, &t);
5503 } else if (r->max < 64000) {
5504 struct snd_interval t = {
5505 .min = hdspm->ss_out_channels,
5506 .max = hdspm->ss_out_channels,
5507 .integer = 1,
5508 };
5509 return snd_interval_refine(c, &t);
5510 } else {
5511 }
5512 return 0;
5513}
5514
5515static int snd_hdspm_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
5516 struct snd_pcm_hw_rule * rule)
5517{
5518 struct hdspm *hdspm = rule->private;
5519 struct snd_interval *c =
5520 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5521 struct snd_interval *r =
5522 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5523
5524 if (c->min >= hdspm->ss_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005525 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005526 .min = 32000,
5527 .max = 48000,
5528 .integer = 1,
5529 };
5530 return snd_interval_refine(r, &t);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005531 } else if (c->max <= hdspm->qs_in_channels) {
5532 struct snd_interval t = {
5533 .min = 128000,
5534 .max = 192000,
5535 .integer = 1,
5536 };
5537 return snd_interval_refine(r, &t);
5538 } else if (c->max <= hdspm->ds_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005539 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005540 .min = 64000,
5541 .max = 96000,
5542 .integer = 1,
5543 };
Takashi Iwai763f3562005-06-03 11:25:34 +02005544 return snd_interval_refine(r, &t);
5545 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005546
5547 return 0;
5548}
5549static int snd_hdspm_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
5550 struct snd_pcm_hw_rule *rule)
5551{
5552 struct hdspm *hdspm = rule->private;
5553 struct snd_interval *c =
5554 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5555 struct snd_interval *r =
5556 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5557
5558 if (c->min >= hdspm->ss_out_channels) {
5559 struct snd_interval t = {
5560 .min = 32000,
5561 .max = 48000,
5562 .integer = 1,
5563 };
5564 return snd_interval_refine(r, &t);
5565 } else if (c->max <= hdspm->qs_out_channels) {
5566 struct snd_interval t = {
5567 .min = 128000,
5568 .max = 192000,
5569 .integer = 1,
5570 };
5571 return snd_interval_refine(r, &t);
5572 } else if (c->max <= hdspm->ds_out_channels) {
5573 struct snd_interval t = {
5574 .min = 64000,
5575 .max = 96000,
5576 .integer = 1,
5577 };
5578 return snd_interval_refine(r, &t);
5579 }
5580
Takashi Iwai763f3562005-06-03 11:25:34 +02005581 return 0;
5582}
5583
Adrian Knoth0dca1792011-01-26 19:32:14 +01005584static int snd_hdspm_hw_rule_in_channels(struct snd_pcm_hw_params *params,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005585 struct snd_pcm_hw_rule *rule)
5586{
5587 unsigned int list[3];
5588 struct hdspm *hdspm = rule->private;
5589 struct snd_interval *c = hw_param_interval(params,
5590 SNDRV_PCM_HW_PARAM_CHANNELS);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005591
5592 list[0] = hdspm->qs_in_channels;
5593 list[1] = hdspm->ds_in_channels;
5594 list[2] = hdspm->ss_in_channels;
5595 return snd_interval_list(c, 3, list, 0);
5596}
5597
5598static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params,
5599 struct snd_pcm_hw_rule *rule)
5600{
5601 unsigned int list[3];
5602 struct hdspm *hdspm = rule->private;
5603 struct snd_interval *c = hw_param_interval(params,
5604 SNDRV_PCM_HW_PARAM_CHANNELS);
5605
5606 list[0] = hdspm->qs_out_channels;
5607 list[1] = hdspm->ds_out_channels;
5608 list[2] = hdspm->ss_out_channels;
5609 return snd_interval_list(c, 3, list, 0);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005610}
5611
5612
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005613static unsigned int hdspm_aes32_sample_rates[] = {
5614 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000
5615};
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005616
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005617static struct snd_pcm_hw_constraint_list
5618hdspm_hw_constraints_aes32_sample_rates = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005619 .count = ARRAY_SIZE(hdspm_aes32_sample_rates),
5620 .list = hdspm_aes32_sample_rates,
5621 .mask = 0
5622};
5623
Takashi Iwai98274f02005-11-17 14:52:34 +01005624static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005625{
Takashi Iwai98274f02005-11-17 14:52:34 +01005626 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5627 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02005628
Takashi Iwai763f3562005-06-03 11:25:34 +02005629 spin_lock_irq(&hdspm->lock);
5630
5631 snd_pcm_set_sync(substream);
5632
Adrian Knoth0dca1792011-01-26 19:32:14 +01005633
Takashi Iwai763f3562005-06-03 11:25:34 +02005634 runtime->hw = snd_hdspm_playback_subinfo;
5635
5636 if (hdspm->capture_substream == NULL)
5637 hdspm_stop_audio(hdspm);
5638
5639 hdspm->playback_pid = current->pid;
5640 hdspm->playback_substream = substream;
5641
5642 spin_unlock_irq(&hdspm->lock);
5643
5644 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
5645
Adrian Knoth0dca1792011-01-26 19:32:14 +01005646 switch (hdspm->io_type) {
5647 case AIO:
5648 case RayDAT:
5649 snd_pcm_hw_constraint_list(runtime, 0,
5650 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5651 &hw_constraints_period_sizes_new);
5652 snd_pcm_hw_constraint_list(runtime, 0,
5653 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
5654 &hw_constraints_raydat_io_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005655
Adrian Knoth0dca1792011-01-26 19:32:14 +01005656 break;
5657
5658 default:
5659 snd_pcm_hw_constraint_list(runtime, 0,
5660 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5661 &hw_constraints_period_sizes_old);
5662 }
5663
5664 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005665 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
5666 &hdspm_hw_constraints_aes32_sample_rates);
5667 } else {
5668 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005669 snd_hdspm_hw_rule_out_channels, hdspm,
5670 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005671 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005672 snd_hdspm_hw_rule_out_channels_rate, hdspm,
5673 SNDRV_PCM_HW_PARAM_RATE, -1);
Takashi Iwai763f3562005-06-03 11:25:34 +02005674
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005675 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005676 snd_hdspm_hw_rule_rate_out_channels, hdspm,
5677 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005678 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005679 return 0;
5680}
5681
Takashi Iwai98274f02005-11-17 14:52:34 +01005682static int snd_hdspm_playback_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005683{
Takashi Iwai98274f02005-11-17 14:52:34 +01005684 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005685
5686 spin_lock_irq(&hdspm->lock);
5687
5688 hdspm->playback_pid = -1;
5689 hdspm->playback_substream = NULL;
5690
5691 spin_unlock_irq(&hdspm->lock);
5692
5693 return 0;
5694}
5695
5696
Takashi Iwai98274f02005-11-17 14:52:34 +01005697static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005698{
Takashi Iwai98274f02005-11-17 14:52:34 +01005699 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5700 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02005701
5702 spin_lock_irq(&hdspm->lock);
5703 snd_pcm_set_sync(substream);
5704 runtime->hw = snd_hdspm_capture_subinfo;
5705
5706 if (hdspm->playback_substream == NULL)
5707 hdspm_stop_audio(hdspm);
5708
5709 hdspm->capture_pid = current->pid;
5710 hdspm->capture_substream = substream;
5711
5712 spin_unlock_irq(&hdspm->lock);
5713
5714 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005715 switch (hdspm->io_type) {
5716 case AIO:
5717 case RayDAT:
5718 snd_pcm_hw_constraint_list(runtime, 0,
5719 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5720 &hw_constraints_period_sizes_new);
5721 snd_pcm_hw_constraint_list(runtime, 0,
5722 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
5723 &hw_constraints_raydat_io_buffer);
5724 break;
5725
5726 default:
5727 snd_pcm_hw_constraint_list(runtime, 0,
5728 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5729 &hw_constraints_period_sizes_old);
5730 }
5731
5732 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005733 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
5734 &hdspm_hw_constraints_aes32_sample_rates);
5735 } else {
5736 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005737 snd_hdspm_hw_rule_in_channels, hdspm,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005738 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
5739 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005740 snd_hdspm_hw_rule_in_channels_rate, hdspm,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005741 SNDRV_PCM_HW_PARAM_RATE, -1);
Takashi Iwai763f3562005-06-03 11:25:34 +02005742
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005743 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005744 snd_hdspm_hw_rule_rate_in_channels, hdspm,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005745 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
5746 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005747 return 0;
5748}
5749
Takashi Iwai98274f02005-11-17 14:52:34 +01005750static int snd_hdspm_capture_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005751{
Takashi Iwai98274f02005-11-17 14:52:34 +01005752 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005753
5754 spin_lock_irq(&hdspm->lock);
5755
5756 hdspm->capture_pid = -1;
5757 hdspm->capture_substream = NULL;
5758
5759 spin_unlock_irq(&hdspm->lock);
5760 return 0;
5761}
5762
Adrian Knoth0dca1792011-01-26 19:32:14 +01005763static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
Takashi Iwai763f3562005-06-03 11:25:34 +02005764{
Adrian Knoth0dca1792011-01-26 19:32:14 +01005765 /* we have nothing to initialize but the call is required */
5766 return 0;
5767}
5768
5769static inline int copy_u32_le(void __user *dest, void __iomem *src)
5770{
5771 u32 val = readl(src);
5772 return copy_to_user(dest, &val, 4);
5773}
5774
5775static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
5776 unsigned int cmd, unsigned long __user arg)
5777{
5778 void __user *argp = (void __user *)arg;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005779 struct hdspm *hdspm = hw->private_data;
Takashi Iwai98274f02005-11-17 14:52:34 +01005780 struct hdspm_mixer_ioctl mixer;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005781 struct hdspm_config info;
5782 struct hdspm_status status;
Takashi Iwai98274f02005-11-17 14:52:34 +01005783 struct hdspm_version hdspm_version;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005784 struct hdspm_peak_rms levels;
5785 struct hdspm_ltc ltc;
5786 unsigned int statusregister;
5787 long unsigned int s;
5788 int i = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005789
5790 switch (cmd) {
5791
Takashi Iwai763f3562005-06-03 11:25:34 +02005792 case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
Adrian Knoth0dca1792011-01-26 19:32:14 +01005793 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
5794 levels.input_peaks[i] =
5795 readl(hdspm->iobase +
5796 HDSPM_MADI_INPUT_PEAK + i*4);
5797 levels.playback_peaks[i] =
5798 readl(hdspm->iobase +
5799 HDSPM_MADI_PLAYBACK_PEAK + i*4);
5800 levels.output_peaks[i] =
5801 readl(hdspm->iobase +
5802 HDSPM_MADI_OUTPUT_PEAK + i*4);
5803
5804 levels.input_rms[i] =
5805 ((uint64_t) readl(hdspm->iobase +
5806 HDSPM_MADI_INPUT_RMS_H + i*4) << 32) |
5807 (uint64_t) readl(hdspm->iobase +
5808 HDSPM_MADI_INPUT_RMS_L + i*4);
5809 levels.playback_rms[i] =
5810 ((uint64_t)readl(hdspm->iobase +
5811 HDSPM_MADI_PLAYBACK_RMS_H+i*4) << 32) |
5812 (uint64_t)readl(hdspm->iobase +
5813 HDSPM_MADI_PLAYBACK_RMS_L + i*4);
5814 levels.output_rms[i] =
5815 ((uint64_t)readl(hdspm->iobase +
5816 HDSPM_MADI_OUTPUT_RMS_H + i*4) << 32) |
5817 (uint64_t)readl(hdspm->iobase +
5818 HDSPM_MADI_OUTPUT_RMS_L + i*4);
5819 }
5820
5821 if (hdspm->system_sample_rate > 96000) {
5822 levels.speed = qs;
5823 } else if (hdspm->system_sample_rate > 48000) {
5824 levels.speed = ds;
5825 } else {
5826 levels.speed = ss;
5827 }
5828 levels.status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
5829
5830 s = copy_to_user(argp, &levels, sizeof(struct hdspm_peak_rms));
5831 if (0 != s) {
5832 /* snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu
5833 [Levels]\n", sizeof(struct hdspm_peak_rms), s);
5834 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005835 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005836 }
5837 break;
5838
5839 case SNDRV_HDSPM_IOCTL_GET_LTC:
5840 ltc.ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
5841 i = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
5842 if (i & HDSPM_TCO1_LTC_Input_valid) {
5843 switch (i & (HDSPM_TCO1_LTC_Format_LSB |
5844 HDSPM_TCO1_LTC_Format_MSB)) {
5845 case 0:
5846 ltc.format = fps_24;
5847 break;
5848 case HDSPM_TCO1_LTC_Format_LSB:
5849 ltc.format = fps_25;
5850 break;
5851 case HDSPM_TCO1_LTC_Format_MSB:
5852 ltc.format = fps_2997;
5853 break;
5854 default:
5855 ltc.format = 30;
5856 break;
5857 }
5858 if (i & HDSPM_TCO1_set_drop_frame_flag) {
5859 ltc.frame = drop_frame;
5860 } else {
5861 ltc.frame = full_frame;
5862 }
5863 } else {
5864 ltc.format = format_invalid;
5865 ltc.frame = frame_invalid;
5866 }
5867 if (i & HDSPM_TCO1_Video_Input_Format_NTSC) {
5868 ltc.input_format = ntsc;
5869 } else if (i & HDSPM_TCO1_Video_Input_Format_PAL) {
5870 ltc.input_format = pal;
5871 } else {
5872 ltc.input_format = no_video;
5873 }
5874
5875 s = copy_to_user(argp, &ltc, sizeof(struct hdspm_ltc));
5876 if (0 != s) {
5877 /*
5878 snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */
Takashi Iwai763f3562005-06-03 11:25:34 +02005879 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005880 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005881
5882 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02005883
Adrian Knoth0dca1792011-01-26 19:32:14 +01005884 case SNDRV_HDSPM_IOCTL_GET_CONFIG:
Takashi Iwai763f3562005-06-03 11:25:34 +02005885
5886 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005887 info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
5888 info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02005889
5890 info.system_sample_rate = hdspm->system_sample_rate;
5891 info.autosync_sample_rate =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005892 hdspm_external_sample_rate(hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005893 info.system_clock_mode = hdspm_system_clock_mode(hdspm);
5894 info.clock_source = hdspm_clock_source(hdspm);
5895 info.autosync_ref = hdspm_autosync_ref(hdspm);
5896 info.line_out = hdspm_line_out(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02005897 info.passthru = 0;
5898 spin_unlock_irq(&hdspm->lock);
5899 if (copy_to_user((void __user *) arg, &info, sizeof(info)))
5900 return -EFAULT;
5901 break;
5902
Adrian Knoth0dca1792011-01-26 19:32:14 +01005903 case SNDRV_HDSPM_IOCTL_GET_STATUS:
5904 status.card_type = hdspm->io_type;
5905
5906 status.autosync_source = hdspm_autosync_ref(hdspm);
5907
5908 status.card_clock = 110069313433624ULL;
5909 status.master_period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
5910
5911 switch (hdspm->io_type) {
5912 case MADI:
5913 case MADIface:
5914 status.card_specific.madi.sync_wc =
5915 hdspm_wc_sync_check(hdspm);
5916 status.card_specific.madi.sync_madi =
5917 hdspm_madi_sync_check(hdspm);
5918 status.card_specific.madi.sync_tco =
5919 hdspm_tco_sync_check(hdspm);
5920 status.card_specific.madi.sync_in =
5921 hdspm_sync_in_sync_check(hdspm);
5922
5923 statusregister =
5924 hdspm_read(hdspm, HDSPM_statusRegister);
5925 status.card_specific.madi.madi_input =
5926 (statusregister & HDSPM_AB_int) ? 1 : 0;
5927 status.card_specific.madi.channel_format =
5928 (statusregister & HDSPM_TX_64ch) ? 1 : 0;
5929 /* TODO: Mac driver sets it when f_s>48kHz */
5930 status.card_specific.madi.frame_format = 0;
5931
5932 default:
5933 break;
5934 }
5935
5936 if (copy_to_user((void __user *) arg, &status, sizeof(status)))
5937 return -EFAULT;
5938
5939
5940 break;
5941
Takashi Iwai763f3562005-06-03 11:25:34 +02005942 case SNDRV_HDSPM_IOCTL_GET_VERSION:
Adrian Knoth0dca1792011-01-26 19:32:14 +01005943 hdspm_version.card_type = hdspm->io_type;
5944 strncpy(hdspm_version.cardname, hdspm->card_name,
5945 sizeof(hdspm_version.cardname));
5946 hdspm_version.serial = (hdspm_read(hdspm,
5947 HDSPM_midiStatusIn0)>>8) & 0xFFFFFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02005948 hdspm_version.firmware_rev = hdspm->firmware_rev;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005949 hdspm_version.addons = 0;
5950 if (hdspm->tco)
5951 hdspm_version.addons |= HDSPM_ADDON_TCO;
5952
Takashi Iwai763f3562005-06-03 11:25:34 +02005953 if (copy_to_user((void __user *) arg, &hdspm_version,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005954 sizeof(hdspm_version)))
Takashi Iwai763f3562005-06-03 11:25:34 +02005955 return -EFAULT;
5956 break;
5957
5958 case SNDRV_HDSPM_IOCTL_GET_MIXER:
5959 if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer)))
5960 return -EFAULT;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005961 if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005962 sizeof(struct hdspm_mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02005963 return -EFAULT;
5964 break;
5965
5966 default:
5967 return -EINVAL;
5968 }
5969 return 0;
5970}
5971
Takashi Iwai98274f02005-11-17 14:52:34 +01005972static struct snd_pcm_ops snd_hdspm_playback_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005973 .open = snd_hdspm_playback_open,
5974 .close = snd_hdspm_playback_release,
5975 .ioctl = snd_hdspm_ioctl,
5976 .hw_params = snd_hdspm_hw_params,
5977 .hw_free = snd_hdspm_hw_free,
5978 .prepare = snd_hdspm_prepare,
5979 .trigger = snd_hdspm_trigger,
5980 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02005981 .page = snd_pcm_sgbuf_ops_page,
5982};
5983
Takashi Iwai98274f02005-11-17 14:52:34 +01005984static struct snd_pcm_ops snd_hdspm_capture_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005985 .open = snd_hdspm_capture_open,
5986 .close = snd_hdspm_capture_release,
5987 .ioctl = snd_hdspm_ioctl,
5988 .hw_params = snd_hdspm_hw_params,
5989 .hw_free = snd_hdspm_hw_free,
5990 .prepare = snd_hdspm_prepare,
5991 .trigger = snd_hdspm_trigger,
5992 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02005993 .page = snd_pcm_sgbuf_ops_page,
5994};
5995
Takashi Iwai98274f02005-11-17 14:52:34 +01005996static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
5997 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005998{
Takashi Iwai98274f02005-11-17 14:52:34 +01005999 struct snd_hwdep *hw;
Takashi Iwai763f3562005-06-03 11:25:34 +02006000 int err;
6001
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006002 err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw);
6003 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006004 return err;
6005
6006 hdspm->hwdep = hw;
6007 hw->private_data = hdspm;
6008 strcpy(hw->name, "HDSPM hwdep interface");
6009
Adrian Knoth0dca1792011-01-26 19:32:14 +01006010 hw->ops.open = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006011 hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006012 hw->ops.release = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006013
6014 return 0;
6015}
6016
6017
6018/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01006019 memory interface
Takashi Iwai763f3562005-06-03 11:25:34 +02006020 ------------------------------------------------------------*/
Adrian Knoth0dca1792011-01-26 19:32:14 +01006021static int __devinit snd_hdspm_preallocate_memory(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006022{
6023 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01006024 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006025 size_t wanted;
6026
6027 pcm = hdspm->pcm;
6028
Remy Bruno3cee5a62006-10-16 12:46:32 +02006029 wanted = HDSPM_DMA_AREA_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02006030
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006031 err =
Takashi Iwai763f3562005-06-03 11:25:34 +02006032 snd_pcm_lib_preallocate_pages_for_all(pcm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006033 SNDRV_DMA_TYPE_DEV_SG,
Takashi Iwai763f3562005-06-03 11:25:34 +02006034 snd_dma_pci_data(hdspm->pci),
6035 wanted,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006036 wanted);
6037 if (err < 0) {
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006038 snd_printdd("Could not preallocate %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006039
6040 return err;
6041 } else
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006042 snd_printdd(" Preallocated %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006043
6044 return 0;
6045}
6046
Adrian Knoth0dca1792011-01-26 19:32:14 +01006047
6048static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +02006049 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02006050 unsigned int reg, int channels)
6051{
6052 int i;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006053
6054 /* continuous memory segment */
Takashi Iwai763f3562005-06-03 11:25:34 +02006055 for (i = 0; i < (channels * 16); i++)
6056 hdspm_write(hdspm, reg + 4 * i,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006057 snd_pcm_sgbuf_get_addr(substream, 4096 * i));
Takashi Iwai763f3562005-06-03 11:25:34 +02006058}
6059
Adrian Knoth0dca1792011-01-26 19:32:14 +01006060
Takashi Iwai763f3562005-06-03 11:25:34 +02006061/* ------------- ALSA Devices ---------------------------- */
Takashi Iwai98274f02005-11-17 14:52:34 +01006062static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006063 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006064{
Takashi Iwai98274f02005-11-17 14:52:34 +01006065 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006066 int err;
6067
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006068 err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm);
6069 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006070 return err;
6071
6072 hdspm->pcm = pcm;
6073 pcm->private_data = hdspm;
6074 strcpy(pcm->name, hdspm->card_name);
6075
6076 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
6077 &snd_hdspm_playback_ops);
6078 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
6079 &snd_hdspm_capture_ops);
6080
6081 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
6082
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006083 err = snd_hdspm_preallocate_memory(hdspm);
6084 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006085 return err;
6086
6087 return 0;
6088}
6089
Takashi Iwai98274f02005-11-17 14:52:34 +01006090static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006091{
6092 snd_hdspm_flush_midi_input(hdspm, 0);
6093 snd_hdspm_flush_midi_input(hdspm, 1);
6094}
6095
Takashi Iwai98274f02005-11-17 14:52:34 +01006096static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
6097 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006098{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006099 int err, i;
Takashi Iwai763f3562005-06-03 11:25:34 +02006100
6101 snd_printdd("Create card...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006102 err = snd_hdspm_create_pcm(card, hdspm);
6103 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006104 return err;
6105
Adrian Knoth0dca1792011-01-26 19:32:14 +01006106 i = 0;
6107 while (i < hdspm->midiPorts) {
6108 err = snd_hdspm_create_midi(card, hdspm, i);
6109 if (err < 0) {
6110 return err;
6111 }
6112 i++;
6113 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006114
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006115 err = snd_hdspm_create_controls(card, hdspm);
6116 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006117 return err;
6118
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006119 err = snd_hdspm_create_hwdep(card, hdspm);
6120 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006121 return err;
6122
6123 snd_printdd("proc init...\n");
6124 snd_hdspm_proc_init(hdspm);
6125
6126 hdspm->system_sample_rate = -1;
6127 hdspm->last_external_sample_rate = -1;
6128 hdspm->last_internal_sample_rate = -1;
6129 hdspm->playback_pid = -1;
6130 hdspm->capture_pid = -1;
6131 hdspm->capture_substream = NULL;
6132 hdspm->playback_substream = NULL;
6133
6134 snd_printdd("Set defaults...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006135 err = snd_hdspm_set_defaults(hdspm);
6136 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006137 return err;
6138
6139 snd_printdd("Update mixer controls...\n");
6140 hdspm_update_simple_mixer_controls(hdspm);
6141
6142 snd_printdd("Initializeing complete ???\n");
6143
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006144 err = snd_card_register(card);
6145 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006146 snd_printk(KERN_ERR "HDSPM: error registering card\n");
6147 return err;
6148 }
6149
6150 snd_printdd("... yes now\n");
6151
6152 return 0;
6153}
6154
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006155static int __devinit snd_hdspm_create(struct snd_card *card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006156 struct hdspm *hdspm) {
6157
Takashi Iwai763f3562005-06-03 11:25:34 +02006158 struct pci_dev *pci = hdspm->pci;
6159 int err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006160 unsigned long io_extent;
6161
6162 hdspm->irq = -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02006163 hdspm->card = card;
6164
6165 spin_lock_init(&hdspm->lock);
6166
Takashi Iwai763f3562005-06-03 11:25:34 +02006167 pci_read_config_word(hdspm->pci,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006168 PCI_CLASS_REVISION, &hdspm->firmware_rev);
Remy Bruno3cee5a62006-10-16 12:46:32 +02006169
Takashi Iwai763f3562005-06-03 11:25:34 +02006170 strcpy(card->mixername, "Xilinx FPGA");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006171 strcpy(card->driver, "HDSPM");
6172
6173 switch (hdspm->firmware_rev) {
6174 case HDSPM_MADI_REV:
6175 hdspm->io_type = MADI;
6176 hdspm->card_name = "RME MADI";
6177 hdspm->midiPorts = 3;
6178 break;
6179 case HDSPM_RAYDAT_REV:
6180 hdspm->io_type = RayDAT;
6181 hdspm->card_name = "RME RayDAT";
6182 hdspm->midiPorts = 2;
6183 break;
6184 case HDSPM_AIO_REV:
6185 hdspm->io_type = AIO;
6186 hdspm->card_name = "RME AIO";
6187 hdspm->midiPorts = 1;
6188 break;
6189 case HDSPM_MADIFACE_REV:
6190 hdspm->io_type = MADIface;
6191 hdspm->card_name = "RME MADIface";
6192 hdspm->midiPorts = 1;
6193 break;
6194 case HDSPM_AES_REV:
6195 hdspm->io_type = AES32;
6196 hdspm->card_name = "RME AES32";
6197 hdspm->midiPorts = 2;
6198 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02006199 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006200
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006201 err = pci_enable_device(pci);
6202 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006203 return err;
6204
6205 pci_set_master(hdspm->pci);
6206
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006207 err = pci_request_regions(pci, "hdspm");
6208 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006209 return err;
6210
6211 hdspm->port = pci_resource_start(pci, 0);
6212 io_extent = pci_resource_len(pci, 0);
6213
6214 snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006215 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006216
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006217 hdspm->iobase = ioremap_nocache(hdspm->port, io_extent);
6218 if (!hdspm->iobase) {
6219 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006220 "unable to remap region 0x%lx-0x%lx\n",
6221 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006222 return -EBUSY;
6223 }
6224 snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006225 (unsigned long)hdspm->iobase, hdspm->port,
6226 hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006227
6228 if (request_irq(pci->irq, snd_hdspm_interrupt,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006229 IRQF_SHARED, "hdspm", hdspm)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006230 snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
6231 return -EBUSY;
6232 }
6233
6234 snd_printdd("use IRQ %d\n", pci->irq);
6235
6236 hdspm->irq = pci->irq;
Takashi Iwai763f3562005-06-03 11:25:34 +02006237
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006238 snd_printdd("kmalloc Mixer memory of %zd Bytes\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006239 sizeof(struct hdspm_mixer));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006240 hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL);
6241 if (!hdspm->mixer) {
6242 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006243 "unable to kmalloc Mixer memory of %d Bytes\n",
6244 (int)sizeof(struct hdspm_mixer));
Takashi Iwai763f3562005-06-03 11:25:34 +02006245 return err;
6246 }
6247
Adrian Knoth0dca1792011-01-26 19:32:14 +01006248 hdspm->port_names_in = NULL;
6249 hdspm->port_names_out = NULL;
6250
6251 switch (hdspm->io_type) {
6252 case AES32:
6253 break;
6254
6255 case MADI:
6256 case MADIface:
6257 hdspm->ss_in_channels = hdspm->ss_out_channels =
6258 MADI_SS_CHANNELS;
6259 hdspm->ds_in_channels = hdspm->ds_out_channels =
6260 MADI_DS_CHANNELS;
6261 hdspm->qs_in_channels = hdspm->qs_out_channels =
6262 MADI_QS_CHANNELS;
6263
6264 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6265 channel_map_unity_ss;
6266 hdspm->channel_map_in_ds = hdspm->channel_map_out_ss =
6267 channel_map_unity_ss;
6268 hdspm->channel_map_in_qs = hdspm->channel_map_out_ss =
6269 channel_map_unity_ss;
6270
6271 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6272 texts_ports_madi;
6273 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6274 texts_ports_madi;
6275 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6276 texts_ports_madi;
6277 break;
6278
6279 case AIO:
6280 if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) {
6281 snd_printk(KERN_INFO "HDSPM: AEB input board found, but not supported\n");
6282 }
6283
6284 hdspm->ss_in_channels = AIO_IN_SS_CHANNELS;
6285 hdspm->ds_in_channels = AIO_IN_DS_CHANNELS;
6286 hdspm->qs_in_channels = AIO_IN_QS_CHANNELS;
6287 hdspm->ss_out_channels = AIO_OUT_SS_CHANNELS;
6288 hdspm->ds_out_channels = AIO_OUT_DS_CHANNELS;
6289 hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS;
6290
6291 hdspm->channel_map_out_ss = channel_map_aio_out_ss;
6292 hdspm->channel_map_out_ds = channel_map_aio_out_ds;
6293 hdspm->channel_map_out_qs = channel_map_aio_out_qs;
6294
6295 hdspm->channel_map_in_ss = channel_map_aio_in_ss;
6296 hdspm->channel_map_in_ds = channel_map_aio_in_ds;
6297 hdspm->channel_map_in_qs = channel_map_aio_in_qs;
6298
6299 hdspm->port_names_in_ss = texts_ports_aio_in_ss;
6300 hdspm->port_names_out_ss = texts_ports_aio_out_ss;
6301 hdspm->port_names_in_ds = texts_ports_aio_in_ds;
6302 hdspm->port_names_out_ds = texts_ports_aio_out_ds;
6303 hdspm->port_names_in_qs = texts_ports_aio_in_qs;
6304 hdspm->port_names_out_qs = texts_ports_aio_out_qs;
6305
6306 break;
6307
6308 case RayDAT:
6309 hdspm->ss_in_channels = hdspm->ss_out_channels =
6310 RAYDAT_SS_CHANNELS;
6311 hdspm->ds_in_channels = hdspm->ds_out_channels =
6312 RAYDAT_DS_CHANNELS;
6313 hdspm->qs_in_channels = hdspm->qs_out_channels =
6314 RAYDAT_QS_CHANNELS;
6315
6316 hdspm->max_channels_in = RAYDAT_SS_CHANNELS;
6317 hdspm->max_channels_out = RAYDAT_SS_CHANNELS;
6318
6319 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6320 channel_map_raydat_ss;
6321 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6322 channel_map_raydat_ds;
6323 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6324 channel_map_raydat_qs;
6325 hdspm->channel_map_in = hdspm->channel_map_out =
6326 channel_map_raydat_ss;
6327
6328 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6329 texts_ports_raydat_ss;
6330 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6331 texts_ports_raydat_ds;
6332 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6333 texts_ports_raydat_qs;
6334
6335
6336 break;
6337
6338 }
6339
6340 /* TCO detection */
6341 switch (hdspm->io_type) {
6342 case AIO:
6343 case RayDAT:
6344 if (hdspm_read(hdspm, HDSPM_statusRegister2) &
6345 HDSPM_s2_tco_detect) {
6346 hdspm->midiPorts++;
6347 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6348 GFP_KERNEL);
6349 if (NULL != hdspm->tco) {
6350 hdspm_tco_write(hdspm);
6351 }
6352 snd_printk(KERN_INFO "HDSPM: AIO/RayDAT TCO module found\n");
6353 } else {
6354 hdspm->tco = NULL;
6355 }
6356 break;
6357
6358 case MADI:
6359 if (hdspm_read(hdspm, HDSPM_statusRegister) & HDSPM_tco_detect) {
6360 hdspm->midiPorts++;
6361 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6362 GFP_KERNEL);
6363 if (NULL != hdspm->tco) {
6364 hdspm_tco_write(hdspm);
6365 }
6366 snd_printk(KERN_INFO "HDSPM: MADI TCO module found\n");
6367 } else {
6368 hdspm->tco = NULL;
6369 }
6370 break;
6371
6372 default:
6373 hdspm->tco = NULL;
6374 }
6375
6376 /* texts */
6377 switch (hdspm->io_type) {
6378 case AES32:
6379 if (hdspm->tco) {
6380 hdspm->texts_autosync = texts_autosync_aes_tco;
6381 hdspm->texts_autosync_items = 10;
6382 } else {
6383 hdspm->texts_autosync = texts_autosync_aes;
6384 hdspm->texts_autosync_items = 9;
6385 }
6386 break;
6387
6388 case MADI:
6389 if (hdspm->tco) {
6390 hdspm->texts_autosync = texts_autosync_madi_tco;
6391 hdspm->texts_autosync_items = 4;
6392 } else {
6393 hdspm->texts_autosync = texts_autosync_madi;
6394 hdspm->texts_autosync_items = 3;
6395 }
6396 break;
6397
6398 case MADIface:
6399
6400 break;
6401
6402 case RayDAT:
6403 if (hdspm->tco) {
6404 hdspm->texts_autosync = texts_autosync_raydat_tco;
6405 hdspm->texts_autosync_items = 9;
6406 } else {
6407 hdspm->texts_autosync = texts_autosync_raydat;
6408 hdspm->texts_autosync_items = 8;
6409 }
6410 break;
6411
6412 case AIO:
6413 if (hdspm->tco) {
6414 hdspm->texts_autosync = texts_autosync_aio_tco;
6415 hdspm->texts_autosync_items = 6;
6416 } else {
6417 hdspm->texts_autosync = texts_autosync_aio;
6418 hdspm->texts_autosync_items = 5;
6419 }
6420 break;
6421
6422 }
6423
6424 tasklet_init(&hdspm->midi_tasklet,
6425 hdspm_midi_tasklet, (unsigned long) hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006426
6427 snd_printdd("create alsa devices.\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006428 err = snd_hdspm_create_alsa_devices(card, hdspm);
6429 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006430 return err;
6431
6432 snd_hdspm_initialize_midi_flush(hdspm);
6433
6434 return 0;
6435}
6436
Adrian Knoth0dca1792011-01-26 19:32:14 +01006437
Takashi Iwai98274f02005-11-17 14:52:34 +01006438static int snd_hdspm_free(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006439{
6440
6441 if (hdspm->port) {
6442
6443 /* stop th audio, and cancel all interrupts */
6444 hdspm->control_register &=
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006445 ~(HDSPM_Start | HDSPM_AudioInterruptEnable |
Adrian Knoth0dca1792011-01-26 19:32:14 +01006446 HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable |
6447 HDSPM_Midi2InterruptEnable | HDSPM_Midi3InterruptEnable);
Takashi Iwai763f3562005-06-03 11:25:34 +02006448 hdspm_write(hdspm, HDSPM_controlRegister,
6449 hdspm->control_register);
6450 }
6451
6452 if (hdspm->irq >= 0)
6453 free_irq(hdspm->irq, (void *) hdspm);
6454
Jesper Juhlfc584222005-10-24 15:11:28 +02006455 kfree(hdspm->mixer);
Takashi Iwai763f3562005-06-03 11:25:34 +02006456
6457 if (hdspm->iobase)
6458 iounmap(hdspm->iobase);
6459
Takashi Iwai763f3562005-06-03 11:25:34 +02006460 if (hdspm->port)
6461 pci_release_regions(hdspm->pci);
6462
6463 pci_disable_device(hdspm->pci);
6464 return 0;
6465}
6466
Adrian Knoth0dca1792011-01-26 19:32:14 +01006467
Takashi Iwai98274f02005-11-17 14:52:34 +01006468static void snd_hdspm_card_free(struct snd_card *card)
Takashi Iwai763f3562005-06-03 11:25:34 +02006469{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006470 struct hdspm *hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006471
6472 if (hdspm)
6473 snd_hdspm_free(hdspm);
6474}
6475
Adrian Knoth0dca1792011-01-26 19:32:14 +01006476
Takashi Iwai763f3562005-06-03 11:25:34 +02006477static int __devinit snd_hdspm_probe(struct pci_dev *pci,
6478 const struct pci_device_id *pci_id)
6479{
6480 static int dev;
Takashi Iwai98274f02005-11-17 14:52:34 +01006481 struct hdspm *hdspm;
6482 struct snd_card *card;
Takashi Iwai763f3562005-06-03 11:25:34 +02006483 int err;
6484
6485 if (dev >= SNDRV_CARDS)
6486 return -ENODEV;
6487 if (!enable[dev]) {
6488 dev++;
6489 return -ENOENT;
6490 }
6491
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006492 err = snd_card_create(index[dev], id[dev],
Adrian Knoth0dca1792011-01-26 19:32:14 +01006493 THIS_MODULE, sizeof(struct hdspm), &card);
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006494 if (err < 0)
6495 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006496
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006497 hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006498 card->private_free = snd_hdspm_card_free;
6499 hdspm->dev = dev;
6500 hdspm->pci = pci;
6501
Takashi Iwaic187c042007-02-19 15:27:33 +01006502 snd_card_set_dev(card, &pci->dev);
6503
Adrian Knoth0dca1792011-01-26 19:32:14 +01006504 err = snd_hdspm_create(card, hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006505 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006506 snd_card_free(card);
6507 return err;
6508 }
6509
Adrian Knoth0dca1792011-01-26 19:32:14 +01006510 if (hdspm->io_type != MADIface) {
6511 sprintf(card->shortname, "%s_%x",
6512 hdspm->card_name,
6513 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF);
6514 sprintf(card->longname, "%s S/N 0x%x at 0x%lx, irq %d",
6515 hdspm->card_name,
6516 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF,
6517 hdspm->port, hdspm->irq);
6518 } else {
6519 sprintf(card->shortname, "%s", hdspm->card_name);
6520 sprintf(card->longname, "%s at 0x%lx, irq %d",
6521 hdspm->card_name, hdspm->port, hdspm->irq);
6522 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006523
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006524 err = snd_card_register(card);
6525 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006526 snd_card_free(card);
6527 return err;
6528 }
6529
6530 pci_set_drvdata(pci, card);
6531
6532 dev++;
6533 return 0;
6534}
6535
6536static void __devexit snd_hdspm_remove(struct pci_dev *pci)
6537{
6538 snd_card_free(pci_get_drvdata(pci));
6539 pci_set_drvdata(pci, NULL);
6540}
6541
6542static struct pci_driver driver = {
6543 .name = "RME Hammerfall DSP MADI",
Takashi Iwai763f3562005-06-03 11:25:34 +02006544 .id_table = snd_hdspm_ids,
6545 .probe = snd_hdspm_probe,
6546 .remove = __devexit_p(snd_hdspm_remove),
6547};
6548
6549
6550static int __init alsa_card_hdspm_init(void)
6551{
6552 return pci_register_driver(&driver);
6553}
6554
6555static void __exit alsa_card_hdspm_exit(void)
6556{
6557 pci_unregister_driver(&driver);
6558}
6559
6560module_init(alsa_card_hdspm_init)
6561module_exit(alsa_card_hdspm_exit)