blob: 6de88b0ce9f426b55c16c7be2ce89fbee3f27c0d [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
Adrian Knoth0dca1792011-01-26 19:32:14 +0100578static char *texts_ports_madi[] = {
579 "MADI.1", "MADI.2", "MADI.3", "MADI.4", "MADI.5", "MADI.6",
580 "MADI.7", "MADI.8", "MADI.9", "MADI.10", "MADI.11", "MADI.12",
581 "MADI.13", "MADI.14", "MADI.15", "MADI.16", "MADI.17", "MADI.18",
582 "MADI.19", "MADI.20", "MADI.21", "MADI.22", "MADI.23", "MADI.24",
583 "MADI.25", "MADI.26", "MADI.27", "MADI.28", "MADI.29", "MADI.30",
584 "MADI.31", "MADI.32", "MADI.33", "MADI.34", "MADI.35", "MADI.36",
585 "MADI.37", "MADI.38", "MADI.39", "MADI.40", "MADI.41", "MADI.42",
586 "MADI.43", "MADI.44", "MADI.45", "MADI.46", "MADI.47", "MADI.48",
587 "MADI.49", "MADI.50", "MADI.51", "MADI.52", "MADI.53", "MADI.54",
588 "MADI.55", "MADI.56", "MADI.57", "MADI.58", "MADI.59", "MADI.60",
589 "MADI.61", "MADI.62", "MADI.63", "MADI.64",
590};
591
592
593static char *texts_ports_raydat_ss[] = {
594 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT1.5", "ADAT1.6",
595 "ADAT1.7", "ADAT1.8", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
596 "ADAT2.5", "ADAT2.6", "ADAT2.7", "ADAT2.8", "ADAT3.1", "ADAT3.2",
597 "ADAT3.3", "ADAT3.4", "ADAT3.5", "ADAT3.6", "ADAT3.7", "ADAT3.8",
598 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4", "ADAT4.5", "ADAT4.6",
599 "ADAT4.7", "ADAT4.8",
600 "AES.L", "AES.R",
601 "SPDIF.L", "SPDIF.R"
602};
603
604static char *texts_ports_raydat_ds[] = {
605 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4",
606 "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
607 "ADAT3.1", "ADAT3.2", "ADAT3.3", "ADAT3.4",
608 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4",
609 "AES.L", "AES.R",
610 "SPDIF.L", "SPDIF.R"
611};
612
613static char *texts_ports_raydat_qs[] = {
614 "ADAT1.1", "ADAT1.2",
615 "ADAT2.1", "ADAT2.2",
616 "ADAT3.1", "ADAT3.2",
617 "ADAT4.1", "ADAT4.2",
618 "AES.L", "AES.R",
619 "SPDIF.L", "SPDIF.R"
620};
621
622
623static char *texts_ports_aio_in_ss[] = {
624 "Analogue.L", "Analogue.R",
625 "AES.L", "AES.R",
626 "SPDIF.L", "SPDIF.R",
627 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
628 "ADAT.7", "ADAT.8"
629};
630
631static char *texts_ports_aio_out_ss[] = {
632 "Analogue.L", "Analogue.R",
633 "AES.L", "AES.R",
634 "SPDIF.L", "SPDIF.R",
635 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
636 "ADAT.7", "ADAT.8",
637 "Phone.L", "Phone.R"
638};
639
640static char *texts_ports_aio_in_ds[] = {
641 "Analogue.L", "Analogue.R",
642 "AES.L", "AES.R",
643 "SPDIF.L", "SPDIF.R",
644 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
645};
646
647static char *texts_ports_aio_out_ds[] = {
648 "Analogue.L", "Analogue.R",
649 "AES.L", "AES.R",
650 "SPDIF.L", "SPDIF.R",
651 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
652 "Phone.L", "Phone.R"
653};
654
655static char *texts_ports_aio_in_qs[] = {
656 "Analogue.L", "Analogue.R",
657 "AES.L", "AES.R",
658 "SPDIF.L", "SPDIF.R",
659 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
660};
661
662static char *texts_ports_aio_out_qs[] = {
663 "Analogue.L", "Analogue.R",
664 "AES.L", "AES.R",
665 "SPDIF.L", "SPDIF.R",
666 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
667 "Phone.L", "Phone.R"
668};
669
Adrian Knoth55a57602011-01-27 11:23:15 +0100670/* These tables map the ALSA channels 1..N to the channels that we
671 need to use in order to find the relevant channel buffer. RME
672 refers to this kind of mapping as between "the ADAT channel and
673 the DMA channel." We index it using the logical audio channel,
674 and the value is the DMA channel (i.e. channel buffer number)
675 where the data for that channel can be read/written from/to.
676*/
677
678static char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = {
679 0, 1, 2, 3, 4, 5, 6, 7,
680 8, 9, 10, 11, 12, 13, 14, 15,
681 16, 17, 18, 19, 20, 21, 22, 23,
682 24, 25, 26, 27, 28, 29, 30, 31,
683 32, 33, 34, 35, 36, 37, 38, 39,
684 40, 41, 42, 43, 44, 45, 46, 47,
685 48, 49, 50, 51, 52, 53, 54, 55,
686 56, 57, 58, 59, 60, 61, 62, 63
687};
688
Adrian Knoth55a57602011-01-27 11:23:15 +0100689static char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = {
690 4, 5, 6, 7, 8, 9, 10, 11, /* ADAT 1 */
691 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT 2 */
692 20, 21, 22, 23, 24, 25, 26, 27, /* ADAT 3 */
693 28, 29, 30, 31, 32, 33, 34, 35, /* ADAT 4 */
694 0, 1, /* AES */
695 2, 3, /* SPDIF */
696 -1, -1, -1, -1,
697 -1, -1, -1, -1, -1, -1, -1, -1,
698 -1, -1, -1, -1, -1, -1, -1, -1,
699 -1, -1, -1, -1, -1, -1, -1, -1,
700};
701
702static char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = {
703 4, 5, 6, 7, /* ADAT 1 */
704 8, 9, 10, 11, /* ADAT 2 */
705 12, 13, 14, 15, /* ADAT 3 */
706 16, 17, 18, 19, /* ADAT 4 */
707 0, 1, /* AES */
708 2, 3, /* SPDIF */
709 -1, -1, -1, -1,
710 -1, -1, -1, -1, -1, -1, -1, -1,
711 -1, -1, -1, -1, -1, -1, -1, -1,
712 -1, -1, -1, -1, -1, -1, -1, -1,
713 -1, -1, -1, -1, -1, -1, -1, -1,
714 -1, -1, -1, -1, -1, -1, -1, -1,
715};
716
717static char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = {
718 4, 5, /* ADAT 1 */
719 6, 7, /* ADAT 2 */
720 8, 9, /* ADAT 3 */
721 10, 11, /* ADAT 4 */
722 0, 1, /* AES */
723 2, 3, /* SPDIF */
724 -1, -1, -1, -1,
725 -1, -1, -1, -1, -1, -1, -1, -1,
726 -1, -1, -1, -1, -1, -1, -1, -1,
727 -1, -1, -1, -1, -1, -1, -1, -1,
728 -1, -1, -1, -1, -1, -1, -1, -1,
729 -1, -1, -1, -1, -1, -1, -1, -1,
730 -1, -1, -1, -1, -1, -1, -1, -1,
731};
732
733static char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = {
734 0, 1, /* line in */
735 8, 9, /* aes in, */
736 10, 11, /* spdif in */
737 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT in */
738 -1, -1,
739 -1, -1, -1, -1, -1, -1, -1, -1,
740 -1, -1, -1, -1, -1, -1, -1, -1,
741 -1, -1, -1, -1, -1, -1, -1, -1,
742 -1, -1, -1, -1, -1, -1, -1, -1,
743 -1, -1, -1, -1, -1, -1, -1, -1,
744 -1, -1, -1, -1, -1, -1, -1, -1,
745};
746
747static char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = {
748 0, 1, /* line out */
749 8, 9, /* aes out */
750 10, 11, /* spdif out */
751 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT out */
752 6, 7, /* phone out */
753 -1, -1, -1, -1, -1, -1, -1, -1,
754 -1, -1, -1, -1, -1, -1, -1, -1,
755 -1, -1, -1, -1, -1, -1, -1, -1,
756 -1, -1, -1, -1, -1, -1, -1, -1,
757 -1, -1, -1, -1, -1, -1, -1, -1,
758 -1, -1, -1, -1, -1, -1, -1, -1,
759};
760
761static char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = {
762 0, 1, /* line in */
763 8, 9, /* aes in */
764 10, 11, /* spdif in */
765 12, 14, 16, 18, /* adat in */
766 -1, -1, -1, -1, -1, -1,
767 -1, -1, -1, -1, -1, -1, -1, -1,
768 -1, -1, -1, -1, -1, -1, -1, -1,
769 -1, -1, -1, -1, -1, -1, -1, -1,
770 -1, -1, -1, -1, -1, -1, -1, -1,
771 -1, -1, -1, -1, -1, -1, -1, -1,
772 -1, -1, -1, -1, -1, -1, -1, -1
773};
774
775static char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = {
776 0, 1, /* line out */
777 8, 9, /* aes out */
778 10, 11, /* spdif out */
779 12, 14, 16, 18, /* adat out */
780 6, 7, /* phone out */
781 -1, -1, -1, -1,
782 -1, -1, -1, -1, -1, -1, -1, -1,
783 -1, -1, -1, -1, -1, -1, -1, -1,
784 -1, -1, -1, -1, -1, -1, -1, -1,
785 -1, -1, -1, -1, -1, -1, -1, -1,
786 -1, -1, -1, -1, -1, -1, -1, -1,
787 -1, -1, -1, -1, -1, -1, -1, -1
788};
789
790static char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = {
791 0, 1, /* line in */
792 8, 9, /* aes in */
793 10, 11, /* spdif in */
794 12, 16, /* adat in */
795 -1, -1, -1, -1, -1, -1, -1, -1,
796 -1, -1, -1, -1, -1, -1, -1, -1,
797 -1, -1, -1, -1, -1, -1, -1, -1,
798 -1, -1, -1, -1, -1, -1, -1, -1,
799 -1, -1, -1, -1, -1, -1, -1, -1,
800 -1, -1, -1, -1, -1, -1, -1, -1,
801 -1, -1, -1, -1, -1, -1, -1, -1
802};
803
804static char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = {
805 0, 1, /* line out */
806 8, 9, /* aes out */
807 10, 11, /* spdif out */
808 12, 16, /* adat out */
809 6, 7, /* phone out */
810 -1, -1, -1, -1, -1, -1,
811 -1, -1, -1, -1, -1, -1, -1, -1,
812 -1, -1, -1, -1, -1, -1, -1, -1,
813 -1, -1, -1, -1, -1, -1, -1, -1,
814 -1, -1, -1, -1, -1, -1, -1, -1,
815 -1, -1, -1, -1, -1, -1, -1, -1,
816 -1, -1, -1, -1, -1, -1, -1, -1
817};
818
Takashi Iwai98274f02005-11-17 14:52:34 +0100819struct hdspm_midi {
820 struct hdspm *hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +0200821 int id;
Takashi Iwai98274f02005-11-17 14:52:34 +0100822 struct snd_rawmidi *rmidi;
823 struct snd_rawmidi_substream *input;
824 struct snd_rawmidi_substream *output;
Takashi Iwai763f3562005-06-03 11:25:34 +0200825 char istimer; /* timer in use */
826 struct timer_list timer;
827 spinlock_t lock;
828 int pending;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100829 int dataIn;
830 int statusIn;
831 int dataOut;
832 int statusOut;
833 int ie;
834 int irq;
835};
836
837struct hdspm_tco {
838 int input;
839 int framerate;
840 int wordclock;
841 int samplerate;
842 int pull;
843 int term; /* 0 = off, 1 = on */
Takashi Iwai763f3562005-06-03 11:25:34 +0200844};
845
Takashi Iwai98274f02005-11-17 14:52:34 +0100846struct hdspm {
Takashi Iwai763f3562005-06-03 11:25:34 +0200847 spinlock_t lock;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200848 /* only one playback and/or capture stream */
849 struct snd_pcm_substream *capture_substream;
850 struct snd_pcm_substream *playback_substream;
Takashi Iwai763f3562005-06-03 11:25:34 +0200851
852 char *card_name; /* for procinfo */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200853 unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
854
Adrian Knoth0dca1792011-01-26 19:32:14 +0100855 uint8_t io_type;
Takashi Iwai763f3562005-06-03 11:25:34 +0200856
Takashi Iwai763f3562005-06-03 11:25:34 +0200857 int monitor_outs; /* set up monitoring outs init flag */
858
859 u32 control_register; /* cached value */
860 u32 control2_register; /* cached value */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100861 u32 settings_register;
Takashi Iwai763f3562005-06-03 11:25:34 +0200862
Adrian Knoth0dca1792011-01-26 19:32:14 +0100863 struct hdspm_midi midi[4];
Takashi Iwai763f3562005-06-03 11:25:34 +0200864 struct tasklet_struct midi_tasklet;
865
866 size_t period_bytes;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100867 unsigned char ss_in_channels;
868 unsigned char ds_in_channels;
869 unsigned char qs_in_channels;
870 unsigned char ss_out_channels;
871 unsigned char ds_out_channels;
872 unsigned char qs_out_channels;
873
874 unsigned char max_channels_in;
875 unsigned char max_channels_out;
876
877 char *channel_map_in;
878 char *channel_map_out;
879
880 char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs;
881 char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs;
882
883 char **port_names_in;
884 char **port_names_out;
885
886 char **port_names_in_ss, **port_names_in_ds, **port_names_in_qs;
887 char **port_names_out_ss, **port_names_out_ds, **port_names_out_qs;
Takashi Iwai763f3562005-06-03 11:25:34 +0200888
889 unsigned char *playback_buffer; /* suitably aligned address */
890 unsigned char *capture_buffer; /* suitably aligned address */
891
892 pid_t capture_pid; /* process id which uses capture */
893 pid_t playback_pid; /* process id which uses capture */
894 int running; /* running status */
895
896 int last_external_sample_rate; /* samplerate mystic ... */
897 int last_internal_sample_rate;
898 int system_sample_rate;
899
Takashi Iwai763f3562005-06-03 11:25:34 +0200900 int dev; /* Hardware vars... */
901 int irq;
902 unsigned long port;
903 void __iomem *iobase;
904
905 int irq_count; /* for debug */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100906 int midiPorts;
Takashi Iwai763f3562005-06-03 11:25:34 +0200907
Takashi Iwai98274f02005-11-17 14:52:34 +0100908 struct snd_card *card; /* one card */
909 struct snd_pcm *pcm; /* has one pcm */
910 struct snd_hwdep *hwdep; /* and a hwdep for additional ioctl */
Takashi Iwai763f3562005-06-03 11:25:34 +0200911 struct pci_dev *pci; /* and an pci info */
912
913 /* Mixer vars */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200914 /* fast alsa mixer */
915 struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS];
916 /* but input to much, so not used */
917 struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS];
Adrian Knoth0dca1792011-01-26 19:32:14 +0100918 /* full mixer accessable over mixer ioctl or hwdep-device */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200919 struct hdspm_mixer *mixer;
Takashi Iwai763f3562005-06-03 11:25:34 +0200920
Adrian Knoth0dca1792011-01-26 19:32:14 +0100921 struct hdspm_tco *tco; /* NULL if no TCO detected */
Takashi Iwai763f3562005-06-03 11:25:34 +0200922
Adrian Knoth0dca1792011-01-26 19:32:14 +0100923 char **texts_autosync;
924 int texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +0200925
Adrian Knoth0dca1792011-01-26 19:32:14 +0100926 cycles_t last_interrupt;
Jaroslav Kysela730a5862011-01-27 13:03:15 +0100927
928 struct hdspm_peak_rms peak_rms;
Takashi Iwai763f3562005-06-03 11:25:34 +0200929};
930
Takashi Iwai763f3562005-06-03 11:25:34 +0200931
Alexey Dobriyancebe41d2010-02-06 00:21:03 +0200932static DEFINE_PCI_DEVICE_TABLE(snd_hdspm_ids) = {
Takashi Iwai763f3562005-06-03 11:25:34 +0200933 {
934 .vendor = PCI_VENDOR_ID_XILINX,
935 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
936 .subvendor = PCI_ANY_ID,
937 .subdevice = PCI_ANY_ID,
938 .class = 0,
939 .class_mask = 0,
940 .driver_data = 0},
941 {0,}
942};
943
944MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
945
946/* prototypes */
Takashi Iwai98274f02005-11-17 14:52:34 +0100947static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
948 struct hdspm * hdspm);
949static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
950 struct hdspm * hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +0200951
Adrian Knoth0dca1792011-01-26 19:32:14 +0100952static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
953static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
954static int hdspm_autosync_ref(struct hdspm *hdspm);
955static int snd_hdspm_set_defaults(struct hdspm *hdspm);
956static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +0200957 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +0200958 unsigned int reg, int channels);
959
Remy Bruno3cee5a62006-10-16 12:46:32 +0200960static inline int HDSPM_bit2freq(int n)
961{
Denys Vlasenko62cef822008-04-14 13:04:18 +0200962 static const int bit2freq_tab[] = {
963 0, 32000, 44100, 48000, 64000, 88200,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200964 96000, 128000, 176400, 192000 };
965 if (n < 1 || n > 9)
966 return 0;
967 return bit2freq_tab[n];
968}
969
Adrian Knoth0dca1792011-01-26 19:32:14 +0100970/* Write/read to/from HDSPM with Adresses in Bytes
Takashi Iwai763f3562005-06-03 11:25:34 +0200971 not words but only 32Bit writes are allowed */
972
Takashi Iwai98274f02005-11-17 14:52:34 +0100973static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
Takashi Iwai763f3562005-06-03 11:25:34 +0200974 unsigned int val)
975{
976 writel(val, hdspm->iobase + reg);
977}
978
Takashi Iwai98274f02005-11-17 14:52:34 +0100979static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
Takashi Iwai763f3562005-06-03 11:25:34 +0200980{
981 return readl(hdspm->iobase + reg);
982}
983
Adrian Knoth0dca1792011-01-26 19:32:14 +0100984/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
985 mixer is write only on hardware so we have to cache him for read
Takashi Iwai763f3562005-06-03 11:25:34 +0200986 each fader is a u32, but uses only the first 16 bit */
987
Takashi Iwai98274f02005-11-17 14:52:34 +0100988static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200989 unsigned int in)
990{
Adrian Bunk5bab24822006-03-13 14:15:04 +0100991 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +0200992 return 0;
993
994 return hdspm->mixer->ch[chan].in[in];
995}
996
Takashi Iwai98274f02005-11-17 14:52:34 +0100997static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200998 unsigned int pb)
999{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001000 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001001 return 0;
1002 return hdspm->mixer->ch[chan].pb[pb];
1003}
1004
Denys Vlasenko62cef822008-04-14 13:04:18 +02001005static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001006 unsigned int in, unsigned short data)
1007{
1008 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
1009 return -1;
1010
1011 hdspm_write(hdspm,
1012 HDSPM_MADI_mixerBase +
1013 ((in + 128 * chan) * sizeof(u32)),
1014 (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
1015 return 0;
1016}
1017
Denys Vlasenko62cef822008-04-14 13:04:18 +02001018static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001019 unsigned int pb, unsigned short data)
1020{
1021 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
1022 return -1;
1023
1024 hdspm_write(hdspm,
1025 HDSPM_MADI_mixerBase +
1026 ((64 + pb + 128 * chan) * sizeof(u32)),
1027 (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
1028 return 0;
1029}
1030
1031
1032/* enable DMA for specific channels, now available for DSP-MADI */
Takashi Iwai98274f02005-11-17 14:52:34 +01001033static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001034{
1035 hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
1036}
1037
Takashi Iwai98274f02005-11-17 14:52:34 +01001038static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001039{
1040 hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
1041}
1042
1043/* check if same process is writing and reading */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001044static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001045{
1046 unsigned long flags;
1047 int ret = 1;
1048
1049 spin_lock_irqsave(&hdspm->lock, flags);
1050 if ((hdspm->playback_pid != hdspm->capture_pid) &&
1051 (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
1052 ret = 0;
1053 }
1054 spin_unlock_irqrestore(&hdspm->lock, flags);
1055 return ret;
1056}
1057
1058/* check for external sample rate */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001059static int hdspm_external_sample_rate(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001060{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001061 unsigned int status, status2, timecode;
1062 int syncref, rate = 0, rate_bits;
Takashi Iwai763f3562005-06-03 11:25:34 +02001063
Adrian Knoth0dca1792011-01-26 19:32:14 +01001064 switch (hdspm->io_type) {
1065 case AES32:
1066 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1067 status = hdspm_read(hdspm, HDSPM_statusRegister);
1068 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
1069
1070 syncref = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001071
Remy Bruno3cee5a62006-10-16 12:46:32 +02001072 if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD &&
1073 status & HDSPM_AES32_wcLock)
Adrian Knoth0dca1792011-01-26 19:32:14 +01001074 return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF);
1075
Remy Bruno3cee5a62006-10-16 12:46:32 +02001076 if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001077 syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
1078 status2 & (HDSPM_LockAES >>
1079 (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1)))
1080 return HDSPM_bit2freq((timecode >> (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF);
Remy Bruno3cee5a62006-10-16 12:46:32 +02001081 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001082 break;
1083
1084 case MADIface:
1085 status = hdspm_read(hdspm, HDSPM_statusRegister);
1086
1087 if (!(status & HDSPM_madiLock)) {
1088 rate = 0; /* no lock */
1089 } else {
1090 switch (status & (HDSPM_status1_freqMask)) {
1091 case HDSPM_status1_F_0*1:
1092 rate = 32000; break;
1093 case HDSPM_status1_F_0*2:
1094 rate = 44100; break;
1095 case HDSPM_status1_F_0*3:
1096 rate = 48000; break;
1097 case HDSPM_status1_F_0*4:
1098 rate = 64000; break;
1099 case HDSPM_status1_F_0*5:
1100 rate = 88200; break;
1101 case HDSPM_status1_F_0*6:
1102 rate = 96000; break;
1103 case HDSPM_status1_F_0*7:
1104 rate = 128000; break;
1105 case HDSPM_status1_F_0*8:
1106 rate = 176400; break;
1107 case HDSPM_status1_F_0*9:
1108 rate = 192000; break;
1109 default:
1110 rate = 0; break;
1111 }
1112 }
1113
1114 break;
1115
1116 case MADI:
1117 case AIO:
1118 case RayDAT:
1119 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1120 status = hdspm_read(hdspm, HDSPM_statusRegister);
1121 rate = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02001122
Remy Bruno3cee5a62006-10-16 12:46:32 +02001123 /* if wordclock has synced freq and wordclock is valid */
1124 if ((status2 & HDSPM_wcLock) != 0 &&
1125 (status & HDSPM_SelSyncRef0) == 0) {
1126
1127 rate_bits = status2 & HDSPM_wcFreqMask;
1128
Adrian Knoth0dca1792011-01-26 19:32:14 +01001129
Remy Bruno3cee5a62006-10-16 12:46:32 +02001130 switch (rate_bits) {
1131 case HDSPM_wcFreq32:
1132 rate = 32000;
1133 break;
1134 case HDSPM_wcFreq44_1:
1135 rate = 44100;
1136 break;
1137 case HDSPM_wcFreq48:
1138 rate = 48000;
1139 break;
1140 case HDSPM_wcFreq64:
1141 rate = 64000;
1142 break;
1143 case HDSPM_wcFreq88_2:
1144 rate = 88200;
1145 break;
1146 case HDSPM_wcFreq96:
1147 rate = 96000;
1148 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001149 default:
1150 rate = 0;
1151 break;
1152 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001153 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001154
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001155 /* if rate detected and Syncref is Word than have it,
1156 * word has priority to MADI
1157 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001158 if (rate != 0 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001159 (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
Remy Bruno3cee5a62006-10-16 12:46:32 +02001160 return rate;
1161
Adrian Knoth0dca1792011-01-26 19:32:14 +01001162 /* maybe a madi input (which is taken if sel sync is madi) */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001163 if (status & HDSPM_madiLock) {
1164 rate_bits = status & HDSPM_madiFreqMask;
1165
1166 switch (rate_bits) {
1167 case HDSPM_madiFreq32:
1168 rate = 32000;
1169 break;
1170 case HDSPM_madiFreq44_1:
1171 rate = 44100;
1172 break;
1173 case HDSPM_madiFreq48:
1174 rate = 48000;
1175 break;
1176 case HDSPM_madiFreq64:
1177 rate = 64000;
1178 break;
1179 case HDSPM_madiFreq88_2:
1180 rate = 88200;
1181 break;
1182 case HDSPM_madiFreq96:
1183 rate = 96000;
1184 break;
1185 case HDSPM_madiFreq128:
1186 rate = 128000;
1187 break;
1188 case HDSPM_madiFreq176_4:
1189 rate = 176400;
1190 break;
1191 case HDSPM_madiFreq192:
1192 rate = 192000;
1193 break;
1194 default:
1195 rate = 0;
1196 break;
1197 }
1198 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001199 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001200 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001201
1202 return rate;
Takashi Iwai763f3562005-06-03 11:25:34 +02001203}
1204
1205/* Latency function */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001206static inline void hdspm_compute_period_size(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001207{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001208 hdspm->period_bytes = 1 << ((hdspm_decode_latency(hdspm->control_register) + 8));
Takashi Iwai763f3562005-06-03 11:25:34 +02001209}
1210
Adrian Knoth0dca1792011-01-26 19:32:14 +01001211
1212static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001213{
1214 int position;
1215
1216 position = hdspm_read(hdspm, HDSPM_statusRegister);
Takashi Iwai763f3562005-06-03 11:25:34 +02001217 position &= HDSPM_BufferPositionMask;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001218 position /= 4; /* Bytes per sample */
Takashi Iwai763f3562005-06-03 11:25:34 +02001219
1220 return position;
1221}
1222
1223
Takashi Iwai98274f02005-11-17 14:52:34 +01001224static inline void hdspm_start_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001225{
1226 s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
1227 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1228}
1229
Takashi Iwai98274f02005-11-17 14:52:34 +01001230static inline void hdspm_stop_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001231{
1232 s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
1233 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1234}
1235
1236/* should I silence all or only opened ones ? doit all for first even is 4MB*/
Denys Vlasenko62cef822008-04-14 13:04:18 +02001237static void hdspm_silence_playback(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001238{
1239 int i;
1240 int n = hdspm->period_bytes;
1241 void *buf = hdspm->playback_buffer;
1242
Remy Bruno3cee5a62006-10-16 12:46:32 +02001243 if (buf == NULL)
1244 return;
Takashi Iwai763f3562005-06-03 11:25:34 +02001245
1246 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
1247 memset(buf, 0, n);
1248 buf += HDSPM_CHANNEL_BUFFER_BYTES;
1249 }
1250}
1251
Adrian Knoth0dca1792011-01-26 19:32:14 +01001252static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames)
Takashi Iwai763f3562005-06-03 11:25:34 +02001253{
1254 int n;
1255
1256 spin_lock_irq(&s->lock);
1257
1258 frames >>= 7;
1259 n = 0;
1260 while (frames) {
1261 n++;
1262 frames >>= 1;
1263 }
1264 s->control_register &= ~HDSPM_LatencyMask;
1265 s->control_register |= hdspm_encode_latency(n);
1266
1267 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1268
1269 hdspm_compute_period_size(s);
1270
1271 spin_unlock_irq(&s->lock);
1272
1273 return 0;
1274}
1275
Adrian Knoth0dca1792011-01-26 19:32:14 +01001276static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period)
1277{
1278 u64 freq_const;
1279
1280 if (period == 0)
1281 return 0;
1282
1283 switch (hdspm->io_type) {
1284 case MADI:
1285 case AES32:
1286 freq_const = 110069313433624ULL;
1287 break;
1288 case RayDAT:
1289 case AIO:
1290 freq_const = 104857600000000ULL;
1291 break;
1292 case MADIface:
1293 freq_const = 131072000000000ULL;
1294 }
1295
1296 return div_u64(freq_const, period);
1297}
1298
1299
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001300static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
1301{
1302 u64 n;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001303
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001304 if (rate >= 112000)
1305 rate /= 4;
1306 else if (rate >= 56000)
1307 rate /= 2;
1308
Adrian Knoth0dca1792011-01-26 19:32:14 +01001309 switch (hdspm->io_type) {
1310 case MADIface:
1311 n = 131072000000000ULL; /* 125 MHz */
1312 break;
1313 case MADI:
1314 case AES32:
1315 n = 110069313433624ULL; /* 105 MHz */
1316 break;
1317 case RayDAT:
1318 case AIO:
1319 n = 104857600000000ULL; /* 100 MHz */
1320 break;
1321 }
1322
Takashi Iwai3f7440a2009-06-05 17:40:04 +02001323 n = div_u64(n, rate);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001324 /* n should be less than 2^32 for being written to FREQ register */
Takashi Iwaida3cec32008-08-08 17:12:14 +02001325 snd_BUG_ON(n >> 32);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001326 hdspm_write(hdspm, HDSPM_freqReg, (u32)n);
1327}
Takashi Iwai763f3562005-06-03 11:25:34 +02001328
1329/* dummy set rate lets see what happens */
Takashi Iwai98274f02005-11-17 14:52:34 +01001330static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
Takashi Iwai763f3562005-06-03 11:25:34 +02001331{
Takashi Iwai763f3562005-06-03 11:25:34 +02001332 int current_rate;
1333 int rate_bits;
1334 int not_set = 0;
Remy Bruno65345992007-08-31 12:21:08 +02001335 int current_speed, target_speed;
Takashi Iwai763f3562005-06-03 11:25:34 +02001336
1337 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
1338 it (e.g. during module initialization).
1339 */
1340
1341 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
1342
Adrian Knoth0dca1792011-01-26 19:32:14 +01001343 /* SLAVE --- */
Takashi Iwai763f3562005-06-03 11:25:34 +02001344 if (called_internally) {
1345
Adrian Knoth0dca1792011-01-26 19:32:14 +01001346 /* request from ctl or card initialization
1347 just make a warning an remember setting
1348 for future master mode switching */
1349
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001350 snd_printk(KERN_WARNING "HDSPM: "
1351 "Warning: device is not running "
1352 "as a clock master.\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001353 not_set = 1;
1354 } else {
1355
1356 /* hw_param request while in AutoSync mode */
1357 int external_freq =
1358 hdspm_external_sample_rate(hdspm);
1359
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001360 if (hdspm_autosync_ref(hdspm) ==
1361 HDSPM_AUTOSYNC_FROM_NONE) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001362
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001363 snd_printk(KERN_WARNING "HDSPM: "
1364 "Detected no Externel Sync \n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001365 not_set = 1;
1366
1367 } else if (rate != external_freq) {
1368
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001369 snd_printk(KERN_WARNING "HDSPM: "
1370 "Warning: No AutoSync source for "
1371 "requested rate\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001372 not_set = 1;
1373 }
1374 }
1375 }
1376
1377 current_rate = hdspm->system_sample_rate;
1378
1379 /* Changing between Singe, Double and Quad speed is not
1380 allowed if any substreams are open. This is because such a change
1381 causes a shift in the location of the DMA buffers and a reduction
1382 in the number of available buffers.
1383
1384 Note that a similar but essentially insoluble problem exists for
1385 externally-driven rate changes. All we can do is to flag rate
Adrian Knoth0dca1792011-01-26 19:32:14 +01001386 changes in the read/write routines.
Takashi Iwai763f3562005-06-03 11:25:34 +02001387 */
1388
Remy Bruno65345992007-08-31 12:21:08 +02001389 if (current_rate <= 48000)
1390 current_speed = HDSPM_SPEED_SINGLE;
1391 else if (current_rate <= 96000)
1392 current_speed = HDSPM_SPEED_DOUBLE;
1393 else
1394 current_speed = HDSPM_SPEED_QUAD;
1395
1396 if (rate <= 48000)
1397 target_speed = HDSPM_SPEED_SINGLE;
1398 else if (rate <= 96000)
1399 target_speed = HDSPM_SPEED_DOUBLE;
1400 else
1401 target_speed = HDSPM_SPEED_QUAD;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001402
Takashi Iwai763f3562005-06-03 11:25:34 +02001403 switch (rate) {
1404 case 32000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001405 rate_bits = HDSPM_Frequency32KHz;
1406 break;
1407 case 44100:
Takashi Iwai763f3562005-06-03 11:25:34 +02001408 rate_bits = HDSPM_Frequency44_1KHz;
1409 break;
1410 case 48000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001411 rate_bits = HDSPM_Frequency48KHz;
1412 break;
1413 case 64000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001414 rate_bits = HDSPM_Frequency64KHz;
1415 break;
1416 case 88200:
Takashi Iwai763f3562005-06-03 11:25:34 +02001417 rate_bits = HDSPM_Frequency88_2KHz;
1418 break;
1419 case 96000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001420 rate_bits = HDSPM_Frequency96KHz;
1421 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001422 case 128000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001423 rate_bits = HDSPM_Frequency128KHz;
1424 break;
1425 case 176400:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001426 rate_bits = HDSPM_Frequency176_4KHz;
1427 break;
1428 case 192000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001429 rate_bits = HDSPM_Frequency192KHz;
1430 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001431 default:
1432 return -EINVAL;
1433 }
1434
Remy Bruno65345992007-08-31 12:21:08 +02001435 if (current_speed != target_speed
Takashi Iwai763f3562005-06-03 11:25:34 +02001436 && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
1437 snd_printk
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001438 (KERN_ERR "HDSPM: "
Remy Bruno65345992007-08-31 12:21:08 +02001439 "cannot change from %s speed to %s speed mode "
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001440 "(capture PID = %d, playback PID = %d)\n",
Remy Bruno65345992007-08-31 12:21:08 +02001441 hdspm_speed_names[current_speed],
1442 hdspm_speed_names[target_speed],
Takashi Iwai763f3562005-06-03 11:25:34 +02001443 hdspm->capture_pid, hdspm->playback_pid);
1444 return -EBUSY;
1445 }
1446
1447 hdspm->control_register &= ~HDSPM_FrequencyMask;
1448 hdspm->control_register |= rate_bits;
1449 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1450
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001451 /* For AES32, need to set DDS value in FREQ register
1452 For MADI, also apparently */
1453 hdspm_set_dds_value(hdspm, rate);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001454
1455 if (AES32 == hdspm->io_type && rate != current_rate)
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001456 hdspm_write(hdspm, HDSPM_eeprom_wr, 0);
Takashi Iwai763f3562005-06-03 11:25:34 +02001457
1458 hdspm->system_sample_rate = rate;
1459
Adrian Knoth0dca1792011-01-26 19:32:14 +01001460 if (rate <= 48000) {
1461 hdspm->channel_map_in = hdspm->channel_map_in_ss;
1462 hdspm->channel_map_out = hdspm->channel_map_out_ss;
1463 hdspm->max_channels_in = hdspm->ss_in_channels;
1464 hdspm->max_channels_out = hdspm->ss_out_channels;
1465 hdspm->port_names_in = hdspm->port_names_in_ss;
1466 hdspm->port_names_out = hdspm->port_names_out_ss;
1467 } else if (rate <= 96000) {
1468 hdspm->channel_map_in = hdspm->channel_map_in_ds;
1469 hdspm->channel_map_out = hdspm->channel_map_out_ds;
1470 hdspm->max_channels_in = hdspm->ds_in_channels;
1471 hdspm->max_channels_out = hdspm->ds_out_channels;
1472 hdspm->port_names_in = hdspm->port_names_in_ds;
1473 hdspm->port_names_out = hdspm->port_names_out_ds;
1474 } else {
1475 hdspm->channel_map_in = hdspm->channel_map_in_qs;
1476 hdspm->channel_map_out = hdspm->channel_map_out_qs;
1477 hdspm->max_channels_in = hdspm->qs_in_channels;
1478 hdspm->max_channels_out = hdspm->qs_out_channels;
1479 hdspm->port_names_in = hdspm->port_names_in_qs;
1480 hdspm->port_names_out = hdspm->port_names_out_qs;
1481 }
1482
Takashi Iwai763f3562005-06-03 11:25:34 +02001483 if (not_set != 0)
1484 return -1;
1485
1486 return 0;
1487}
1488
1489/* mainly for init to 0 on load */
Takashi Iwai98274f02005-11-17 14:52:34 +01001490static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
Takashi Iwai763f3562005-06-03 11:25:34 +02001491{
1492 int i, j;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001493 unsigned int gain;
1494
1495 if (sgain > UNITY_GAIN)
1496 gain = UNITY_GAIN;
1497 else if (sgain < 0)
1498 gain = 0;
1499 else
1500 gain = sgain;
Takashi Iwai763f3562005-06-03 11:25:34 +02001501
1502 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
1503 for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
1504 hdspm_write_in_gain(hdspm, i, j, gain);
1505 hdspm_write_pb_gain(hdspm, i, j, gain);
1506 }
1507}
1508
1509/*----------------------------------------------------------------------------
1510 MIDI
1511 ----------------------------------------------------------------------------*/
1512
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001513static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm,
1514 int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001515{
1516 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001517 return hdspm_read(hdspm, hdspm->midi[id].dataIn);
Takashi Iwai763f3562005-06-03 11:25:34 +02001518}
1519
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001520static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
1521 int val)
Takashi Iwai763f3562005-06-03 11:25:34 +02001522{
1523 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001524 return hdspm_write(hdspm, hdspm->midi[id].dataOut, val);
Takashi Iwai763f3562005-06-03 11:25:34 +02001525}
1526
Takashi Iwai98274f02005-11-17 14:52:34 +01001527static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001528{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001529 return hdspm_read(hdspm, hdspm->midi[id].statusIn) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001530}
1531
Takashi Iwai98274f02005-11-17 14:52:34 +01001532static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001533{
1534 int fifo_bytes_used;
1535
Adrian Knoth0dca1792011-01-26 19:32:14 +01001536 fifo_bytes_used = hdspm_read(hdspm, hdspm->midi[id].statusOut) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001537
1538 if (fifo_bytes_used < 128)
1539 return 128 - fifo_bytes_used;
1540 else
1541 return 0;
1542}
1543
Denys Vlasenko62cef822008-04-14 13:04:18 +02001544static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001545{
1546 while (snd_hdspm_midi_input_available (hdspm, id))
1547 snd_hdspm_midi_read_byte (hdspm, id);
1548}
1549
Takashi Iwai98274f02005-11-17 14:52:34 +01001550static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001551{
1552 unsigned long flags;
1553 int n_pending;
1554 int to_write;
1555 int i;
1556 unsigned char buf[128];
1557
1558 /* Output is not interrupt driven */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001559
Takashi Iwai763f3562005-06-03 11:25:34 +02001560 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001561 if (hmidi->output &&
1562 !snd_rawmidi_transmit_empty (hmidi->output)) {
1563 n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm,
1564 hmidi->id);
1565 if (n_pending > 0) {
1566 if (n_pending > (int)sizeof (buf))
1567 n_pending = sizeof (buf);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001568
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001569 to_write = snd_rawmidi_transmit (hmidi->output, buf,
1570 n_pending);
1571 if (to_write > 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001572 for (i = 0; i < to_write; ++i)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001573 snd_hdspm_midi_write_byte (hmidi->hdspm,
1574 hmidi->id,
1575 buf[i]);
Takashi Iwai763f3562005-06-03 11:25:34 +02001576 }
1577 }
1578 }
1579 spin_unlock_irqrestore (&hmidi->lock, flags);
1580 return 0;
1581}
1582
Takashi Iwai98274f02005-11-17 14:52:34 +01001583static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001584{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001585 unsigned char buf[128]; /* this buffer is designed to match the MIDI
1586 * input FIFO size
1587 */
Takashi Iwai763f3562005-06-03 11:25:34 +02001588 unsigned long flags;
1589 int n_pending;
1590 int i;
1591
1592 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001593 n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id);
1594 if (n_pending > 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001595 if (hmidi->input) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001596 if (n_pending > (int)sizeof (buf))
Takashi Iwai763f3562005-06-03 11:25:34 +02001597 n_pending = sizeof (buf);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001598 for (i = 0; i < n_pending; ++i)
1599 buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm,
1600 hmidi->id);
1601 if (n_pending)
1602 snd_rawmidi_receive (hmidi->input, buf,
1603 n_pending);
Takashi Iwai763f3562005-06-03 11:25:34 +02001604 } else {
1605 /* flush the MIDI input FIFO */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001606 while (n_pending--)
1607 snd_hdspm_midi_read_byte (hmidi->hdspm,
1608 hmidi->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02001609 }
1610 }
1611 hmidi->pending = 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001612
1613 hmidi->hdspm->control_register |= hmidi->ie;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001614 hdspm_write(hmidi->hdspm, HDSPM_controlRegister,
1615 hmidi->hdspm->control_register);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001616
Takashi Iwai763f3562005-06-03 11:25:34 +02001617 spin_unlock_irqrestore (&hmidi->lock, flags);
1618 return snd_hdspm_midi_output_write (hmidi);
1619}
1620
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001621static void
1622snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001623{
Takashi Iwai98274f02005-11-17 14:52:34 +01001624 struct hdspm *hdspm;
1625 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001626 unsigned long flags;
Takashi Iwai763f3562005-06-03 11:25:34 +02001627
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001628 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001629 hdspm = hmidi->hdspm;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001630
Takashi Iwai763f3562005-06-03 11:25:34 +02001631 spin_lock_irqsave (&hdspm->lock, flags);
1632 if (up) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001633 if (!(hdspm->control_register & hmidi->ie)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001634 snd_hdspm_flush_midi_input (hdspm, hmidi->id);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001635 hdspm->control_register |= hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001636 }
1637 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001638 hdspm->control_register &= ~hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001639 }
1640
1641 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1642 spin_unlock_irqrestore (&hdspm->lock, flags);
1643}
1644
1645static void snd_hdspm_midi_output_timer(unsigned long data)
1646{
Takashi Iwai98274f02005-11-17 14:52:34 +01001647 struct hdspm_midi *hmidi = (struct hdspm_midi *) data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001648 unsigned long flags;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001649
Takashi Iwai763f3562005-06-03 11:25:34 +02001650 snd_hdspm_midi_output_write(hmidi);
1651 spin_lock_irqsave (&hmidi->lock, flags);
1652
1653 /* this does not bump hmidi->istimer, because the
1654 kernel automatically removed the timer when it
1655 expired, and we are now adding it back, thus
Adrian Knoth0dca1792011-01-26 19:32:14 +01001656 leaving istimer wherever it was set before.
Takashi Iwai763f3562005-06-03 11:25:34 +02001657 */
1658
1659 if (hmidi->istimer) {
1660 hmidi->timer.expires = 1 + jiffies;
1661 add_timer(&hmidi->timer);
1662 }
1663
1664 spin_unlock_irqrestore (&hmidi->lock, flags);
1665}
1666
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001667static void
1668snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001669{
Takashi Iwai98274f02005-11-17 14:52:34 +01001670 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001671 unsigned long flags;
1672
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001673 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001674 spin_lock_irqsave (&hmidi->lock, flags);
1675 if (up) {
1676 if (!hmidi->istimer) {
1677 init_timer(&hmidi->timer);
1678 hmidi->timer.function = snd_hdspm_midi_output_timer;
1679 hmidi->timer.data = (unsigned long) hmidi;
1680 hmidi->timer.expires = 1 + jiffies;
1681 add_timer(&hmidi->timer);
1682 hmidi->istimer++;
1683 }
1684 } else {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001685 if (hmidi->istimer && --hmidi->istimer <= 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02001686 del_timer (&hmidi->timer);
Takashi Iwai763f3562005-06-03 11:25:34 +02001687 }
1688 spin_unlock_irqrestore (&hmidi->lock, flags);
1689 if (up)
1690 snd_hdspm_midi_output_write(hmidi);
1691}
1692
Takashi Iwai98274f02005-11-17 14:52:34 +01001693static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001694{
Takashi Iwai98274f02005-11-17 14:52:34 +01001695 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001696
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001697 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001698 spin_lock_irq (&hmidi->lock);
1699 snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
1700 hmidi->input = substream;
1701 spin_unlock_irq (&hmidi->lock);
1702
1703 return 0;
1704}
1705
Takashi Iwai98274f02005-11-17 14:52:34 +01001706static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001707{
Takashi Iwai98274f02005-11-17 14:52:34 +01001708 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001709
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001710 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001711 spin_lock_irq (&hmidi->lock);
1712 hmidi->output = substream;
1713 spin_unlock_irq (&hmidi->lock);
1714
1715 return 0;
1716}
1717
Takashi Iwai98274f02005-11-17 14:52:34 +01001718static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001719{
Takashi Iwai98274f02005-11-17 14:52:34 +01001720 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001721
1722 snd_hdspm_midi_input_trigger (substream, 0);
1723
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001724 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001725 spin_lock_irq (&hmidi->lock);
1726 hmidi->input = NULL;
1727 spin_unlock_irq (&hmidi->lock);
1728
1729 return 0;
1730}
1731
Takashi Iwai98274f02005-11-17 14:52:34 +01001732static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001733{
Takashi Iwai98274f02005-11-17 14:52:34 +01001734 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001735
1736 snd_hdspm_midi_output_trigger (substream, 0);
1737
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001738 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001739 spin_lock_irq (&hmidi->lock);
1740 hmidi->output = NULL;
1741 spin_unlock_irq (&hmidi->lock);
1742
1743 return 0;
1744}
1745
Takashi Iwai98274f02005-11-17 14:52:34 +01001746static struct snd_rawmidi_ops snd_hdspm_midi_output =
Takashi Iwai763f3562005-06-03 11:25:34 +02001747{
1748 .open = snd_hdspm_midi_output_open,
1749 .close = snd_hdspm_midi_output_close,
1750 .trigger = snd_hdspm_midi_output_trigger,
1751};
1752
Takashi Iwai98274f02005-11-17 14:52:34 +01001753static struct snd_rawmidi_ops snd_hdspm_midi_input =
Takashi Iwai763f3562005-06-03 11:25:34 +02001754{
1755 .open = snd_hdspm_midi_input_open,
1756 .close = snd_hdspm_midi_input_close,
1757 .trigger = snd_hdspm_midi_input_trigger,
1758};
1759
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001760static int __devinit snd_hdspm_create_midi (struct snd_card *card,
1761 struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001762{
1763 int err;
1764 char buf[32];
1765
1766 hdspm->midi[id].id = id;
Takashi Iwai763f3562005-06-03 11:25:34 +02001767 hdspm->midi[id].hdspm = hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +02001768 spin_lock_init (&hdspm->midi[id].lock);
1769
Adrian Knoth0dca1792011-01-26 19:32:14 +01001770 if (0 == id) {
1771 if (MADIface == hdspm->io_type) {
1772 /* MIDI-over-MADI on HDSPe MADIface */
1773 hdspm->midi[0].dataIn = HDSPM_midiDataIn2;
1774 hdspm->midi[0].statusIn = HDSPM_midiStatusIn2;
1775 hdspm->midi[0].dataOut = HDSPM_midiDataOut2;
1776 hdspm->midi[0].statusOut = HDSPM_midiStatusOut2;
1777 hdspm->midi[0].ie = HDSPM_Midi2InterruptEnable;
1778 hdspm->midi[0].irq = HDSPM_midi2IRQPending;
1779 } else {
1780 hdspm->midi[0].dataIn = HDSPM_midiDataIn0;
1781 hdspm->midi[0].statusIn = HDSPM_midiStatusIn0;
1782 hdspm->midi[0].dataOut = HDSPM_midiDataOut0;
1783 hdspm->midi[0].statusOut = HDSPM_midiStatusOut0;
1784 hdspm->midi[0].ie = HDSPM_Midi0InterruptEnable;
1785 hdspm->midi[0].irq = HDSPM_midi0IRQPending;
1786 }
1787 } else if (1 == id) {
1788 hdspm->midi[1].dataIn = HDSPM_midiDataIn1;
1789 hdspm->midi[1].statusIn = HDSPM_midiStatusIn1;
1790 hdspm->midi[1].dataOut = HDSPM_midiDataOut1;
1791 hdspm->midi[1].statusOut = HDSPM_midiStatusOut1;
1792 hdspm->midi[1].ie = HDSPM_Midi1InterruptEnable;
1793 hdspm->midi[1].irq = HDSPM_midi1IRQPending;
1794 } else if ((2 == id) && (MADI == hdspm->io_type)) {
1795 /* MIDI-over-MADI on HDSPe MADI */
1796 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1797 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1798 hdspm->midi[2].dataOut = HDSPM_midiDataOut2;
1799 hdspm->midi[2].statusOut = HDSPM_midiStatusOut2;
1800 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1801 hdspm->midi[2].irq = HDSPM_midi2IRQPending;
1802 } else if (2 == id) {
1803 /* TCO MTC, read only */
1804 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1805 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1806 hdspm->midi[2].dataOut = -1;
1807 hdspm->midi[2].statusOut = -1;
1808 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1809 hdspm->midi[2].irq = HDSPM_midi2IRQPendingAES;
1810 } else if (3 == id) {
1811 /* TCO MTC on HDSPe MADI */
1812 hdspm->midi[3].dataIn = HDSPM_midiDataIn3;
1813 hdspm->midi[3].statusIn = HDSPM_midiStatusIn3;
1814 hdspm->midi[3].dataOut = -1;
1815 hdspm->midi[3].statusOut = -1;
1816 hdspm->midi[3].ie = HDSPM_Midi3InterruptEnable;
1817 hdspm->midi[3].irq = HDSPM_midi3IRQPending;
1818 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001819
Adrian Knoth0dca1792011-01-26 19:32:14 +01001820 if ((id < 2) || ((2 == id) && ((MADI == hdspm->io_type) ||
1821 (MADIface == hdspm->io_type)))) {
1822 if ((id == 0) && (MADIface == hdspm->io_type)) {
1823 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1824 } else if ((id == 2) && (MADI == hdspm->io_type)) {
1825 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1826 } else {
1827 sprintf(buf, "%s MIDI %d", card->shortname, id+1);
1828 }
1829 err = snd_rawmidi_new(card, buf, id, 1, 1,
1830 &hdspm->midi[id].rmidi);
1831 if (err < 0)
1832 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02001833
Adrian Knoth0dca1792011-01-26 19:32:14 +01001834 sprintf(hdspm->midi[id].rmidi->name, "%s MIDI %d",
1835 card->id, id+1);
1836 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
Takashi Iwai763f3562005-06-03 11:25:34 +02001837
Adrian Knoth0dca1792011-01-26 19:32:14 +01001838 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1839 SNDRV_RAWMIDI_STREAM_OUTPUT,
1840 &snd_hdspm_midi_output);
1841 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1842 SNDRV_RAWMIDI_STREAM_INPUT,
1843 &snd_hdspm_midi_input);
1844
1845 hdspm->midi[id].rmidi->info_flags |=
1846 SNDRV_RAWMIDI_INFO_OUTPUT |
1847 SNDRV_RAWMIDI_INFO_INPUT |
1848 SNDRV_RAWMIDI_INFO_DUPLEX;
1849 } else {
1850 /* TCO MTC, read only */
1851 sprintf(buf, "%s MTC %d", card->shortname, id+1);
1852 err = snd_rawmidi_new(card, buf, id, 1, 1,
1853 &hdspm->midi[id].rmidi);
1854 if (err < 0)
1855 return err;
1856
1857 sprintf(hdspm->midi[id].rmidi->name,
1858 "%s MTC %d", card->id, id+1);
1859 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
1860
1861 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1862 SNDRV_RAWMIDI_STREAM_INPUT,
1863 &snd_hdspm_midi_input);
1864
1865 hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
1866 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001867
1868 return 0;
1869}
1870
1871
1872static void hdspm_midi_tasklet(unsigned long arg)
1873{
Takashi Iwai98274f02005-11-17 14:52:34 +01001874 struct hdspm *hdspm = (struct hdspm *)arg;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001875 int i = 0;
1876
1877 while (i < hdspm->midiPorts) {
1878 if (hdspm->midi[i].pending)
1879 snd_hdspm_midi_input_read(&hdspm->midi[i]);
1880
1881 i++;
1882 }
1883}
Takashi Iwai763f3562005-06-03 11:25:34 +02001884
1885
1886/*-----------------------------------------------------------------------------
1887 Status Interface
1888 ----------------------------------------------------------------------------*/
1889
1890/* get the system sample rate which is set */
1891
Adrian Knoth0dca1792011-01-26 19:32:14 +01001892
1893/**
1894 * Calculate the real sample rate from the
1895 * current DDS value.
1896 **/
1897static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
1898{
1899 unsigned int period, rate;
1900
1901 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
1902 rate = hdspm_calc_dds_value(hdspm, period);
1903
1904 return rate;
1905}
1906
1907
Takashi Iwai763f3562005-06-03 11:25:34 +02001908#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001909{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001910 .name = xname, \
1911 .index = xindex, \
1912 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1913 .info = snd_hdspm_info_system_sample_rate, \
1914 .get = snd_hdspm_get_system_sample_rate \
1915}
1916
Takashi Iwai98274f02005-11-17 14:52:34 +01001917static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
1918 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001919{
1920 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1921 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001922 uinfo->value.integer.min = 27000;
1923 uinfo->value.integer.max = 207000;
1924 uinfo->value.integer.step = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02001925 return 0;
1926}
1927
Adrian Knoth0dca1792011-01-26 19:32:14 +01001928
Takashi Iwai98274f02005-11-17 14:52:34 +01001929static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
1930 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02001931 ucontrol)
1932{
Takashi Iwai98274f02005-11-17 14:52:34 +01001933 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001934
Adrian Knoth0dca1792011-01-26 19:32:14 +01001935 ucontrol->value.integer.value[0] = hdspm_get_system_sample_rate(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001936 return 0;
1937}
1938
Adrian Knoth0dca1792011-01-26 19:32:14 +01001939
1940/**
1941 * Returns the WordClock sample rate class for the given card.
1942 **/
1943static int hdspm_get_wc_sample_rate(struct hdspm *hdspm)
1944{
1945 int status;
1946
1947 switch (hdspm->io_type) {
1948 case RayDAT:
1949 case AIO:
1950 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
1951 return (status >> 16) & 0xF;
1952 break;
1953 default:
1954 break;
1955 }
1956
1957
1958 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02001959}
1960
Adrian Knoth0dca1792011-01-26 19:32:14 +01001961
1962/**
1963 * Returns the TCO sample rate class for the given card.
1964 **/
1965static int hdspm_get_tco_sample_rate(struct hdspm *hdspm)
1966{
1967 int status;
1968
1969 if (hdspm->tco) {
1970 switch (hdspm->io_type) {
1971 case RayDAT:
1972 case AIO:
1973 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
1974 return (status >> 20) & 0xF;
1975 break;
1976 default:
1977 break;
1978 }
1979 }
1980
1981 return 0;
1982}
1983
1984
1985/**
1986 * Returns the SYNC_IN sample rate class for the given card.
1987 **/
1988static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm)
1989{
1990 int status;
1991
1992 if (hdspm->tco) {
1993 switch (hdspm->io_type) {
1994 case RayDAT:
1995 case AIO:
1996 status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
1997 return (status >> 12) & 0xF;
1998 break;
1999 default:
2000 break;
2001 }
2002 }
2003
2004 return 0;
2005}
2006
2007
2008/**
2009 * Returns the sample rate class for input source <idx> for
2010 * 'new style' cards like the AIO and RayDAT.
2011 **/
2012static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
2013{
2014 int status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2015
2016 return (status >> (idx*4)) & 0xF;
2017}
2018
2019
2020
2021#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
2022{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2023 .name = xname, \
2024 .private_value = xindex, \
2025 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2026 .info = snd_hdspm_info_autosync_sample_rate, \
2027 .get = snd_hdspm_get_autosync_sample_rate \
2028}
2029
2030
Takashi Iwai98274f02005-11-17 14:52:34 +01002031static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2032 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002033{
Takashi Iwai763f3562005-06-03 11:25:34 +02002034 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2035 uinfo->count = 1;
2036 uinfo->value.enumerated.items = 10;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002037
Takashi Iwai763f3562005-06-03 11:25:34 +02002038 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
Adrian Knoth0dca1792011-01-26 19:32:14 +01002039 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002040 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002041 texts_freq[uinfo->value.enumerated.item]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002042 return 0;
2043}
2044
Adrian Knoth0dca1792011-01-26 19:32:14 +01002045
Takashi Iwai98274f02005-11-17 14:52:34 +01002046static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2047 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002048 ucontrol)
2049{
Takashi Iwai98274f02005-11-17 14:52:34 +01002050 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002051
Adrian Knoth0dca1792011-01-26 19:32:14 +01002052 switch (hdspm->io_type) {
2053 case RayDAT:
2054 switch (kcontrol->private_value) {
2055 case 0:
2056 ucontrol->value.enumerated.item[0] =
2057 hdspm_get_wc_sample_rate(hdspm);
2058 break;
2059 case 7:
2060 ucontrol->value.enumerated.item[0] =
2061 hdspm_get_tco_sample_rate(hdspm);
2062 break;
2063 case 8:
2064 ucontrol->value.enumerated.item[0] =
2065 hdspm_get_sync_in_sample_rate(hdspm);
2066 break;
2067 default:
2068 ucontrol->value.enumerated.item[0] =
2069 hdspm_get_s1_sample_rate(hdspm,
2070 kcontrol->private_value-1);
2071 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002072
Adrian Knoth0dca1792011-01-26 19:32:14 +01002073 case AIO:
2074 switch (kcontrol->private_value) {
2075 case 0: /* WC */
2076 ucontrol->value.enumerated.item[0] =
2077 hdspm_get_wc_sample_rate(hdspm);
2078 break;
2079 case 4: /* TCO */
2080 ucontrol->value.enumerated.item[0] =
2081 hdspm_get_tco_sample_rate(hdspm);
2082 break;
2083 case 5: /* SYNC_IN */
2084 ucontrol->value.enumerated.item[0] =
2085 hdspm_get_sync_in_sample_rate(hdspm);
2086 break;
2087 default:
2088 ucontrol->value.enumerated.item[0] =
2089 hdspm_get_s1_sample_rate(hdspm,
2090 ucontrol->id.index-1);
2091 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002092 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002093 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002094 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002095
Takashi Iwai763f3562005-06-03 11:25:34 +02002096 return 0;
2097}
2098
Adrian Knoth0dca1792011-01-26 19:32:14 +01002099
Takashi Iwai763f3562005-06-03 11:25:34 +02002100#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002101{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2102 .name = xname, \
2103 .index = xindex, \
2104 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2105 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2106 .info = snd_hdspm_info_system_clock_mode, \
2107 .get = snd_hdspm_get_system_clock_mode, \
2108 .put = snd_hdspm_put_system_clock_mode, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002109}
2110
2111
Adrian Knoth0dca1792011-01-26 19:32:14 +01002112/**
2113 * Returns the system clock mode for the given card.
2114 * @returns 0 - master, 1 - slave
2115 **/
2116static int hdspm_system_clock_mode(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002117{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002118 switch (hdspm->io_type) {
2119 case AIO:
2120 case RayDAT:
2121 if (hdspm->settings_register & HDSPM_c0Master)
2122 return 0;
2123 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002124
Adrian Knoth0dca1792011-01-26 19:32:14 +01002125 default:
2126 if (hdspm->control_register & HDSPM_ClockModeMaster)
2127 return 0;
2128 }
2129
Takashi Iwai763f3562005-06-03 11:25:34 +02002130 return 1;
2131}
2132
Adrian Knoth0dca1792011-01-26 19:32:14 +01002133
2134/**
2135 * Sets the system clock mode.
2136 * @param mode 0 - master, 1 - slave
2137 **/
2138static void hdspm_set_system_clock_mode(struct hdspm *hdspm, int mode)
2139{
2140 switch (hdspm->io_type) {
2141 case AIO:
2142 case RayDAT:
2143 if (0 == mode)
2144 hdspm->settings_register |= HDSPM_c0Master;
2145 else
2146 hdspm->settings_register &= ~HDSPM_c0Master;
2147
2148 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2149 break;
2150
2151 default:
2152 if (0 == mode)
2153 hdspm->control_register |= HDSPM_ClockModeMaster;
2154 else
2155 hdspm->control_register &= ~HDSPM_ClockModeMaster;
2156
2157 hdspm_write(hdspm, HDSPM_controlRegister,
2158 hdspm->control_register);
2159 }
2160}
2161
2162
Takashi Iwai98274f02005-11-17 14:52:34 +01002163static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
2164 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002165{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002166 static char *texts[] = { "Master", "AutoSync" };
Takashi Iwai763f3562005-06-03 11:25:34 +02002167
2168 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2169 uinfo->count = 1;
2170 uinfo->value.enumerated.items = 2;
2171 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2172 uinfo->value.enumerated.item =
2173 uinfo->value.enumerated.items - 1;
2174 strcpy(uinfo->value.enumerated.name,
2175 texts[uinfo->value.enumerated.item]);
2176 return 0;
2177}
2178
Takashi Iwai98274f02005-11-17 14:52:34 +01002179static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
2180 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002181{
Takashi Iwai98274f02005-11-17 14:52:34 +01002182 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002183
Adrian Knoth0dca1792011-01-26 19:32:14 +01002184 ucontrol->value.enumerated.item[0] = hdspm_system_clock_mode(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002185 return 0;
2186}
2187
Adrian Knoth0dca1792011-01-26 19:32:14 +01002188static int snd_hdspm_put_system_clock_mode(struct snd_kcontrol *kcontrol,
2189 struct snd_ctl_elem_value *ucontrol)
2190{
2191 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2192 int val;
2193
2194 if (!snd_hdspm_use_is_exclusive(hdspm))
2195 return -EBUSY;
2196
2197 val = ucontrol->value.enumerated.item[0];
2198 if (val < 0)
2199 val = 0;
2200 else if (val > 1)
2201 val = 1;
2202
2203 hdspm_set_system_clock_mode(hdspm, val);
2204
2205 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002206}
2207
Adrian Knoth0dca1792011-01-26 19:32:14 +01002208
2209#define HDSPM_INTERNAL_CLOCK(xname, xindex) \
2210{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2211 .name = xname, \
2212 .index = xindex, \
2213 .info = snd_hdspm_info_clock_source, \
2214 .get = snd_hdspm_get_clock_source, \
2215 .put = snd_hdspm_put_clock_source \
2216}
2217
2218
Takashi Iwai98274f02005-11-17 14:52:34 +01002219static int hdspm_clock_source(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002220{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002221 switch (hdspm->system_sample_rate) {
2222 case 32000: return 0;
2223 case 44100: return 1;
2224 case 48000: return 2;
2225 case 64000: return 3;
2226 case 88200: return 4;
2227 case 96000: return 5;
2228 case 128000: return 6;
2229 case 176400: return 7;
2230 case 192000: return 8;
Takashi Iwai763f3562005-06-03 11:25:34 +02002231 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002232
2233 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002234}
2235
Takashi Iwai98274f02005-11-17 14:52:34 +01002236static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
Takashi Iwai763f3562005-06-03 11:25:34 +02002237{
2238 int rate;
2239 switch (mode) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002240 case 0:
2241 rate = 32000; break;
2242 case 1:
2243 rate = 44100; break;
2244 case 2:
2245 rate = 48000; break;
2246 case 3:
2247 rate = 64000; break;
2248 case 4:
2249 rate = 88200; break;
2250 case 5:
2251 rate = 96000; break;
2252 case 6:
2253 rate = 128000; break;
2254 case 7:
2255 rate = 176400; break;
2256 case 8:
2257 rate = 192000; break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002258 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002259 rate = 48000;
Takashi Iwai763f3562005-06-03 11:25:34 +02002260 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002261 hdspm_set_rate(hdspm, rate, 1);
2262 return 0;
2263}
2264
Takashi Iwai98274f02005-11-17 14:52:34 +01002265static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
2266 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002267{
Takashi Iwai763f3562005-06-03 11:25:34 +02002268 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2269 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002270 uinfo->value.enumerated.items = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002271
2272 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2273 uinfo->value.enumerated.item =
2274 uinfo->value.enumerated.items - 1;
2275
2276 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002277 texts_freq[uinfo->value.enumerated.item+1]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002278
2279 return 0;
2280}
2281
Takashi Iwai98274f02005-11-17 14:52:34 +01002282static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
2283 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002284{
Takashi Iwai98274f02005-11-17 14:52:34 +01002285 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002286
2287 ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
2288 return 0;
2289}
2290
Takashi Iwai98274f02005-11-17 14:52:34 +01002291static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
2292 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002293{
Takashi Iwai98274f02005-11-17 14:52:34 +01002294 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002295 int change;
2296 int val;
2297
2298 if (!snd_hdspm_use_is_exclusive(hdspm))
2299 return -EBUSY;
2300 val = ucontrol->value.enumerated.item[0];
2301 if (val < 0)
2302 val = 0;
Remy Bruno65345992007-08-31 12:21:08 +02002303 if (val > 9)
2304 val = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002305 spin_lock_irq(&hdspm->lock);
2306 if (val != hdspm_clock_source(hdspm))
2307 change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
2308 else
2309 change = 0;
2310 spin_unlock_irq(&hdspm->lock);
2311 return change;
2312}
2313
Adrian Knoth0dca1792011-01-26 19:32:14 +01002314
Takashi Iwai763f3562005-06-03 11:25:34 +02002315#define HDSPM_PREF_SYNC_REF(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002316{.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2317 .name = xname, \
2318 .index = xindex, \
2319 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2320 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2321 .info = snd_hdspm_info_pref_sync_ref, \
2322 .get = snd_hdspm_get_pref_sync_ref, \
2323 .put = snd_hdspm_put_pref_sync_ref \
Takashi Iwai763f3562005-06-03 11:25:34 +02002324}
2325
Adrian Knoth0dca1792011-01-26 19:32:14 +01002326
2327/**
2328 * Returns the current preferred sync reference setting.
2329 * The semantics of the return value are depending on the
2330 * card, please see the comments for clarification.
2331 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002332static int hdspm_pref_sync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002333{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002334 switch (hdspm->io_type) {
2335 case AES32:
Remy Bruno3cee5a62006-10-16 12:46:32 +02002336 switch (hdspm->control_register & HDSPM_SyncRefMask) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002337 case 0: return 0; /* WC */
2338 case HDSPM_SyncRef0: return 1; /* AES 1 */
2339 case HDSPM_SyncRef1: return 2; /* AES 2 */
2340 case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; /* AES 3 */
2341 case HDSPM_SyncRef2: return 4; /* AES 4 */
2342 case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; /* AES 5 */
2343 case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; /* AES 6 */
2344 case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0:
2345 return 7; /* AES 7 */
2346 case HDSPM_SyncRef3: return 8; /* AES 8 */
2347 case HDSPM_SyncRef3+HDSPM_SyncRef0: return 9; /* TCO */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002348 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002349 break;
2350
2351 case MADI:
2352 case MADIface:
2353 if (hdspm->tco) {
2354 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2355 case 0: return 0; /* WC */
2356 case HDSPM_SyncRef0: return 1; /* MADI */
2357 case HDSPM_SyncRef1: return 2; /* TCO */
2358 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2359 return 3; /* SYNC_IN */
2360 }
2361 } else {
2362 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2363 case 0: return 0; /* WC */
2364 case HDSPM_SyncRef0: return 1; /* MADI */
2365 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2366 return 2; /* SYNC_IN */
2367 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02002368 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002369 break;
2370
2371 case RayDAT:
2372 if (hdspm->tco) {
2373 switch ((hdspm->settings_register &
2374 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2375 case 0: return 0; /* WC */
2376 case 3: return 1; /* ADAT 1 */
2377 case 4: return 2; /* ADAT 2 */
2378 case 5: return 3; /* ADAT 3 */
2379 case 6: return 4; /* ADAT 4 */
2380 case 1: return 5; /* AES */
2381 case 2: return 6; /* SPDIF */
2382 case 9: return 7; /* TCO */
2383 case 10: return 8; /* SYNC_IN */
2384 }
2385 } else {
2386 switch ((hdspm->settings_register &
2387 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2388 case 0: return 0; /* WC */
2389 case 3: return 1; /* ADAT 1 */
2390 case 4: return 2; /* ADAT 2 */
2391 case 5: return 3; /* ADAT 3 */
2392 case 6: return 4; /* ADAT 4 */
2393 case 1: return 5; /* AES */
2394 case 2: return 6; /* SPDIF */
2395 case 10: return 7; /* SYNC_IN */
2396 }
2397 }
2398
2399 break;
2400
2401 case AIO:
2402 if (hdspm->tco) {
2403 switch ((hdspm->settings_register &
2404 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2405 case 0: return 0; /* WC */
2406 case 3: return 1; /* ADAT */
2407 case 1: return 2; /* AES */
2408 case 2: return 3; /* SPDIF */
2409 case 9: return 4; /* TCO */
2410 case 10: return 5; /* SYNC_IN */
2411 }
2412 } else {
2413 switch ((hdspm->settings_register &
2414 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2415 case 0: return 0; /* WC */
2416 case 3: return 1; /* ADAT */
2417 case 1: return 2; /* AES */
2418 case 2: return 3; /* SPDIF */
2419 case 10: return 4; /* SYNC_IN */
2420 }
2421 }
2422
2423 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002424 }
2425
Adrian Knoth0dca1792011-01-26 19:32:14 +01002426 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002427}
2428
Adrian Knoth0dca1792011-01-26 19:32:14 +01002429
2430/**
2431 * Set the preferred sync reference to <pref>. The semantics
2432 * of <pref> are depending on the card type, see the comments
2433 * for clarification.
2434 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002435static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
Takashi Iwai763f3562005-06-03 11:25:34 +02002436{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002437 int p = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002438
Adrian Knoth0dca1792011-01-26 19:32:14 +01002439 switch (hdspm->io_type) {
2440 case AES32:
2441 hdspm->control_register &= ~HDSPM_SyncRefMask;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002442 switch (pref) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002443 case 0: /* WC */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002444 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002445 case 1: /* AES 1 */
2446 hdspm->control_register |= HDSPM_SyncRef0;
2447 break;
2448 case 2: /* AES 2 */
2449 hdspm->control_register |= HDSPM_SyncRef1;
2450 break;
2451 case 3: /* AES 3 */
2452 hdspm->control_register |=
2453 HDSPM_SyncRef1+HDSPM_SyncRef0;
2454 break;
2455 case 4: /* AES 4 */
2456 hdspm->control_register |= HDSPM_SyncRef2;
2457 break;
2458 case 5: /* AES 5 */
2459 hdspm->control_register |=
2460 HDSPM_SyncRef2+HDSPM_SyncRef0;
2461 break;
2462 case 6: /* AES 6 */
2463 hdspm->control_register |=
2464 HDSPM_SyncRef2+HDSPM_SyncRef1;
2465 break;
2466 case 7: /* AES 7 */
2467 hdspm->control_register |=
2468 HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
2469 break;
2470 case 8: /* AES 8 */
2471 hdspm->control_register |= HDSPM_SyncRef3;
2472 break;
2473 case 9: /* TCO */
2474 hdspm->control_register |=
2475 HDSPM_SyncRef3+HDSPM_SyncRef0;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002476 break;
2477 default:
2478 return -1;
2479 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002480
2481 break;
2482
2483 case MADI:
2484 case MADIface:
2485 hdspm->control_register &= ~HDSPM_SyncRefMask;
2486 if (hdspm->tco) {
2487 switch (pref) {
2488 case 0: /* WC */
2489 break;
2490 case 1: /* MADI */
2491 hdspm->control_register |= HDSPM_SyncRef0;
2492 break;
2493 case 2: /* TCO */
2494 hdspm->control_register |= HDSPM_SyncRef1;
2495 break;
2496 case 3: /* SYNC_IN */
2497 hdspm->control_register |=
2498 HDSPM_SyncRef0+HDSPM_SyncRef1;
2499 break;
2500 default:
2501 return -1;
2502 }
2503 } else {
2504 switch (pref) {
2505 case 0: /* WC */
2506 break;
2507 case 1: /* MADI */
2508 hdspm->control_register |= HDSPM_SyncRef0;
2509 break;
2510 case 2: /* SYNC_IN */
2511 hdspm->control_register |=
2512 HDSPM_SyncRef0+HDSPM_SyncRef1;
2513 break;
2514 default:
2515 return -1;
2516 }
2517 }
2518
2519 break;
2520
2521 case RayDAT:
2522 if (hdspm->tco) {
2523 switch (pref) {
2524 case 0: p = 0; break; /* WC */
2525 case 1: p = 3; break; /* ADAT 1 */
2526 case 2: p = 4; break; /* ADAT 2 */
2527 case 3: p = 5; break; /* ADAT 3 */
2528 case 4: p = 6; break; /* ADAT 4 */
2529 case 5: p = 1; break; /* AES */
2530 case 6: p = 2; break; /* SPDIF */
2531 case 7: p = 9; break; /* TCO */
2532 case 8: p = 10; break; /* SYNC_IN */
2533 default: return -1;
2534 }
2535 } else {
2536 switch (pref) {
2537 case 0: p = 0; break; /* WC */
2538 case 1: p = 3; break; /* ADAT 1 */
2539 case 2: p = 4; break; /* ADAT 2 */
2540 case 3: p = 5; break; /* ADAT 3 */
2541 case 4: p = 6; break; /* ADAT 4 */
2542 case 5: p = 1; break; /* AES */
2543 case 6: p = 2; break; /* SPDIF */
2544 case 7: p = 10; break; /* SYNC_IN */
2545 default: return -1;
2546 }
2547 }
2548 break;
2549
2550 case AIO:
2551 if (hdspm->tco) {
2552 switch (pref) {
2553 case 0: p = 0; break; /* WC */
2554 case 1: p = 3; break; /* ADAT */
2555 case 2: p = 1; break; /* AES */
2556 case 3: p = 2; break; /* SPDIF */
2557 case 4: p = 9; break; /* TCO */
2558 case 5: p = 10; break; /* SYNC_IN */
2559 default: return -1;
2560 }
2561 } else {
2562 switch (pref) {
2563 case 0: p = 0; break; /* WC */
2564 case 1: p = 3; break; /* ADAT */
2565 case 2: p = 1; break; /* AES */
2566 case 3: p = 2; break; /* SPDIF */
2567 case 4: p = 10; break; /* SYNC_IN */
2568 default: return -1;
2569 }
2570 }
2571 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002572 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002573
2574 switch (hdspm->io_type) {
2575 case RayDAT:
2576 case AIO:
2577 hdspm->settings_register &= ~HDSPM_c0_SyncRefMask;
2578 hdspm->settings_register |= HDSPM_c0_SyncRef0 * p;
2579 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2580 break;
2581
2582 case MADI:
2583 case MADIface:
2584 case AES32:
2585 hdspm_write(hdspm, HDSPM_controlRegister,
2586 hdspm->control_register);
2587 }
2588
Takashi Iwai763f3562005-06-03 11:25:34 +02002589 return 0;
2590}
2591
Adrian Knoth0dca1792011-01-26 19:32:14 +01002592
Takashi Iwai98274f02005-11-17 14:52:34 +01002593static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
2594 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002595{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002596 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002597
Adrian Knoth0dca1792011-01-26 19:32:14 +01002598 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2599 uinfo->count = 1;
2600 uinfo->value.enumerated.items = hdspm->texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +02002601
Adrian Knoth0dca1792011-01-26 19:32:14 +01002602 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2603 uinfo->value.enumerated.item =
2604 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002605
Adrian Knoth0dca1792011-01-26 19:32:14 +01002606 strcpy(uinfo->value.enumerated.name,
2607 hdspm->texts_autosync[uinfo->value.enumerated.item]);
Remy Bruno3cee5a62006-10-16 12:46:32 +02002608
Takashi Iwai763f3562005-06-03 11:25:34 +02002609 return 0;
2610}
2611
Takashi Iwai98274f02005-11-17 14:52:34 +01002612static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
2613 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002614{
Takashi Iwai98274f02005-11-17 14:52:34 +01002615 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002616 int psf = hdspm_pref_sync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002617
Adrian Knoth0dca1792011-01-26 19:32:14 +01002618 if (psf >= 0) {
2619 ucontrol->value.enumerated.item[0] = psf;
2620 return 0;
2621 }
2622
2623 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002624}
2625
Takashi Iwai98274f02005-11-17 14:52:34 +01002626static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
2627 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002628{
Takashi Iwai98274f02005-11-17 14:52:34 +01002629 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002630 int val, change = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002631
2632 if (!snd_hdspm_use_is_exclusive(hdspm))
2633 return -EBUSY;
2634
Adrian Knoth0dca1792011-01-26 19:32:14 +01002635 val = ucontrol->value.enumerated.item[0];
2636
2637 if (val < 0)
2638 val = 0;
2639 else if (val >= hdspm->texts_autosync_items)
2640 val = hdspm->texts_autosync_items-1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002641
2642 spin_lock_irq(&hdspm->lock);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002643 if (val != hdspm_pref_sync_ref(hdspm))
2644 change = (0 == hdspm_set_pref_sync_ref(hdspm, val)) ? 1 : 0;
2645
Takashi Iwai763f3562005-06-03 11:25:34 +02002646 spin_unlock_irq(&hdspm->lock);
2647 return change;
2648}
2649
Adrian Knoth0dca1792011-01-26 19:32:14 +01002650
Takashi Iwai763f3562005-06-03 11:25:34 +02002651#define HDSPM_AUTOSYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002652{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002653 .name = xname, \
2654 .index = xindex, \
2655 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2656 .info = snd_hdspm_info_autosync_ref, \
2657 .get = snd_hdspm_get_autosync_ref, \
2658}
2659
Adrian Knoth0dca1792011-01-26 19:32:14 +01002660static int hdspm_autosync_ref(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002661{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002662 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002663 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002664 unsigned int syncref =
2665 (status >> HDSPM_AES32_syncref_bit) & 0xF;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002666 if (syncref == 0)
2667 return HDSPM_AES32_AUTOSYNC_FROM_WORD;
2668 if (syncref <= 8)
2669 return syncref;
2670 return HDSPM_AES32_AUTOSYNC_FROM_NONE;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002671 } else if (MADI == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002672 /* This looks at the autosync selected sync reference */
2673 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Takashi Iwai763f3562005-06-03 11:25:34 +02002674
Remy Bruno3cee5a62006-10-16 12:46:32 +02002675 switch (status2 & HDSPM_SelSyncRefMask) {
2676 case HDSPM_SelSyncRef_WORD:
2677 return HDSPM_AUTOSYNC_FROM_WORD;
2678 case HDSPM_SelSyncRef_MADI:
2679 return HDSPM_AUTOSYNC_FROM_MADI;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002680 case HDSPM_SelSyncRef_TCO:
2681 return HDSPM_AUTOSYNC_FROM_TCO;
2682 case HDSPM_SelSyncRef_SyncIn:
2683 return HDSPM_AUTOSYNC_FROM_SYNC_IN;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002684 case HDSPM_SelSyncRef_NVALID:
2685 return HDSPM_AUTOSYNC_FROM_NONE;
2686 default:
2687 return 0;
2688 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002689
Takashi Iwai763f3562005-06-03 11:25:34 +02002690 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002691 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002692}
2693
Adrian Knoth0dca1792011-01-26 19:32:14 +01002694
Takashi Iwai98274f02005-11-17 14:52:34 +01002695static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
2696 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002697{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002698 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002699
Adrian Knoth0dca1792011-01-26 19:32:14 +01002700 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002701 static char *texts[] = { "WordClock", "AES1", "AES2", "AES3",
2702 "AES4", "AES5", "AES6", "AES7", "AES8", "None"};
2703
2704 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2705 uinfo->count = 1;
2706 uinfo->value.enumerated.items = 10;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002707 if (uinfo->value.enumerated.item >=
2708 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002709 uinfo->value.enumerated.item =
2710 uinfo->value.enumerated.items - 1;
2711 strcpy(uinfo->value.enumerated.name,
2712 texts[uinfo->value.enumerated.item]);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002713 } else if (MADI == hdspm->io_type) {
2714 static char *texts[] = {"Word Clock", "MADI", "TCO",
2715 "Sync In", "None" };
Remy Bruno3cee5a62006-10-16 12:46:32 +02002716
2717 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2718 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002719 uinfo->value.enumerated.items = 5;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002720 if (uinfo->value.enumerated.item >=
Adrian Knoth0dca1792011-01-26 19:32:14 +01002721 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002722 uinfo->value.enumerated.item =
2723 uinfo->value.enumerated.items - 1;
2724 strcpy(uinfo->value.enumerated.name,
2725 texts[uinfo->value.enumerated.item]);
2726 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002727 return 0;
2728}
2729
Takashi Iwai98274f02005-11-17 14:52:34 +01002730static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
2731 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002732{
Takashi Iwai98274f02005-11-17 14:52:34 +01002733 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002734
Remy Bruno65345992007-08-31 12:21:08 +02002735 ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002736 return 0;
2737}
2738
Adrian Knoth0dca1792011-01-26 19:32:14 +01002739
Takashi Iwai763f3562005-06-03 11:25:34 +02002740#define HDSPM_LINE_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002741{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002742 .name = xname, \
2743 .index = xindex, \
2744 .info = snd_hdspm_info_line_out, \
2745 .get = snd_hdspm_get_line_out, \
2746 .put = snd_hdspm_put_line_out \
2747}
2748
Takashi Iwai98274f02005-11-17 14:52:34 +01002749static int hdspm_line_out(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002750{
2751 return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0;
2752}
2753
2754
Takashi Iwai98274f02005-11-17 14:52:34 +01002755static int hdspm_set_line_output(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002756{
2757 if (out)
2758 hdspm->control_register |= HDSPM_LineOut;
2759 else
2760 hdspm->control_register &= ~HDSPM_LineOut;
2761 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2762
2763 return 0;
2764}
2765
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002766#define snd_hdspm_info_line_out snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002767
Takashi Iwai98274f02005-11-17 14:52:34 +01002768static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol,
2769 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002770{
Takashi Iwai98274f02005-11-17 14:52:34 +01002771 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002772
2773 spin_lock_irq(&hdspm->lock);
2774 ucontrol->value.integer.value[0] = hdspm_line_out(hdspm);
2775 spin_unlock_irq(&hdspm->lock);
2776 return 0;
2777}
2778
Takashi Iwai98274f02005-11-17 14:52:34 +01002779static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
2780 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002781{
Takashi Iwai98274f02005-11-17 14:52:34 +01002782 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002783 int change;
2784 unsigned int val;
2785
2786 if (!snd_hdspm_use_is_exclusive(hdspm))
2787 return -EBUSY;
2788 val = ucontrol->value.integer.value[0] & 1;
2789 spin_lock_irq(&hdspm->lock);
2790 change = (int) val != hdspm_line_out(hdspm);
2791 hdspm_set_line_output(hdspm, val);
2792 spin_unlock_irq(&hdspm->lock);
2793 return change;
2794}
2795
Adrian Knoth0dca1792011-01-26 19:32:14 +01002796
Takashi Iwai763f3562005-06-03 11:25:34 +02002797#define HDSPM_TX_64(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002798{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002799 .name = xname, \
2800 .index = xindex, \
2801 .info = snd_hdspm_info_tx_64, \
2802 .get = snd_hdspm_get_tx_64, \
2803 .put = snd_hdspm_put_tx_64 \
2804}
2805
Takashi Iwai98274f02005-11-17 14:52:34 +01002806static int hdspm_tx_64(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002807{
2808 return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0;
2809}
2810
Takashi Iwai98274f02005-11-17 14:52:34 +01002811static int hdspm_set_tx_64(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002812{
2813 if (out)
2814 hdspm->control_register |= HDSPM_TX_64ch;
2815 else
2816 hdspm->control_register &= ~HDSPM_TX_64ch;
2817 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2818
2819 return 0;
2820}
2821
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002822#define snd_hdspm_info_tx_64 snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002823
Takashi Iwai98274f02005-11-17 14:52:34 +01002824static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol,
2825 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002826{
Takashi Iwai98274f02005-11-17 14:52:34 +01002827 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002828
2829 spin_lock_irq(&hdspm->lock);
2830 ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm);
2831 spin_unlock_irq(&hdspm->lock);
2832 return 0;
2833}
2834
Takashi Iwai98274f02005-11-17 14:52:34 +01002835static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
2836 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002837{
Takashi Iwai98274f02005-11-17 14:52:34 +01002838 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002839 int change;
2840 unsigned int val;
2841
2842 if (!snd_hdspm_use_is_exclusive(hdspm))
2843 return -EBUSY;
2844 val = ucontrol->value.integer.value[0] & 1;
2845 spin_lock_irq(&hdspm->lock);
2846 change = (int) val != hdspm_tx_64(hdspm);
2847 hdspm_set_tx_64(hdspm, val);
2848 spin_unlock_irq(&hdspm->lock);
2849 return change;
2850}
2851
Adrian Knoth0dca1792011-01-26 19:32:14 +01002852
Takashi Iwai763f3562005-06-03 11:25:34 +02002853#define HDSPM_C_TMS(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002854{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002855 .name = xname, \
2856 .index = xindex, \
2857 .info = snd_hdspm_info_c_tms, \
2858 .get = snd_hdspm_get_c_tms, \
2859 .put = snd_hdspm_put_c_tms \
2860}
2861
Takashi Iwai98274f02005-11-17 14:52:34 +01002862static int hdspm_c_tms(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002863{
2864 return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0;
2865}
2866
Takashi Iwai98274f02005-11-17 14:52:34 +01002867static int hdspm_set_c_tms(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002868{
2869 if (out)
2870 hdspm->control_register |= HDSPM_clr_tms;
2871 else
2872 hdspm->control_register &= ~HDSPM_clr_tms;
2873 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2874
2875 return 0;
2876}
2877
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002878#define snd_hdspm_info_c_tms snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002879
Takashi Iwai98274f02005-11-17 14:52:34 +01002880static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol,
2881 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002882{
Takashi Iwai98274f02005-11-17 14:52:34 +01002883 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002884
2885 spin_lock_irq(&hdspm->lock);
2886 ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm);
2887 spin_unlock_irq(&hdspm->lock);
2888 return 0;
2889}
2890
Takashi Iwai98274f02005-11-17 14:52:34 +01002891static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,
2892 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002893{
Takashi Iwai98274f02005-11-17 14:52:34 +01002894 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002895 int change;
2896 unsigned int val;
2897
2898 if (!snd_hdspm_use_is_exclusive(hdspm))
2899 return -EBUSY;
2900 val = ucontrol->value.integer.value[0] & 1;
2901 spin_lock_irq(&hdspm->lock);
2902 change = (int) val != hdspm_c_tms(hdspm);
2903 hdspm_set_c_tms(hdspm, val);
2904 spin_unlock_irq(&hdspm->lock);
2905 return change;
2906}
2907
Adrian Knoth0dca1792011-01-26 19:32:14 +01002908
Takashi Iwai763f3562005-06-03 11:25:34 +02002909#define HDSPM_SAFE_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002910{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002911 .name = xname, \
2912 .index = xindex, \
2913 .info = snd_hdspm_info_safe_mode, \
2914 .get = snd_hdspm_get_safe_mode, \
2915 .put = snd_hdspm_put_safe_mode \
2916}
2917
Takashi Iwai98274f02005-11-17 14:52:34 +01002918static int hdspm_safe_mode(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002919{
2920 return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0;
2921}
2922
Takashi Iwai98274f02005-11-17 14:52:34 +01002923static int hdspm_set_safe_mode(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002924{
2925 if (out)
2926 hdspm->control_register |= HDSPM_AutoInp;
2927 else
2928 hdspm->control_register &= ~HDSPM_AutoInp;
2929 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2930
2931 return 0;
2932}
2933
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002934#define snd_hdspm_info_safe_mode snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002935
Takashi Iwai98274f02005-11-17 14:52:34 +01002936static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol,
2937 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002938{
Takashi Iwai98274f02005-11-17 14:52:34 +01002939 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002940
2941 spin_lock_irq(&hdspm->lock);
2942 ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm);
2943 spin_unlock_irq(&hdspm->lock);
2944 return 0;
2945}
2946
Takashi Iwai98274f02005-11-17 14:52:34 +01002947static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
2948 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002949{
Takashi Iwai98274f02005-11-17 14:52:34 +01002950 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002951 int change;
2952 unsigned int val;
2953
2954 if (!snd_hdspm_use_is_exclusive(hdspm))
2955 return -EBUSY;
2956 val = ucontrol->value.integer.value[0] & 1;
2957 spin_lock_irq(&hdspm->lock);
2958 change = (int) val != hdspm_safe_mode(hdspm);
2959 hdspm_set_safe_mode(hdspm, val);
2960 spin_unlock_irq(&hdspm->lock);
2961 return change;
2962}
2963
Adrian Knoth0dca1792011-01-26 19:32:14 +01002964
Remy Bruno3cee5a62006-10-16 12:46:32 +02002965#define HDSPM_EMPHASIS(xname, xindex) \
2966{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2967 .name = xname, \
2968 .index = xindex, \
2969 .info = snd_hdspm_info_emphasis, \
2970 .get = snd_hdspm_get_emphasis, \
2971 .put = snd_hdspm_put_emphasis \
2972}
2973
2974static int hdspm_emphasis(struct hdspm * hdspm)
2975{
2976 return (hdspm->control_register & HDSPM_Emphasis) ? 1 : 0;
2977}
2978
2979static int hdspm_set_emphasis(struct hdspm * hdspm, int emp)
2980{
2981 if (emp)
2982 hdspm->control_register |= HDSPM_Emphasis;
2983 else
2984 hdspm->control_register &= ~HDSPM_Emphasis;
2985 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2986
2987 return 0;
2988}
2989
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002990#define snd_hdspm_info_emphasis snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02002991
2992static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol,
2993 struct snd_ctl_elem_value *ucontrol)
2994{
2995 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2996
2997 spin_lock_irq(&hdspm->lock);
2998 ucontrol->value.enumerated.item[0] = hdspm_emphasis(hdspm);
2999 spin_unlock_irq(&hdspm->lock);
3000 return 0;
3001}
3002
3003static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
3004 struct snd_ctl_elem_value *ucontrol)
3005{
3006 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3007 int change;
3008 unsigned int val;
3009
3010 if (!snd_hdspm_use_is_exclusive(hdspm))
3011 return -EBUSY;
3012 val = ucontrol->value.integer.value[0] & 1;
3013 spin_lock_irq(&hdspm->lock);
3014 change = (int) val != hdspm_emphasis(hdspm);
3015 hdspm_set_emphasis(hdspm, val);
3016 spin_unlock_irq(&hdspm->lock);
3017 return change;
3018}
3019
Adrian Knoth0dca1792011-01-26 19:32:14 +01003020
Remy Bruno3cee5a62006-10-16 12:46:32 +02003021#define HDSPM_DOLBY(xname, xindex) \
3022{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3023 .name = xname, \
3024 .index = xindex, \
3025 .info = snd_hdspm_info_dolby, \
3026 .get = snd_hdspm_get_dolby, \
3027 .put = snd_hdspm_put_dolby \
3028}
3029
3030static int hdspm_dolby(struct hdspm * hdspm)
3031{
3032 return (hdspm->control_register & HDSPM_Dolby) ? 1 : 0;
3033}
3034
3035static int hdspm_set_dolby(struct hdspm * hdspm, int dol)
3036{
3037 if (dol)
3038 hdspm->control_register |= HDSPM_Dolby;
3039 else
3040 hdspm->control_register &= ~HDSPM_Dolby;
3041 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3042
3043 return 0;
3044}
3045
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003046#define snd_hdspm_info_dolby snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02003047
3048static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol,
3049 struct snd_ctl_elem_value *ucontrol)
3050{
3051 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3052
3053 spin_lock_irq(&hdspm->lock);
3054 ucontrol->value.enumerated.item[0] = hdspm_dolby(hdspm);
3055 spin_unlock_irq(&hdspm->lock);
3056 return 0;
3057}
3058
3059static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
3060 struct snd_ctl_elem_value *ucontrol)
3061{
3062 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3063 int change;
3064 unsigned int val;
3065
3066 if (!snd_hdspm_use_is_exclusive(hdspm))
3067 return -EBUSY;
3068 val = ucontrol->value.integer.value[0] & 1;
3069 spin_lock_irq(&hdspm->lock);
3070 change = (int) val != hdspm_dolby(hdspm);
3071 hdspm_set_dolby(hdspm, val);
3072 spin_unlock_irq(&hdspm->lock);
3073 return change;
3074}
3075
Adrian Knoth0dca1792011-01-26 19:32:14 +01003076
Remy Bruno3cee5a62006-10-16 12:46:32 +02003077#define HDSPM_PROFESSIONAL(xname, xindex) \
3078{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3079 .name = xname, \
3080 .index = xindex, \
3081 .info = snd_hdspm_info_professional, \
3082 .get = snd_hdspm_get_professional, \
3083 .put = snd_hdspm_put_professional \
3084}
3085
3086static int hdspm_professional(struct hdspm * hdspm)
3087{
3088 return (hdspm->control_register & HDSPM_Professional) ? 1 : 0;
3089}
3090
3091static int hdspm_set_professional(struct hdspm * hdspm, int dol)
3092{
3093 if (dol)
3094 hdspm->control_register |= HDSPM_Professional;
3095 else
3096 hdspm->control_register &= ~HDSPM_Professional;
3097 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3098
3099 return 0;
3100}
3101
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003102#define snd_hdspm_info_professional snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02003103
3104static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol,
3105 struct snd_ctl_elem_value *ucontrol)
3106{
3107 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3108
3109 spin_lock_irq(&hdspm->lock);
3110 ucontrol->value.enumerated.item[0] = hdspm_professional(hdspm);
3111 spin_unlock_irq(&hdspm->lock);
3112 return 0;
3113}
3114
3115static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,
3116 struct snd_ctl_elem_value *ucontrol)
3117{
3118 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3119 int change;
3120 unsigned int val;
3121
3122 if (!snd_hdspm_use_is_exclusive(hdspm))
3123 return -EBUSY;
3124 val = ucontrol->value.integer.value[0] & 1;
3125 spin_lock_irq(&hdspm->lock);
3126 change = (int) val != hdspm_professional(hdspm);
3127 hdspm_set_professional(hdspm, val);
3128 spin_unlock_irq(&hdspm->lock);
3129 return change;
3130}
3131
Takashi Iwai763f3562005-06-03 11:25:34 +02003132#define HDSPM_INPUT_SELECT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003133{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003134 .name = xname, \
3135 .index = xindex, \
3136 .info = snd_hdspm_info_input_select, \
3137 .get = snd_hdspm_get_input_select, \
3138 .put = snd_hdspm_put_input_select \
3139}
3140
Takashi Iwai98274f02005-11-17 14:52:34 +01003141static int hdspm_input_select(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003142{
3143 return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
3144}
3145
Takashi Iwai98274f02005-11-17 14:52:34 +01003146static int hdspm_set_input_select(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02003147{
3148 if (out)
3149 hdspm->control_register |= HDSPM_InputSelect0;
3150 else
3151 hdspm->control_register &= ~HDSPM_InputSelect0;
3152 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3153
3154 return 0;
3155}
3156
Takashi Iwai98274f02005-11-17 14:52:34 +01003157static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
3158 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003159{
3160 static char *texts[] = { "optical", "coaxial" };
3161
3162 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3163 uinfo->count = 1;
3164 uinfo->value.enumerated.items = 2;
3165
3166 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3167 uinfo->value.enumerated.item =
3168 uinfo->value.enumerated.items - 1;
3169 strcpy(uinfo->value.enumerated.name,
3170 texts[uinfo->value.enumerated.item]);
3171
3172 return 0;
3173}
3174
Takashi Iwai98274f02005-11-17 14:52:34 +01003175static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
3176 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003177{
Takashi Iwai98274f02005-11-17 14:52:34 +01003178 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003179
3180 spin_lock_irq(&hdspm->lock);
3181 ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
3182 spin_unlock_irq(&hdspm->lock);
3183 return 0;
3184}
3185
Takashi Iwai98274f02005-11-17 14:52:34 +01003186static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
3187 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003188{
Takashi Iwai98274f02005-11-17 14:52:34 +01003189 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003190 int change;
3191 unsigned int val;
3192
3193 if (!snd_hdspm_use_is_exclusive(hdspm))
3194 return -EBUSY;
3195 val = ucontrol->value.integer.value[0] & 1;
3196 spin_lock_irq(&hdspm->lock);
3197 change = (int) val != hdspm_input_select(hdspm);
3198 hdspm_set_input_select(hdspm, val);
3199 spin_unlock_irq(&hdspm->lock);
3200 return change;
3201}
3202
Adrian Knoth0dca1792011-01-26 19:32:14 +01003203
Remy Bruno3cee5a62006-10-16 12:46:32 +02003204#define HDSPM_DS_WIRE(xname, xindex) \
3205{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3206 .name = xname, \
3207 .index = xindex, \
3208 .info = snd_hdspm_info_ds_wire, \
3209 .get = snd_hdspm_get_ds_wire, \
3210 .put = snd_hdspm_put_ds_wire \
3211}
3212
3213static int hdspm_ds_wire(struct hdspm * hdspm)
3214{
3215 return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
3216}
3217
3218static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
3219{
3220 if (ds)
3221 hdspm->control_register |= HDSPM_DS_DoubleWire;
3222 else
3223 hdspm->control_register &= ~HDSPM_DS_DoubleWire;
3224 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3225
3226 return 0;
3227}
3228
3229static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
3230 struct snd_ctl_elem_info *uinfo)
3231{
3232 static char *texts[] = { "Single", "Double" };
3233
3234 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3235 uinfo->count = 1;
3236 uinfo->value.enumerated.items = 2;
3237
3238 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3239 uinfo->value.enumerated.item =
3240 uinfo->value.enumerated.items - 1;
3241 strcpy(uinfo->value.enumerated.name,
3242 texts[uinfo->value.enumerated.item]);
3243
3244 return 0;
3245}
3246
3247static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
3248 struct snd_ctl_elem_value *ucontrol)
3249{
3250 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3251
3252 spin_lock_irq(&hdspm->lock);
3253 ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
3254 spin_unlock_irq(&hdspm->lock);
3255 return 0;
3256}
3257
3258static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
3259 struct snd_ctl_elem_value *ucontrol)
3260{
3261 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3262 int change;
3263 unsigned int val;
3264
3265 if (!snd_hdspm_use_is_exclusive(hdspm))
3266 return -EBUSY;
3267 val = ucontrol->value.integer.value[0] & 1;
3268 spin_lock_irq(&hdspm->lock);
3269 change = (int) val != hdspm_ds_wire(hdspm);
3270 hdspm_set_ds_wire(hdspm, val);
3271 spin_unlock_irq(&hdspm->lock);
3272 return change;
3273}
3274
Adrian Knoth0dca1792011-01-26 19:32:14 +01003275
Remy Bruno3cee5a62006-10-16 12:46:32 +02003276#define HDSPM_QS_WIRE(xname, xindex) \
3277{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3278 .name = xname, \
3279 .index = xindex, \
3280 .info = snd_hdspm_info_qs_wire, \
3281 .get = snd_hdspm_get_qs_wire, \
3282 .put = snd_hdspm_put_qs_wire \
3283}
3284
3285static int hdspm_qs_wire(struct hdspm * hdspm)
3286{
3287 if (hdspm->control_register & HDSPM_QS_DoubleWire)
3288 return 1;
3289 if (hdspm->control_register & HDSPM_QS_QuadWire)
3290 return 2;
3291 return 0;
3292}
3293
3294static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
3295{
3296 hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
3297 switch (mode) {
3298 case 0:
3299 break;
3300 case 1:
3301 hdspm->control_register |= HDSPM_QS_DoubleWire;
3302 break;
3303 case 2:
3304 hdspm->control_register |= HDSPM_QS_QuadWire;
3305 break;
3306 }
3307 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3308
3309 return 0;
3310}
3311
3312static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
3313 struct snd_ctl_elem_info *uinfo)
3314{
3315 static char *texts[] = { "Single", "Double", "Quad" };
3316
3317 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3318 uinfo->count = 1;
3319 uinfo->value.enumerated.items = 3;
3320
3321 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3322 uinfo->value.enumerated.item =
3323 uinfo->value.enumerated.items - 1;
3324 strcpy(uinfo->value.enumerated.name,
3325 texts[uinfo->value.enumerated.item]);
3326
3327 return 0;
3328}
3329
3330static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
3331 struct snd_ctl_elem_value *ucontrol)
3332{
3333 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3334
3335 spin_lock_irq(&hdspm->lock);
3336 ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
3337 spin_unlock_irq(&hdspm->lock);
3338 return 0;
3339}
3340
3341static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
3342 struct snd_ctl_elem_value *ucontrol)
3343{
3344 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3345 int change;
3346 int val;
3347
3348 if (!snd_hdspm_use_is_exclusive(hdspm))
3349 return -EBUSY;
3350 val = ucontrol->value.integer.value[0];
3351 if (val < 0)
3352 val = 0;
3353 if (val > 2)
3354 val = 2;
3355 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003356 change = val != hdspm_qs_wire(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003357 hdspm_set_qs_wire(hdspm, val);
3358 spin_unlock_irq(&hdspm->lock);
3359 return change;
3360}
3361
Takashi Iwai763f3562005-06-03 11:25:34 +02003362
3363#define HDSPM_MIXER(xname, xindex) \
3364{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
3365 .name = xname, \
3366 .index = xindex, \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003367 .device = 0, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003368 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
3369 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3370 .info = snd_hdspm_info_mixer, \
3371 .get = snd_hdspm_get_mixer, \
3372 .put = snd_hdspm_put_mixer \
3373}
3374
Takashi Iwai98274f02005-11-17 14:52:34 +01003375static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
3376 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003377{
3378 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3379 uinfo->count = 3;
3380 uinfo->value.integer.min = 0;
3381 uinfo->value.integer.max = 65535;
3382 uinfo->value.integer.step = 1;
3383 return 0;
3384}
3385
Takashi Iwai98274f02005-11-17 14:52:34 +01003386static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
3387 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003388{
Takashi Iwai98274f02005-11-17 14:52:34 +01003389 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003390 int source;
3391 int destination;
3392
3393 source = ucontrol->value.integer.value[0];
3394 if (source < 0)
3395 source = 0;
3396 else if (source >= 2 * HDSPM_MAX_CHANNELS)
3397 source = 2 * HDSPM_MAX_CHANNELS - 1;
3398
3399 destination = ucontrol->value.integer.value[1];
3400 if (destination < 0)
3401 destination = 0;
3402 else if (destination >= HDSPM_MAX_CHANNELS)
3403 destination = HDSPM_MAX_CHANNELS - 1;
3404
3405 spin_lock_irq(&hdspm->lock);
3406 if (source >= HDSPM_MAX_CHANNELS)
3407 ucontrol->value.integer.value[2] =
3408 hdspm_read_pb_gain(hdspm, destination,
3409 source - HDSPM_MAX_CHANNELS);
3410 else
3411 ucontrol->value.integer.value[2] =
3412 hdspm_read_in_gain(hdspm, destination, source);
3413
3414 spin_unlock_irq(&hdspm->lock);
3415
3416 return 0;
3417}
3418
Takashi Iwai98274f02005-11-17 14:52:34 +01003419static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
3420 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003421{
Takashi Iwai98274f02005-11-17 14:52:34 +01003422 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003423 int change;
3424 int source;
3425 int destination;
3426 int gain;
3427
3428 if (!snd_hdspm_use_is_exclusive(hdspm))
3429 return -EBUSY;
3430
3431 source = ucontrol->value.integer.value[0];
3432 destination = ucontrol->value.integer.value[1];
3433
3434 if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
3435 return -1;
3436 if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
3437 return -1;
3438
3439 gain = ucontrol->value.integer.value[2];
3440
3441 spin_lock_irq(&hdspm->lock);
3442
3443 if (source >= HDSPM_MAX_CHANNELS)
3444 change = gain != hdspm_read_pb_gain(hdspm, destination,
3445 source -
3446 HDSPM_MAX_CHANNELS);
3447 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003448 change = gain != hdspm_read_in_gain(hdspm, destination,
3449 source);
Takashi Iwai763f3562005-06-03 11:25:34 +02003450
3451 if (change) {
3452 if (source >= HDSPM_MAX_CHANNELS)
3453 hdspm_write_pb_gain(hdspm, destination,
3454 source - HDSPM_MAX_CHANNELS,
3455 gain);
3456 else
3457 hdspm_write_in_gain(hdspm, destination, source,
3458 gain);
3459 }
3460 spin_unlock_irq(&hdspm->lock);
3461
3462 return change;
3463}
3464
3465/* The simple mixer control(s) provide gain control for the
3466 basic 1:1 mappings of playback streams to output
Adrian Knoth0dca1792011-01-26 19:32:14 +01003467 streams.
Takashi Iwai763f3562005-06-03 11:25:34 +02003468*/
3469
3470#define HDSPM_PLAYBACK_MIXER \
3471{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3472 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
3473 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3474 .info = snd_hdspm_info_playback_mixer, \
3475 .get = snd_hdspm_get_playback_mixer, \
3476 .put = snd_hdspm_put_playback_mixer \
3477}
3478
Takashi Iwai98274f02005-11-17 14:52:34 +01003479static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
3480 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003481{
3482 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3483 uinfo->count = 1;
3484 uinfo->value.integer.min = 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003485 uinfo->value.integer.max = 64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003486 uinfo->value.integer.step = 1;
3487 return 0;
3488}
3489
Takashi Iwai98274f02005-11-17 14:52:34 +01003490static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
3491 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003492{
Takashi Iwai98274f02005-11-17 14:52:34 +01003493 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003494 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003495
3496 channel = ucontrol->id.index - 1;
3497
Takashi Iwaida3cec32008-08-08 17:12:14 +02003498 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3499 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003500
Takashi Iwai763f3562005-06-03 11:25:34 +02003501 spin_lock_irq(&hdspm->lock);
3502 ucontrol->value.integer.value[0] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003503 (hdspm_read_pb_gain(hdspm, channel, channel)*64)/UNITY_GAIN;
Takashi Iwai763f3562005-06-03 11:25:34 +02003504 spin_unlock_irq(&hdspm->lock);
3505
Takashi Iwai763f3562005-06-03 11:25:34 +02003506 return 0;
3507}
3508
Takashi Iwai98274f02005-11-17 14:52:34 +01003509static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
3510 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003511{
Takashi Iwai98274f02005-11-17 14:52:34 +01003512 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003513 int change;
3514 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003515 int gain;
3516
3517 if (!snd_hdspm_use_is_exclusive(hdspm))
3518 return -EBUSY;
3519
3520 channel = ucontrol->id.index - 1;
3521
Takashi Iwaida3cec32008-08-08 17:12:14 +02003522 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3523 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003524
Adrian Knoth0dca1792011-01-26 19:32:14 +01003525 gain = ucontrol->value.integer.value[0]*UNITY_GAIN/64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003526
3527 spin_lock_irq(&hdspm->lock);
3528 change =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003529 gain != hdspm_read_pb_gain(hdspm, channel,
3530 channel);
Takashi Iwai763f3562005-06-03 11:25:34 +02003531 if (change)
Adrian Knoth0dca1792011-01-26 19:32:14 +01003532 hdspm_write_pb_gain(hdspm, channel, channel,
Takashi Iwai763f3562005-06-03 11:25:34 +02003533 gain);
3534 spin_unlock_irq(&hdspm->lock);
3535 return change;
3536}
3537
Adrian Knoth0dca1792011-01-26 19:32:14 +01003538#define HDSPM_SYNC_CHECK(xname, xindex) \
3539{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3540 .name = xname, \
3541 .private_value = xindex, \
3542 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3543 .info = snd_hdspm_info_sync_check, \
3544 .get = snd_hdspm_get_sync_check \
Takashi Iwai763f3562005-06-03 11:25:34 +02003545}
3546
Adrian Knoth0dca1792011-01-26 19:32:14 +01003547
Takashi Iwai98274f02005-11-17 14:52:34 +01003548static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
3549 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003550{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003551 static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" };
Takashi Iwai763f3562005-06-03 11:25:34 +02003552 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3553 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003554 uinfo->value.enumerated.items = 4;
Takashi Iwai763f3562005-06-03 11:25:34 +02003555 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3556 uinfo->value.enumerated.item =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003557 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02003558 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01003559 texts[uinfo->value.enumerated.item]);
Takashi Iwai763f3562005-06-03 11:25:34 +02003560 return 0;
3561}
3562
Adrian Knoth0dca1792011-01-26 19:32:14 +01003563static int hdspm_wc_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003564{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003565 int status, status2;
3566
3567 switch (hdspm->io_type) {
3568 case AES32:
3569 status = hdspm_read(hdspm, HDSPM_statusRegister);
3570 if (status & HDSPM_wcSync)
Takashi Iwai763f3562005-06-03 11:25:34 +02003571 return 2;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003572 else if (status & HDSPM_wcLock)
3573 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003574 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003575 break;
3576
3577 case MADI:
3578 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003579 if (status2 & HDSPM_wcLock) {
3580 if (status2 & HDSPM_wcSync)
3581 return 2;
3582 else
3583 return 1;
3584 }
3585 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003586 break;
3587
3588 case RayDAT:
3589 case AIO:
3590 status = hdspm_read(hdspm, HDSPM_statusRegister);
3591
3592 if (status & 0x2000000)
3593 return 2;
3594 else if (status & 0x1000000)
3595 return 1;
3596 return 0;
3597
3598 break;
3599
3600 case MADIface:
3601 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02003602 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003603
Takashi Iwai763f3562005-06-03 11:25:34 +02003604
Adrian Knoth0dca1792011-01-26 19:32:14 +01003605 return 3;
Takashi Iwai763f3562005-06-03 11:25:34 +02003606}
3607
3608
Adrian Knoth0dca1792011-01-26 19:32:14 +01003609static int hdspm_madi_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003610{
3611 int status = hdspm_read(hdspm, HDSPM_statusRegister);
3612 if (status & HDSPM_madiLock) {
3613 if (status & HDSPM_madiSync)
3614 return 2;
3615 else
3616 return 1;
3617 }
3618 return 0;
3619}
3620
Adrian Knoth0dca1792011-01-26 19:32:14 +01003621
3622static int hdspm_s1_sync_check(struct hdspm *hdspm, int idx)
3623{
3624 int status, lock, sync;
3625
3626 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3627
3628 lock = (status & (0x1<<idx)) ? 1 : 0;
3629 sync = (status & (0x100<<idx)) ? 1 : 0;
3630
3631 if (lock && sync)
3632 return 2;
3633 else if (lock)
3634 return 1;
3635 return 0;
3636}
3637
3638
3639static int hdspm_sync_in_sync_check(struct hdspm *hdspm)
3640{
3641 int status, lock = 0, sync = 0;
3642
3643 switch (hdspm->io_type) {
3644 case RayDAT:
3645 case AIO:
3646 status = hdspm_read(hdspm, HDSPM_RD_STATUS_3);
3647 lock = (status & 0x400) ? 1 : 0;
3648 sync = (status & 0x800) ? 1 : 0;
3649 break;
3650
3651 case MADI:
3652 case AES32:
3653 status = hdspm_read(hdspm, HDSPM_statusRegister2);
3654 lock = (status & 0x400000) ? 1 : 0;
3655 sync = (status & 0x800000) ? 1 : 0;
3656 break;
3657
3658 case MADIface:
3659 break;
3660 }
3661
3662 if (lock && sync)
3663 return 2;
3664 else if (lock)
3665 return 1;
3666
3667 return 0;
3668}
3669
3670static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx)
3671{
3672 int status2, lock, sync;
3673 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
3674
3675 lock = (status2 & (0x0080 >> idx)) ? 1 : 0;
3676 sync = (status2 & (0x8000 >> idx)) ? 1 : 0;
3677
3678 if (sync)
3679 return 2;
3680 else if (lock)
3681 return 1;
3682 return 0;
3683}
3684
3685
3686static int hdspm_tco_sync_check(struct hdspm *hdspm)
3687{
3688 int status;
3689
3690 if (hdspm->tco) {
3691 switch (hdspm->io_type) {
3692 case MADI:
3693 case AES32:
3694 status = hdspm_read(hdspm, HDSPM_statusRegister);
3695 if (status & HDSPM_tcoLock) {
3696 if (status & HDSPM_tcoSync)
3697 return 2;
3698 else
3699 return 1;
3700 }
3701 return 0;
3702
3703 break;
3704
3705 case RayDAT:
3706 case AIO:
3707 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3708
3709 if (status & 0x8000000)
3710 return 2; /* Sync */
3711 if (status & 0x4000000)
3712 return 1; /* Lock */
3713 return 0; /* No signal */
3714 break;
3715
3716 default:
3717 break;
3718 }
3719 }
3720
3721 return 3; /* N/A */
3722}
3723
3724
3725static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
3726 struct snd_ctl_elem_value *ucontrol)
3727{
3728 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3729 int val = -1;
3730
3731 switch (hdspm->io_type) {
3732 case RayDAT:
3733 switch (kcontrol->private_value) {
3734 case 0: /* WC */
3735 val = hdspm_wc_sync_check(hdspm); break;
3736 case 7: /* TCO */
3737 val = hdspm_tco_sync_check(hdspm); break;
3738 case 8: /* SYNC IN */
3739 val = hdspm_sync_in_sync_check(hdspm); break;
3740 default:
3741 val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
3742 }
3743
3744 case AIO:
3745 switch (kcontrol->private_value) {
3746 case 0: /* WC */
3747 val = hdspm_wc_sync_check(hdspm); break;
3748 case 4: /* TCO */
3749 val = hdspm_tco_sync_check(hdspm); break;
3750 case 5: /* SYNC IN */
3751 val = hdspm_sync_in_sync_check(hdspm); break;
3752 default:
3753 val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
3754 }
3755
3756 case MADI:
3757 switch (kcontrol->private_value) {
3758 case 0: /* WC */
3759 val = hdspm_wc_sync_check(hdspm); break;
3760 case 1: /* MADI */
3761 val = hdspm_madi_sync_check(hdspm); break;
3762 case 2: /* TCO */
3763 val = hdspm_tco_sync_check(hdspm); break;
3764 case 3: /* SYNC_IN */
3765 val = hdspm_sync_in_sync_check(hdspm); break;
3766 }
3767
3768 case MADIface:
3769 val = hdspm_madi_sync_check(hdspm); /* MADI */
3770 break;
3771
3772 case AES32:
3773 switch (kcontrol->private_value) {
3774 case 0: /* WC */
3775 val = hdspm_wc_sync_check(hdspm); break;
3776 case 9: /* TCO */
3777 val = hdspm_tco_sync_check(hdspm); break;
3778 case 10 /* SYNC IN */:
3779 val = hdspm_sync_in_sync_check(hdspm); break;
3780 default:
3781 val = hdspm_aes_sync_check(hdspm,
3782 ucontrol->id.index-1);
3783 }
3784
3785 }
3786
3787 if (-1 == val)
3788 val = 3;
3789
3790 ucontrol->value.enumerated.item[0] = val;
3791 return 0;
3792}
3793
3794
3795
3796/**
3797 * TCO controls
3798 **/
3799static void hdspm_tco_write(struct hdspm *hdspm)
3800{
3801 unsigned int tc[4] = { 0, 0, 0, 0};
3802
3803 switch (hdspm->tco->input) {
3804 case 0:
3805 tc[2] |= HDSPM_TCO2_set_input_MSB;
3806 break;
3807 case 1:
3808 tc[2] |= HDSPM_TCO2_set_input_LSB;
3809 break;
3810 default:
3811 break;
3812 }
3813
3814 switch (hdspm->tco->framerate) {
3815 case 1:
3816 tc[1] |= HDSPM_TCO1_LTC_Format_LSB;
3817 break;
3818 case 2:
3819 tc[1] |= HDSPM_TCO1_LTC_Format_MSB;
3820 break;
3821 case 3:
3822 tc[1] |= HDSPM_TCO1_LTC_Format_MSB +
3823 HDSPM_TCO1_set_drop_frame_flag;
3824 break;
3825 case 4:
3826 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
3827 HDSPM_TCO1_LTC_Format_MSB;
3828 break;
3829 case 5:
3830 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
3831 HDSPM_TCO1_LTC_Format_MSB +
3832 HDSPM_TCO1_set_drop_frame_flag;
3833 break;
3834 default:
3835 break;
3836 }
3837
3838 switch (hdspm->tco->wordclock) {
3839 case 1:
3840 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_LSB;
3841 break;
3842 case 2:
3843 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_MSB;
3844 break;
3845 default:
3846 break;
3847 }
3848
3849 switch (hdspm->tco->samplerate) {
3850 case 1:
3851 tc[2] |= HDSPM_TCO2_set_freq;
3852 break;
3853 case 2:
3854 tc[2] |= HDSPM_TCO2_set_freq_from_app;
3855 break;
3856 default:
3857 break;
3858 }
3859
3860 switch (hdspm->tco->pull) {
3861 case 1:
3862 tc[2] |= HDSPM_TCO2_set_pull_up;
3863 break;
3864 case 2:
3865 tc[2] |= HDSPM_TCO2_set_pull_down;
3866 break;
3867 case 3:
3868 tc[2] |= HDSPM_TCO2_set_pull_up + HDSPM_TCO2_set_01_4;
3869 break;
3870 case 4:
3871 tc[2] |= HDSPM_TCO2_set_pull_down + HDSPM_TCO2_set_01_4;
3872 break;
3873 default:
3874 break;
3875 }
3876
3877 if (1 == hdspm->tco->term) {
3878 tc[2] |= HDSPM_TCO2_set_term_75R;
3879 }
3880
3881 hdspm_write(hdspm, HDSPM_WR_TCO, tc[0]);
3882 hdspm_write(hdspm, HDSPM_WR_TCO+4, tc[1]);
3883 hdspm_write(hdspm, HDSPM_WR_TCO+8, tc[2]);
3884 hdspm_write(hdspm, HDSPM_WR_TCO+12, tc[3]);
3885}
3886
3887
3888#define HDSPM_TCO_SAMPLE_RATE(xname, xindex) \
3889{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3890 .name = xname, \
3891 .index = xindex, \
3892 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
3893 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3894 .info = snd_hdspm_info_tco_sample_rate, \
3895 .get = snd_hdspm_get_tco_sample_rate, \
3896 .put = snd_hdspm_put_tco_sample_rate \
3897}
3898
3899static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol,
3900 struct snd_ctl_elem_info *uinfo)
3901{
3902 static char *texts[] = { "44.1 kHz", "48 kHz" };
3903 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3904 uinfo->count = 1;
3905 uinfo->value.enumerated.items = 2;
3906
3907 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3908 uinfo->value.enumerated.item =
3909 uinfo->value.enumerated.items - 1;
3910
3911 strcpy(uinfo->value.enumerated.name,
3912 texts[uinfo->value.enumerated.item]);
3913
3914 return 0;
3915}
3916
3917static int snd_hdspm_get_tco_sample_rate(struct snd_kcontrol *kcontrol,
3918 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003919{
Takashi Iwai98274f02005-11-17 14:52:34 +01003920 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003921
Adrian Knoth0dca1792011-01-26 19:32:14 +01003922 ucontrol->value.enumerated.item[0] = hdspm->tco->samplerate;
3923
Takashi Iwai763f3562005-06-03 11:25:34 +02003924 return 0;
3925}
3926
Adrian Knoth0dca1792011-01-26 19:32:14 +01003927static int snd_hdspm_put_tco_sample_rate(struct snd_kcontrol *kcontrol,
3928 struct snd_ctl_elem_value *ucontrol)
Remy Bruno3cee5a62006-10-16 12:46:32 +02003929{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003930 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3931
3932 if (hdspm->tco->samplerate != ucontrol->value.enumerated.item[0]) {
3933 hdspm->tco->samplerate = ucontrol->value.enumerated.item[0];
3934
3935 hdspm_tco_write(hdspm);
3936
3937 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003938 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01003939
Remy Bruno3cee5a62006-10-16 12:46:32 +02003940 return 0;
3941}
3942
Adrian Knoth0dca1792011-01-26 19:32:14 +01003943
3944#define HDSPM_TCO_PULL(xname, xindex) \
3945{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3946 .name = xname, \
3947 .index = xindex, \
3948 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
3949 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3950 .info = snd_hdspm_info_tco_pull, \
3951 .get = snd_hdspm_get_tco_pull, \
3952 .put = snd_hdspm_put_tco_pull \
3953}
3954
3955static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol,
3956 struct snd_ctl_elem_info *uinfo)
3957{
3958 static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" };
3959 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3960 uinfo->count = 1;
3961 uinfo->value.enumerated.items = 5;
3962
3963 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3964 uinfo->value.enumerated.item =
3965 uinfo->value.enumerated.items - 1;
3966
3967 strcpy(uinfo->value.enumerated.name,
3968 texts[uinfo->value.enumerated.item]);
3969
3970 return 0;
3971}
3972
3973static int snd_hdspm_get_tco_pull(struct snd_kcontrol *kcontrol,
3974 struct snd_ctl_elem_value *ucontrol)
3975{
3976 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3977
3978 ucontrol->value.enumerated.item[0] = hdspm->tco->pull;
3979
3980 return 0;
3981}
3982
3983static int snd_hdspm_put_tco_pull(struct snd_kcontrol *kcontrol,
3984 struct snd_ctl_elem_value *ucontrol)
3985{
3986 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3987
3988 if (hdspm->tco->pull != ucontrol->value.enumerated.item[0]) {
3989 hdspm->tco->pull = ucontrol->value.enumerated.item[0];
3990
3991 hdspm_tco_write(hdspm);
3992
3993 return 1;
3994 }
3995
3996 return 0;
3997}
3998
3999#define HDSPM_TCO_WCK_CONVERSION(xname, xindex) \
4000{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4001 .name = xname, \
4002 .index = xindex, \
4003 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4004 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4005 .info = snd_hdspm_info_tco_wck_conversion, \
4006 .get = snd_hdspm_get_tco_wck_conversion, \
4007 .put = snd_hdspm_put_tco_wck_conversion \
4008}
4009
4010static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4011 struct snd_ctl_elem_info *uinfo)
4012{
4013 static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
4014 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4015 uinfo->count = 1;
4016 uinfo->value.enumerated.items = 3;
4017
4018 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4019 uinfo->value.enumerated.item =
4020 uinfo->value.enumerated.items - 1;
4021
4022 strcpy(uinfo->value.enumerated.name,
4023 texts[uinfo->value.enumerated.item]);
4024
4025 return 0;
4026}
4027
4028static int snd_hdspm_get_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4029 struct snd_ctl_elem_value *ucontrol)
4030{
4031 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4032
4033 ucontrol->value.enumerated.item[0] = hdspm->tco->wordclock;
4034
4035 return 0;
4036}
4037
4038static int snd_hdspm_put_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4039 struct snd_ctl_elem_value *ucontrol)
4040{
4041 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4042
4043 if (hdspm->tco->wordclock != ucontrol->value.enumerated.item[0]) {
4044 hdspm->tco->wordclock = ucontrol->value.enumerated.item[0];
4045
4046 hdspm_tco_write(hdspm);
4047
4048 return 1;
4049 }
4050
4051 return 0;
4052}
4053
4054
4055#define HDSPM_TCO_FRAME_RATE(xname, xindex) \
4056{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4057 .name = xname, \
4058 .index = xindex, \
4059 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4060 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4061 .info = snd_hdspm_info_tco_frame_rate, \
4062 .get = snd_hdspm_get_tco_frame_rate, \
4063 .put = snd_hdspm_put_tco_frame_rate \
4064}
4065
4066static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol,
4067 struct snd_ctl_elem_info *uinfo)
4068{
4069 static char *texts[] = { "24 fps", "25 fps", "29.97fps",
4070 "29.97 dfps", "30 fps", "30 dfps" };
4071 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4072 uinfo->count = 1;
4073 uinfo->value.enumerated.items = 6;
4074
4075 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4076 uinfo->value.enumerated.item =
4077 uinfo->value.enumerated.items - 1;
4078
4079 strcpy(uinfo->value.enumerated.name,
4080 texts[uinfo->value.enumerated.item]);
4081
4082 return 0;
4083}
4084
4085static int snd_hdspm_get_tco_frame_rate(struct snd_kcontrol *kcontrol,
Remy Bruno3cee5a62006-10-16 12:46:32 +02004086 struct snd_ctl_elem_value *ucontrol)
4087{
Remy Bruno3cee5a62006-10-16 12:46:32 +02004088 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4089
Adrian Knoth0dca1792011-01-26 19:32:14 +01004090 ucontrol->value.enumerated.item[0] = hdspm->tco->framerate;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004091
Remy Bruno3cee5a62006-10-16 12:46:32 +02004092 return 0;
4093}
Takashi Iwai763f3562005-06-03 11:25:34 +02004094
Adrian Knoth0dca1792011-01-26 19:32:14 +01004095static int snd_hdspm_put_tco_frame_rate(struct snd_kcontrol *kcontrol,
4096 struct snd_ctl_elem_value *ucontrol)
4097{
4098 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4099
4100 if (hdspm->tco->framerate != ucontrol->value.enumerated.item[0]) {
4101 hdspm->tco->framerate = ucontrol->value.enumerated.item[0];
4102
4103 hdspm_tco_write(hdspm);
4104
4105 return 1;
4106 }
4107
4108 return 0;
4109}
4110
4111
4112#define HDSPM_TCO_SYNC_SOURCE(xname, xindex) \
4113{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4114 .name = xname, \
4115 .index = xindex, \
4116 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4117 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4118 .info = snd_hdspm_info_tco_sync_source, \
4119 .get = snd_hdspm_get_tco_sync_source, \
4120 .put = snd_hdspm_put_tco_sync_source \
4121}
4122
4123static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol,
4124 struct snd_ctl_elem_info *uinfo)
4125{
4126 static char *texts[] = { "LTC", "Video", "WCK" };
4127 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4128 uinfo->count = 1;
4129 uinfo->value.enumerated.items = 3;
4130
4131 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4132 uinfo->value.enumerated.item =
4133 uinfo->value.enumerated.items - 1;
4134
4135 strcpy(uinfo->value.enumerated.name,
4136 texts[uinfo->value.enumerated.item]);
4137
4138 return 0;
4139}
4140
4141static int snd_hdspm_get_tco_sync_source(struct snd_kcontrol *kcontrol,
4142 struct snd_ctl_elem_value *ucontrol)
4143{
4144 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4145
4146 ucontrol->value.enumerated.item[0] = hdspm->tco->input;
4147
4148 return 0;
4149}
4150
4151static int snd_hdspm_put_tco_sync_source(struct snd_kcontrol *kcontrol,
4152 struct snd_ctl_elem_value *ucontrol)
4153{
4154 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4155
4156 if (hdspm->tco->input != ucontrol->value.enumerated.item[0]) {
4157 hdspm->tco->input = ucontrol->value.enumerated.item[0];
4158
4159 hdspm_tco_write(hdspm);
4160
4161 return 1;
4162 }
4163
4164 return 0;
4165}
4166
4167
4168#define HDSPM_TCO_WORD_TERM(xname, xindex) \
4169{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4170 .name = xname, \
4171 .index = xindex, \
4172 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4173 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4174 .info = snd_hdspm_info_tco_word_term, \
4175 .get = snd_hdspm_get_tco_word_term, \
4176 .put = snd_hdspm_put_tco_word_term \
4177}
4178
4179static int snd_hdspm_info_tco_word_term(struct snd_kcontrol *kcontrol,
4180 struct snd_ctl_elem_info *uinfo)
4181{
4182 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
4183 uinfo->count = 1;
4184 uinfo->value.integer.min = 0;
4185 uinfo->value.integer.max = 1;
4186
4187 return 0;
4188}
4189
4190
4191static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol,
4192 struct snd_ctl_elem_value *ucontrol)
4193{
4194 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4195
4196 ucontrol->value.enumerated.item[0] = hdspm->tco->term;
4197
4198 return 0;
4199}
4200
4201
4202static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol,
4203 struct snd_ctl_elem_value *ucontrol)
4204{
4205 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4206
4207 if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) {
4208 hdspm->tco->term = ucontrol->value.enumerated.item[0];
4209
4210 hdspm_tco_write(hdspm);
4211
4212 return 1;
4213 }
4214
4215 return 0;
4216}
4217
4218
4219
Takashi Iwai763f3562005-06-03 11:25:34 +02004220
Remy Bruno3cee5a62006-10-16 12:46:32 +02004221static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004222 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004223 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Takashi Iwai763f3562005-06-03 11:25:34 +02004224 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4225 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4226 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4227 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004228 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4229 HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
4230 HDSPM_SYNC_CHECK("TCO SyncCHeck", 2),
4231 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
Takashi Iwai763f3562005-06-03 11:25:34 +02004232 HDSPM_LINE_OUT("Line Out", 0),
4233 HDSPM_TX_64("TX 64 channels mode", 0),
4234 HDSPM_C_TMS("Clear Track Marker", 0),
4235 HDSPM_SAFE_MODE("Safe Mode", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004236 HDSPM_INPUT_SELECT("Input Select", 0)
4237};
4238
4239
4240static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
4241 HDSPM_MIXER("Mixer", 0),
4242 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4243 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4244 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4245 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4246 HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
4247 HDSPM_TX_64("TX 64 channels mode", 0),
4248 HDSPM_C_TMS("Clear Track Marker", 0),
4249 HDSPM_SAFE_MODE("Safe Mode", 0),
Takashi Iwai763f3562005-06-03 11:25:34 +02004250 HDSPM_INPUT_SELECT("Input Select", 0),
4251};
4252
Adrian Knoth0dca1792011-01-26 19:32:14 +01004253static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004254 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004255 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004256 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4257 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4258 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4259 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004260 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004261 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4262 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4263 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4264 HDSPM_SYNC_CHECK("ADAT SyncCheck", 3),
4265 HDSPM_SYNC_CHECK("TCO SyncCheck", 4),
4266 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 5),
4267 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4268 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4269 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4270 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT Frequency", 3),
4271 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 4),
4272 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5)
4273
4274 /*
4275 HDSPM_INPUT_SELECT("Input Select", 0),
4276 HDSPM_SPDIF_OPTICAL("SPDIF Out Optical", 0),
4277 HDSPM_PROFESSIONAL("SPDIF Out Professional", 0);
4278 HDSPM_SPDIF_IN("SPDIF In", 0);
4279 HDSPM_BREAKOUT_CABLE("Breakout Cable", 0);
4280 HDSPM_INPUT_LEVEL("Input Level", 0);
4281 HDSPM_OUTPUT_LEVEL("Output Level", 0);
4282 HDSPM_PHONES("Phones", 0);
4283 */
4284};
4285
4286static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = {
4287 HDSPM_MIXER("Mixer", 0),
4288 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4289 HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0),
4290 HDSPM_PREF_SYNC_REF("Pref Sync Ref", 0),
4291 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4292 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4293 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4294 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4295 HDSPM_SYNC_CHECK("ADAT1 SyncCheck", 3),
4296 HDSPM_SYNC_CHECK("ADAT2 SyncCheck", 4),
4297 HDSPM_SYNC_CHECK("ADAT3 SyncCheck", 5),
4298 HDSPM_SYNC_CHECK("ADAT4 SyncCheck", 6),
4299 HDSPM_SYNC_CHECK("TCO SyncCheck", 7),
4300 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 8),
4301 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4302 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4303 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4304 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT1 Frequency", 3),
4305 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT2 Frequency", 4),
4306 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT3 Frequency", 5),
4307 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT4 Frequency", 6),
4308 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 7),
4309 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8)
4310};
4311
4312static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
4313 HDSPM_MIXER("Mixer", 0),
4314 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4315 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4316 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4317 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4318 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4319 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4320 HDSPM_SYNC_CHECK("WC Sync Check", 0),
4321 HDSPM_SYNC_CHECK("AES1 Sync Check", 1),
4322 HDSPM_SYNC_CHECK("AES2 Sync Check", 2),
4323 HDSPM_SYNC_CHECK("AES3 Sync Check", 3),
4324 HDSPM_SYNC_CHECK("AES4 Sync Check", 4),
4325 HDSPM_SYNC_CHECK("AES5 Sync Check", 5),
4326 HDSPM_SYNC_CHECK("AES6 Sync Check", 6),
4327 HDSPM_SYNC_CHECK("AES7 Sync Check", 7),
4328 HDSPM_SYNC_CHECK("AES8 Sync Check", 8),
4329 HDSPM_SYNC_CHECK("TCO Sync Check", 9),
4330 HDSPM_SYNC_CHECK("SYNC IN Sync Check", 10),
4331 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4332 HDSPM_AUTOSYNC_SAMPLE_RATE("AES1 Frequency", 1),
4333 HDSPM_AUTOSYNC_SAMPLE_RATE("AES2 Frequency", 2),
4334 HDSPM_AUTOSYNC_SAMPLE_RATE("AES3 Frequency", 3),
4335 HDSPM_AUTOSYNC_SAMPLE_RATE("AES4 Frequency", 4),
4336 HDSPM_AUTOSYNC_SAMPLE_RATE("AES5 Frequency", 5),
4337 HDSPM_AUTOSYNC_SAMPLE_RATE("AES6 Frequency", 6),
4338 HDSPM_AUTOSYNC_SAMPLE_RATE("AES7 Frequency", 7),
4339 HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8),
4340 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9),
4341 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004342 HDSPM_LINE_OUT("Line Out", 0),
4343 HDSPM_EMPHASIS("Emphasis", 0),
4344 HDSPM_DOLBY("Non Audio", 0),
4345 HDSPM_PROFESSIONAL("Professional", 0),
4346 HDSPM_C_TMS("Clear Track Marker", 0),
4347 HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
4348 HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
4349};
4350
Adrian Knoth0dca1792011-01-26 19:32:14 +01004351
4352
4353/* Control elements for the optional TCO module */
4354static struct snd_kcontrol_new snd_hdspm_controls_tco[] = {
4355 HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0),
4356 HDSPM_TCO_PULL("TCO Pull", 0),
4357 HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0),
4358 HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0),
4359 HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0),
4360 HDSPM_TCO_WORD_TERM("TCO Word Term", 0)
4361};
4362
4363
Takashi Iwai98274f02005-11-17 14:52:34 +01004364static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
Takashi Iwai763f3562005-06-03 11:25:34 +02004365
4366
Takashi Iwai98274f02005-11-17 14:52:34 +01004367static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004368{
4369 int i;
4370
Adrian Knoth0dca1792011-01-26 19:32:14 +01004371 for (i = hdspm->ds_out_channels; i < hdspm->ss_out_channels; ++i) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004372 if (hdspm->system_sample_rate > 48000) {
4373 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004374 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
4375 SNDRV_CTL_ELEM_ACCESS_READ |
4376 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004377 } else {
4378 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004379 SNDRV_CTL_ELEM_ACCESS_READWRITE |
4380 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004381 }
4382 snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
Adrian Knoth0dca1792011-01-26 19:32:14 +01004383 SNDRV_CTL_EVENT_MASK_INFO,
4384 &hdspm->playback_mixer_ctls[i]->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02004385 }
4386
4387 return 0;
4388}
4389
4390
Adrian Knoth0dca1792011-01-26 19:32:14 +01004391static int snd_hdspm_create_controls(struct snd_card *card,
4392 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004393{
4394 unsigned int idx, limit;
4395 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01004396 struct snd_kcontrol *kctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004397 struct snd_kcontrol_new *list = NULL;
Takashi Iwai763f3562005-06-03 11:25:34 +02004398
Adrian Knoth0dca1792011-01-26 19:32:14 +01004399 switch (hdspm->io_type) {
4400 case MADI:
4401 list = snd_hdspm_controls_madi;
4402 limit = ARRAY_SIZE(snd_hdspm_controls_madi);
4403 break;
4404 case MADIface:
4405 list = snd_hdspm_controls_madiface;
4406 limit = ARRAY_SIZE(snd_hdspm_controls_madiface);
4407 break;
4408 case AIO:
4409 list = snd_hdspm_controls_aio;
4410 limit = ARRAY_SIZE(snd_hdspm_controls_aio);
4411 break;
4412 case RayDAT:
4413 list = snd_hdspm_controls_raydat;
4414 limit = ARRAY_SIZE(snd_hdspm_controls_raydat);
4415 break;
4416 case AES32:
4417 list = snd_hdspm_controls_aes32;
4418 limit = ARRAY_SIZE(snd_hdspm_controls_aes32);
4419 break;
4420 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004421
Adrian Knoth0dca1792011-01-26 19:32:14 +01004422 if (NULL != list) {
4423 for (idx = 0; idx < limit; idx++) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004424 err = snd_ctl_add(card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004425 snd_ctl_new1(&list[idx], hdspm));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004426 if (err < 0)
4427 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004428 }
4429 }
4430
Takashi Iwai763f3562005-06-03 11:25:34 +02004431
Adrian Knoth0dca1792011-01-26 19:32:14 +01004432 /* create simple 1:1 playback mixer controls */
Takashi Iwai763f3562005-06-03 11:25:34 +02004433 snd_hdspm_playback_mixer.name = "Chn";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004434 if (hdspm->system_sample_rate >= 128000) {
4435 limit = hdspm->qs_out_channels;
4436 } else if (hdspm->system_sample_rate >= 64000) {
4437 limit = hdspm->ds_out_channels;
4438 } else {
4439 limit = hdspm->ss_out_channels;
4440 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004441 for (idx = 0; idx < limit; ++idx) {
4442 snd_hdspm_playback_mixer.index = idx + 1;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004443 kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm);
4444 err = snd_ctl_add(card, kctl);
4445 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004446 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004447 hdspm->playback_mixer_ctls[idx] = kctl;
4448 }
4449
Adrian Knoth0dca1792011-01-26 19:32:14 +01004450
4451 if (hdspm->tco) {
4452 /* add tco control elements */
4453 list = snd_hdspm_controls_tco;
4454 limit = ARRAY_SIZE(snd_hdspm_controls_tco);
4455 for (idx = 0; idx < limit; idx++) {
4456 err = snd_ctl_add(card,
4457 snd_ctl_new1(&list[idx], hdspm));
4458 if (err < 0)
4459 return err;
4460 }
4461 }
4462
Takashi Iwai763f3562005-06-03 11:25:34 +02004463 return 0;
4464}
4465
4466/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01004467 /proc interface
Takashi Iwai763f3562005-06-03 11:25:34 +02004468 ------------------------------------------------------------*/
4469
4470static void
Remy Bruno3cee5a62006-10-16 12:46:32 +02004471snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
4472 struct snd_info_buffer *buffer)
Takashi Iwai763f3562005-06-03 11:25:34 +02004473{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004474 struct hdspm *hdspm = entry->private_data;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004475 unsigned int status, status2, control, freq;
4476
Takashi Iwai763f3562005-06-03 11:25:34 +02004477 char *pref_sync_ref;
4478 char *autosync_ref;
4479 char *system_clock_mode;
Takashi Iwai763f3562005-06-03 11:25:34 +02004480 char *insel;
Takashi Iwai763f3562005-06-03 11:25:34 +02004481 int x, x2;
4482
Adrian Knoth0dca1792011-01-26 19:32:14 +01004483 /* TCO stuff */
4484 int a, ltc, frames, seconds, minutes, hours;
4485 unsigned int period;
4486 u64 freq_const = 0;
4487 u32 rate;
4488
Takashi Iwai763f3562005-06-03 11:25:34 +02004489 status = hdspm_read(hdspm, HDSPM_statusRegister);
4490 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004491 control = hdspm->control_register;
4492 freq = hdspm_read(hdspm, HDSPM_timecodeRegister);
Takashi Iwai763f3562005-06-03 11:25:34 +02004493
4494 snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004495 hdspm->card_name, hdspm->card->number + 1,
4496 hdspm->firmware_rev,
4497 (status2 & HDSPM_version0) |
4498 (status2 & HDSPM_version1) | (status2 &
4499 HDSPM_version2));
4500
4501 snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n",
4502 (hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF,
4503 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF);
Takashi Iwai763f3562005-06-03 11:25:34 +02004504
4505 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004506 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
Takashi Iwai763f3562005-06-03 11:25:34 +02004507
4508 snd_iprintf(buffer, "--- System ---\n");
4509
4510 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004511 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4512 status & HDSPM_audioIRQPending,
4513 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4514 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4515 hdspm->irq_count);
Takashi Iwai763f3562005-06-03 11:25:34 +02004516 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004517 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4518 "estimated= %ld (bytes)\n",
4519 ((status & HDSPM_BufferID) ? 1 : 0),
4520 (status & HDSPM_BufferPositionMask),
4521 (status & HDSPM_BufferPositionMask) %
4522 (2 * (int)hdspm->period_bytes),
4523 ((status & HDSPM_BufferPositionMask) - 64) %
4524 (2 * (int)hdspm->period_bytes),
4525 (long) hdspm_hw_pointer(hdspm) * 4);
Takashi Iwai763f3562005-06-03 11:25:34 +02004526
4527 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004528 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4529 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4530 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4531 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4532 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
Takashi Iwai763f3562005-06-03 11:25:34 +02004533 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004534 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4535 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4536 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4537 snd_iprintf(buffer,
4538 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4539 "status2=0x%x\n",
4540 hdspm->control_register, hdspm->control2_register,
4541 status, status2);
4542 if (status & HDSPM_tco_detect) {
4543 snd_iprintf(buffer, "TCO module detected.\n");
4544 a = hdspm_read(hdspm, HDSPM_RD_TCO+4);
4545 if (a & HDSPM_TCO1_LTC_Input_valid) {
4546 snd_iprintf(buffer, " LTC valid, ");
4547 switch (a & (HDSPM_TCO1_LTC_Format_LSB |
4548 HDSPM_TCO1_LTC_Format_MSB)) {
4549 case 0:
4550 snd_iprintf(buffer, "24 fps, ");
4551 break;
4552 case HDSPM_TCO1_LTC_Format_LSB:
4553 snd_iprintf(buffer, "25 fps, ");
4554 break;
4555 case HDSPM_TCO1_LTC_Format_MSB:
4556 snd_iprintf(buffer, "29.97 fps, ");
4557 break;
4558 default:
4559 snd_iprintf(buffer, "30 fps, ");
4560 break;
4561 }
4562 if (a & HDSPM_TCO1_set_drop_frame_flag) {
4563 snd_iprintf(buffer, "drop frame\n");
4564 } else {
4565 snd_iprintf(buffer, "full frame\n");
4566 }
4567 } else {
4568 snd_iprintf(buffer, " no LTC\n");
4569 }
4570 if (a & HDSPM_TCO1_Video_Input_Format_NTSC) {
4571 snd_iprintf(buffer, " Video: NTSC\n");
4572 } else if (a & HDSPM_TCO1_Video_Input_Format_PAL) {
4573 snd_iprintf(buffer, " Video: PAL\n");
4574 } else {
4575 snd_iprintf(buffer, " No video\n");
4576 }
4577 if (a & HDSPM_TCO1_TCO_lock) {
4578 snd_iprintf(buffer, " Sync: lock\n");
4579 } else {
4580 snd_iprintf(buffer, " Sync: no lock\n");
4581 }
4582
4583 switch (hdspm->io_type) {
4584 case MADI:
4585 case AES32:
4586 freq_const = 110069313433624ULL;
4587 break;
4588 case RayDAT:
4589 case AIO:
4590 freq_const = 104857600000000ULL;
4591 break;
4592 case MADIface:
4593 break; /* no TCO possible */
4594 }
4595
4596 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
4597 snd_iprintf(buffer, " period: %u\n", period);
4598
4599
4600 /* rate = freq_const/period; */
4601 rate = div_u64(freq_const, period);
4602
4603 if (control & HDSPM_QuadSpeed) {
4604 rate *= 4;
4605 } else if (control & HDSPM_DoubleSpeed) {
4606 rate *= 2;
4607 }
4608
4609 snd_iprintf(buffer, " Frequency: %u Hz\n",
4610 (unsigned int) rate);
4611
4612 ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
4613 frames = ltc & 0xF;
4614 ltc >>= 4;
4615 frames += (ltc & 0x3) * 10;
4616 ltc >>= 4;
4617 seconds = ltc & 0xF;
4618 ltc >>= 4;
4619 seconds += (ltc & 0x7) * 10;
4620 ltc >>= 4;
4621 minutes = ltc & 0xF;
4622 ltc >>= 4;
4623 minutes += (ltc & 0x7) * 10;
4624 ltc >>= 4;
4625 hours = ltc & 0xF;
4626 ltc >>= 4;
4627 hours += (ltc & 0x3) * 10;
4628 snd_iprintf(buffer,
4629 " LTC In: %02d:%02d:%02d:%02d\n",
4630 hours, minutes, seconds, frames);
4631
4632 } else {
4633 snd_iprintf(buffer, "No TCO module detected.\n");
4634 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004635
4636 snd_iprintf(buffer, "--- Settings ---\n");
4637
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004638 x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
Adrian Knoth0dca1792011-01-26 19:32:14 +01004639 HDSPM_LatencyMask));
Takashi Iwai763f3562005-06-03 11:25:34 +02004640
4641 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004642 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4643 x, (unsigned long) hdspm->period_bytes);
Takashi Iwai763f3562005-06-03 11:25:34 +02004644
Adrian Knoth0dca1792011-01-26 19:32:14 +01004645 snd_iprintf(buffer, "Line out: %s\n",
4646 (hdspm->control_register & HDSPM_LineOut) ? "on " : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004647
4648 switch (hdspm->control_register & HDSPM_InputMask) {
4649 case HDSPM_InputOptical:
4650 insel = "Optical";
4651 break;
4652 case HDSPM_InputCoaxial:
4653 insel = "Coaxial";
4654 break;
4655 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01004656 insel = "Unkown";
Takashi Iwai763f3562005-06-03 11:25:34 +02004657 }
4658
Takashi Iwai763f3562005-06-03 11:25:34 +02004659 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004660 "ClearTrackMarker = %s, Transmit in %s Channel Mode, "
4661 "Auto Input %s\n",
4662 (hdspm->control_register & HDSPM_clr_tms) ? "on" : "off",
4663 (hdspm->control_register & HDSPM_TX_64ch) ? "64" : "56",
4664 (hdspm->control_register & HDSPM_AutoInp) ? "on" : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004665
Adrian Knoth0dca1792011-01-26 19:32:14 +01004666
Remy Bruno3cee5a62006-10-16 12:46:32 +02004667 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
Adrian Knoth0dca1792011-01-26 19:32:14 +01004668 system_clock_mode = "AutoSync";
Remy Bruno3cee5a62006-10-16 12:46:32 +02004669 else
Takashi Iwai763f3562005-06-03 11:25:34 +02004670 system_clock_mode = "Master";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004671 snd_iprintf(buffer, "AutoSync Reference: %s\n", system_clock_mode);
Takashi Iwai763f3562005-06-03 11:25:34 +02004672
4673 switch (hdspm_pref_sync_ref(hdspm)) {
4674 case HDSPM_SYNC_FROM_WORD:
4675 pref_sync_ref = "Word Clock";
4676 break;
4677 case HDSPM_SYNC_FROM_MADI:
4678 pref_sync_ref = "MADI Sync";
4679 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004680 case HDSPM_SYNC_FROM_TCO:
4681 pref_sync_ref = "TCO";
4682 break;
4683 case HDSPM_SYNC_FROM_SYNC_IN:
4684 pref_sync_ref = "Sync In";
4685 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004686 default:
4687 pref_sync_ref = "XXXX Clock";
4688 break;
4689 }
4690 snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004691 pref_sync_ref);
Takashi Iwai763f3562005-06-03 11:25:34 +02004692
4693 snd_iprintf(buffer, "System Clock Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004694 hdspm->system_sample_rate);
Takashi Iwai763f3562005-06-03 11:25:34 +02004695
4696
4697 snd_iprintf(buffer, "--- Status:\n");
4698
4699 x = status & HDSPM_madiSync;
4700 x2 = status2 & HDSPM_wcSync;
4701
4702 snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004703 (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
4704 "NoLock",
4705 (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
4706 "NoLock");
Takashi Iwai763f3562005-06-03 11:25:34 +02004707
4708 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004709 case HDSPM_AUTOSYNC_FROM_SYNC_IN:
4710 autosync_ref = "Sync In";
4711 break;
4712 case HDSPM_AUTOSYNC_FROM_TCO:
4713 autosync_ref = "TCO";
4714 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004715 case HDSPM_AUTOSYNC_FROM_WORD:
4716 autosync_ref = "Word Clock";
4717 break;
4718 case HDSPM_AUTOSYNC_FROM_MADI:
4719 autosync_ref = "MADI Sync";
4720 break;
4721 case HDSPM_AUTOSYNC_FROM_NONE:
4722 autosync_ref = "Input not valid";
4723 break;
4724 default:
4725 autosync_ref = "---";
4726 break;
4727 }
4728 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004729 "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
4730 autosync_ref, hdspm_external_sample_rate(hdspm),
4731 (status & HDSPM_madiFreqMask) >> 22,
4732 (status2 & HDSPM_wcFreqMask) >> 5);
Takashi Iwai763f3562005-06-03 11:25:34 +02004733
4734 snd_iprintf(buffer, "Input: %s, Mode=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004735 (status & HDSPM_AB_int) ? "Coax" : "Optical",
4736 (status & HDSPM_RX_64ch) ? "64 channels" :
4737 "56 channels");
Takashi Iwai763f3562005-06-03 11:25:34 +02004738
4739 snd_iprintf(buffer, "\n");
4740}
4741
Remy Bruno3cee5a62006-10-16 12:46:32 +02004742static void
4743snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
4744 struct snd_info_buffer *buffer)
4745{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004746 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004747 unsigned int status;
4748 unsigned int status2;
4749 unsigned int timecode;
4750 int pref_syncref;
4751 char *autosync_ref;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004752 int x;
4753
4754 status = hdspm_read(hdspm, HDSPM_statusRegister);
4755 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
4756 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
4757
4758 snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
4759 hdspm->card_name, hdspm->card->number + 1,
4760 hdspm->firmware_rev);
4761
4762 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
4763 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
4764
4765 snd_iprintf(buffer, "--- System ---\n");
4766
4767 snd_iprintf(buffer,
4768 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4769 status & HDSPM_audioIRQPending,
4770 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4771 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4772 hdspm->irq_count);
4773 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004774 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4775 "estimated= %ld (bytes)\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004776 ((status & HDSPM_BufferID) ? 1 : 0),
4777 (status & HDSPM_BufferPositionMask),
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004778 (status & HDSPM_BufferPositionMask) %
4779 (2 * (int)hdspm->period_bytes),
4780 ((status & HDSPM_BufferPositionMask) - 64) %
4781 (2 * (int)hdspm->period_bytes),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004782 (long) hdspm_hw_pointer(hdspm) * 4);
4783
4784 snd_iprintf(buffer,
4785 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4786 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4787 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4788 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4789 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
4790 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004791 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4792 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4793 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4794 snd_iprintf(buffer,
4795 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4796 "status2=0x%x\n",
4797 hdspm->control_register, hdspm->control2_register,
4798 status, status2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02004799
4800 snd_iprintf(buffer, "--- Settings ---\n");
4801
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004802 x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
Adrian Knoth0dca1792011-01-26 19:32:14 +01004803 HDSPM_LatencyMask));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004804
4805 snd_iprintf(buffer,
4806 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4807 x, (unsigned long) hdspm->period_bytes);
4808
Adrian Knoth0dca1792011-01-26 19:32:14 +01004809 snd_iprintf(buffer, "Line out: %s\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004810 (hdspm->
Adrian Knoth0dca1792011-01-26 19:32:14 +01004811 control_register & HDSPM_LineOut) ? "on " : "off");
Remy Bruno3cee5a62006-10-16 12:46:32 +02004812
4813 snd_iprintf(buffer,
4814 "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
4815 (hdspm->
4816 control_register & HDSPM_clr_tms) ? "on" : "off",
4817 (hdspm->
4818 control_register & HDSPM_Emphasis) ? "on" : "off",
4819 (hdspm->
4820 control_register & HDSPM_Dolby) ? "on" : "off");
4821
Remy Bruno3cee5a62006-10-16 12:46:32 +02004822
4823 pref_syncref = hdspm_pref_sync_ref(hdspm);
4824 if (pref_syncref == 0)
4825 snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
4826 else
4827 snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
4828 pref_syncref);
4829
4830 snd_iprintf(buffer, "System Clock Frequency: %d\n",
4831 hdspm->system_sample_rate);
4832
4833 snd_iprintf(buffer, "Double speed: %s\n",
4834 hdspm->control_register & HDSPM_DS_DoubleWire?
4835 "Double wire" : "Single wire");
4836 snd_iprintf(buffer, "Quad speed: %s\n",
4837 hdspm->control_register & HDSPM_QS_DoubleWire?
4838 "Double wire" :
4839 hdspm->control_register & HDSPM_QS_QuadWire?
4840 "Quad wire" : "Single wire");
4841
4842 snd_iprintf(buffer, "--- Status:\n");
4843
4844 snd_iprintf(buffer, "Word: %s Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004845 (status & HDSPM_AES32_wcLock) ? "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004846 HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004847
4848 for (x = 0; x < 8; x++) {
4849 snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004850 x+1,
4851 (status2 & (HDSPM_LockAES >> x)) ?
Adrian Knoth0dca1792011-01-26 19:32:14 +01004852 "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004853 HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004854 }
4855
4856 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004857 case HDSPM_AES32_AUTOSYNC_FROM_NONE:
4858 autosync_ref = "None"; break;
4859 case HDSPM_AES32_AUTOSYNC_FROM_WORD:
4860 autosync_ref = "Word Clock"; break;
4861 case HDSPM_AES32_AUTOSYNC_FROM_AES1:
4862 autosync_ref = "AES1"; break;
4863 case HDSPM_AES32_AUTOSYNC_FROM_AES2:
4864 autosync_ref = "AES2"; break;
4865 case HDSPM_AES32_AUTOSYNC_FROM_AES3:
4866 autosync_ref = "AES3"; break;
4867 case HDSPM_AES32_AUTOSYNC_FROM_AES4:
4868 autosync_ref = "AES4"; break;
4869 case HDSPM_AES32_AUTOSYNC_FROM_AES5:
4870 autosync_ref = "AES5"; break;
4871 case HDSPM_AES32_AUTOSYNC_FROM_AES6:
4872 autosync_ref = "AES6"; break;
4873 case HDSPM_AES32_AUTOSYNC_FROM_AES7:
4874 autosync_ref = "AES7"; break;
4875 case HDSPM_AES32_AUTOSYNC_FROM_AES8:
4876 autosync_ref = "AES8"; break;
4877 default:
4878 autosync_ref = "---"; break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004879 }
4880 snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
4881
4882 snd_iprintf(buffer, "\n");
4883}
4884
Adrian Knoth0dca1792011-01-26 19:32:14 +01004885static void
4886snd_hdspm_proc_read_raydat(struct snd_info_entry *entry,
4887 struct snd_info_buffer *buffer)
4888{
4889 struct hdspm *hdspm = entry->private_data;
4890 unsigned int status1, status2, status3, control, i;
4891 unsigned int lock, sync;
4892
4893 status1 = hdspm_read(hdspm, HDSPM_RD_STATUS_1); /* s1 */
4894 status2 = hdspm_read(hdspm, HDSPM_RD_STATUS_2); /* freq */
4895 status3 = hdspm_read(hdspm, HDSPM_RD_STATUS_3); /* s2 */
4896
4897 control = hdspm->control_register;
4898
4899 snd_iprintf(buffer, "STATUS1: 0x%08x\n", status1);
4900 snd_iprintf(buffer, "STATUS2: 0x%08x\n", status2);
4901 snd_iprintf(buffer, "STATUS3: 0x%08x\n", status3);
4902
4903
4904 snd_iprintf(buffer, "\n*** CLOCK MODE\n\n");
4905
4906 snd_iprintf(buffer, "Clock mode : %s\n",
4907 (hdspm_system_clock_mode(hdspm) == 0) ? "master" : "slave");
4908 snd_iprintf(buffer, "System frequency: %d Hz\n",
4909 hdspm_get_system_sample_rate(hdspm));
4910
4911 snd_iprintf(buffer, "\n*** INPUT STATUS\n\n");
4912
4913 lock = 0x1;
4914 sync = 0x100;
4915
4916 for (i = 0; i < 8; i++) {
4917 snd_iprintf(buffer, "s1_input %d: Lock %d, Sync %d, Freq %s\n",
4918 i,
4919 (status1 & lock) ? 1 : 0,
4920 (status1 & sync) ? 1 : 0,
4921 texts_freq[(status2 >> (i * 4)) & 0xF]);
4922
4923 lock = lock<<1;
4924 sync = sync<<1;
4925 }
4926
4927 snd_iprintf(buffer, "WC input: Lock %d, Sync %d, Freq %s\n",
4928 (status1 & 0x1000000) ? 1 : 0,
4929 (status1 & 0x2000000) ? 1 : 0,
4930 texts_freq[(status1 >> 16) & 0xF]);
4931
4932 snd_iprintf(buffer, "TCO input: Lock %d, Sync %d, Freq %s\n",
4933 (status1 & 0x4000000) ? 1 : 0,
4934 (status1 & 0x8000000) ? 1 : 0,
4935 texts_freq[(status1 >> 20) & 0xF]);
4936
4937 snd_iprintf(buffer, "SYNC IN: Lock %d, Sync %d, Freq %s\n",
4938 (status3 & 0x400) ? 1 : 0,
4939 (status3 & 0x800) ? 1 : 0,
4940 texts_freq[(status2 >> 12) & 0xF]);
4941
4942}
4943
Remy Bruno3cee5a62006-10-16 12:46:32 +02004944#ifdef CONFIG_SND_DEBUG
4945static void
Adrian Knoth0dca1792011-01-26 19:32:14 +01004946snd_hdspm_proc_read_debug(struct snd_info_entry *entry,
Remy Bruno3cee5a62006-10-16 12:46:32 +02004947 struct snd_info_buffer *buffer)
4948{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004949 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004950
4951 int j,i;
4952
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004953 for (i = 0; i < 256 /* 1024*64 */; i += j) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004954 snd_iprintf(buffer, "0x%08X: ", i);
4955 for (j = 0; j < 16; j += 4)
4956 snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
4957 snd_iprintf(buffer, "\n");
4958 }
4959}
4960#endif
4961
4962
Adrian Knoth0dca1792011-01-26 19:32:14 +01004963static void snd_hdspm_proc_ports_in(struct snd_info_entry *entry,
4964 struct snd_info_buffer *buffer)
4965{
4966 struct hdspm *hdspm = entry->private_data;
4967 int i;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004968
Adrian Knoth0dca1792011-01-26 19:32:14 +01004969 snd_iprintf(buffer, "# generated by hdspm\n");
4970
4971 for (i = 0; i < hdspm->max_channels_in; i++) {
4972 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_in[i]);
4973 }
4974}
4975
4976static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry,
4977 struct snd_info_buffer *buffer)
4978{
4979 struct hdspm *hdspm = entry->private_data;
4980 int i;
4981
4982 snd_iprintf(buffer, "# generated by hdspm\n");
4983
4984 for (i = 0; i < hdspm->max_channels_out; i++) {
4985 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_out[i]);
4986 }
4987}
4988
4989
4990static void __devinit snd_hdspm_proc_init(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004991{
Takashi Iwai98274f02005-11-17 14:52:34 +01004992 struct snd_info_entry *entry;
Takashi Iwai763f3562005-06-03 11:25:34 +02004993
Adrian Knoth0dca1792011-01-26 19:32:14 +01004994 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) {
4995 switch (hdspm->io_type) {
4996 case AES32:
4997 snd_info_set_text_ops(entry, hdspm,
4998 snd_hdspm_proc_read_aes32);
4999 break;
5000 case MADI:
5001 snd_info_set_text_ops(entry, hdspm,
5002 snd_hdspm_proc_read_madi);
5003 break;
5004 case MADIface:
5005 /* snd_info_set_text_ops(entry, hdspm,
5006 snd_hdspm_proc_read_madiface); */
5007 break;
5008 case RayDAT:
5009 snd_info_set_text_ops(entry, hdspm,
5010 snd_hdspm_proc_read_raydat);
5011 break;
5012 case AIO:
5013 break;
5014 }
5015 }
5016
5017 if (!snd_card_proc_new(hdspm->card, "ports.in", &entry)) {
5018 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_in);
5019 }
5020
5021 if (!snd_card_proc_new(hdspm->card, "ports.out", &entry)) {
5022 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_out);
5023 }
5024
Remy Bruno3cee5a62006-10-16 12:46:32 +02005025#ifdef CONFIG_SND_DEBUG
5026 /* debug file to read all hdspm registers */
5027 if (!snd_card_proc_new(hdspm->card, "debug", &entry))
5028 snd_info_set_text_ops(entry, hdspm,
5029 snd_hdspm_proc_read_debug);
5030#endif
Takashi Iwai763f3562005-06-03 11:25:34 +02005031}
5032
5033/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005034 hdspm intitialize
Takashi Iwai763f3562005-06-03 11:25:34 +02005035 ------------------------------------------------------------*/
5036
Takashi Iwai98274f02005-11-17 14:52:34 +01005037static int snd_hdspm_set_defaults(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005038{
Takashi Iwai763f3562005-06-03 11:25:34 +02005039 /* ASSUMPTION: hdspm->lock is either held, or there is no need to
Joe Perches561de312007-12-18 13:13:47 +01005040 hold it (e.g. during module initialization).
Adrian Knoth0dca1792011-01-26 19:32:14 +01005041 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005042
5043 /* set defaults: */
5044
Adrian Knoth0dca1792011-01-26 19:32:14 +01005045 hdspm->settings_register = 0;
5046
5047 switch (hdspm->io_type) {
5048 case MADI:
5049 case MADIface:
5050 hdspm->control_register =
5051 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5052 break;
5053
5054 case RayDAT:
5055 case AIO:
5056 hdspm->settings_register = 0x1 + 0x1000;
5057 /* Magic values are: LAT_0, LAT_2, Master, freq1, tx64ch, inp_0,
5058 * line_out */
5059 hdspm->control_register =
5060 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5061 break;
5062
5063 case AES32:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005064 hdspm->control_register =
5065 HDSPM_ClockModeMaster | /* Master Cloack Mode on */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005066 hdspm_encode_latency(7) | /* latency max=8192samples */
Remy Bruno3cee5a62006-10-16 12:46:32 +02005067 HDSPM_SyncRef0 | /* AES1 is syncclock */
5068 HDSPM_LineOut | /* Analog output in */
5069 HDSPM_Professional; /* Professional mode */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005070 break;
5071 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005072
5073 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5074
Adrian Knoth0dca1792011-01-26 19:32:14 +01005075 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005076 /* No control2 register for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005077#ifdef SNDRV_BIG_ENDIAN
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005078 hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
Takashi Iwai763f3562005-06-03 11:25:34 +02005079#else
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005080 hdspm->control2_register = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005081#endif
5082
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005083 hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
5084 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005085 hdspm_compute_period_size(hdspm);
5086
5087 /* silence everything */
5088
5089 all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
5090
Adrian Knoth0dca1792011-01-26 19:32:14 +01005091 if (hdspm->io_type == AIO || hdspm->io_type == RayDAT) {
5092 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
Takashi Iwai763f3562005-06-03 11:25:34 +02005093 }
5094
5095 /* set a default rate so that the channel map is set up. */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005096 hdspm_set_rate(hdspm, 48000, 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02005097
5098 return 0;
5099}
5100
5101
5102/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005103 interrupt
Takashi Iwai763f3562005-06-03 11:25:34 +02005104 ------------------------------------------------------------*/
5105
David Howells7d12e782006-10-05 14:55:46 +01005106static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02005107{
Takashi Iwai98274f02005-11-17 14:52:34 +01005108 struct hdspm *hdspm = (struct hdspm *) dev_id;
Takashi Iwai763f3562005-06-03 11:25:34 +02005109 unsigned int status;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005110 int i, audio, midi, schedule = 0;
5111 /* cycles_t now; */
Takashi Iwai763f3562005-06-03 11:25:34 +02005112
5113 status = hdspm_read(hdspm, HDSPM_statusRegister);
5114
5115 audio = status & HDSPM_audioIRQPending;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005116 midi = status & (HDSPM_midi0IRQPending | HDSPM_midi1IRQPending |
5117 HDSPM_midi2IRQPending | HDSPM_midi3IRQPending);
Takashi Iwai763f3562005-06-03 11:25:34 +02005118
Adrian Knoth0dca1792011-01-26 19:32:14 +01005119 /* now = get_cycles(); */
5120 /**
5121 * LAT_2..LAT_0 period counter (win) counter (mac)
5122 * 6 4096 ~256053425 ~514672358
5123 * 5 2048 ~128024983 ~257373821
5124 * 4 1024 ~64023706 ~128718089
5125 * 3 512 ~32005945 ~64385999
5126 * 2 256 ~16003039 ~32260176
5127 * 1 128 ~7998738 ~16194507
5128 * 0 64 ~3998231 ~8191558
5129 **/
5130 /*
5131 snd_printk(KERN_INFO "snd_hdspm_interrupt %llu @ %llx\n",
5132 now-hdspm->last_interrupt, status & 0xFFC0);
5133 hdspm->last_interrupt = now;
5134 */
5135
5136 if (!audio && !midi)
Takashi Iwai763f3562005-06-03 11:25:34 +02005137 return IRQ_NONE;
5138
5139 hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
5140 hdspm->irq_count++;
5141
Takashi Iwai763f3562005-06-03 11:25:34 +02005142
5143 if (audio) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005144 if (hdspm->capture_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005145 snd_pcm_period_elapsed(hdspm->capture_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005146
5147 if (hdspm->playback_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005148 snd_pcm_period_elapsed(hdspm->playback_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005149 }
5150
Adrian Knoth0dca1792011-01-26 19:32:14 +01005151 if (midi) {
5152 i = 0;
5153 while (i < hdspm->midiPorts) {
5154 if ((hdspm_read(hdspm,
5155 hdspm->midi[i].statusIn) & 0xff) &&
5156 (status & hdspm->midi[i].irq)) {
5157 /* we disable interrupts for this input until
5158 * processing is done
5159 */
5160 hdspm->control_register &= ~hdspm->midi[i].ie;
5161 hdspm_write(hdspm, HDSPM_controlRegister,
5162 hdspm->control_register);
5163 hdspm->midi[i].pending = 1;
5164 schedule = 1;
5165 }
5166
5167 i++;
5168 }
5169
5170 if (schedule)
5171 tasklet_hi_schedule(&hdspm->midi_tasklet);
Takashi Iwai763f3562005-06-03 11:25:34 +02005172 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005173
Takashi Iwai763f3562005-06-03 11:25:34 +02005174 return IRQ_HANDLED;
5175}
5176
5177/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005178 pcm interface
Takashi Iwai763f3562005-06-03 11:25:34 +02005179 ------------------------------------------------------------*/
5180
5181
Adrian Knoth0dca1792011-01-26 19:32:14 +01005182static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream
5183 *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005184{
Takashi Iwai98274f02005-11-17 14:52:34 +01005185 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005186 return hdspm_hw_pointer(hdspm);
5187}
5188
Takashi Iwai763f3562005-06-03 11:25:34 +02005189
Takashi Iwai98274f02005-11-17 14:52:34 +01005190static int snd_hdspm_reset(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005191{
Takashi Iwai98274f02005-11-17 14:52:34 +01005192 struct snd_pcm_runtime *runtime = substream->runtime;
5193 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5194 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005195
5196 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5197 other = hdspm->capture_substream;
5198 else
5199 other = hdspm->playback_substream;
5200
5201 if (hdspm->running)
5202 runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
5203 else
5204 runtime->status->hw_ptr = 0;
5205 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005206 struct snd_pcm_substream *s;
5207 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01005208 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005209 if (s == other) {
5210 oruntime->status->hw_ptr =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005211 runtime->status->hw_ptr;
Takashi Iwai763f3562005-06-03 11:25:34 +02005212 break;
5213 }
5214 }
5215 }
5216 return 0;
5217}
5218
Takashi Iwai98274f02005-11-17 14:52:34 +01005219static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
5220 struct snd_pcm_hw_params *params)
Takashi Iwai763f3562005-06-03 11:25:34 +02005221{
Takashi Iwai98274f02005-11-17 14:52:34 +01005222 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005223 int err;
5224 int i;
5225 pid_t this_pid;
5226 pid_t other_pid;
Takashi Iwai763f3562005-06-03 11:25:34 +02005227
5228 spin_lock_irq(&hdspm->lock);
5229
5230 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5231 this_pid = hdspm->playback_pid;
5232 other_pid = hdspm->capture_pid;
5233 } else {
5234 this_pid = hdspm->capture_pid;
5235 other_pid = hdspm->playback_pid;
5236 }
5237
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005238 if (other_pid > 0 && this_pid != other_pid) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005239
5240 /* The other stream is open, and not by the same
5241 task as this one. Make sure that the parameters
5242 that matter are the same.
Adrian Knoth0dca1792011-01-26 19:32:14 +01005243 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005244
5245 if (params_rate(params) != hdspm->system_sample_rate) {
5246 spin_unlock_irq(&hdspm->lock);
5247 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005248 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005249 return -EBUSY;
5250 }
5251
5252 if (params_period_size(params) != hdspm->period_bytes / 4) {
5253 spin_unlock_irq(&hdspm->lock);
5254 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005255 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005256 return -EBUSY;
5257 }
5258
5259 }
5260 /* We're fine. */
5261 spin_unlock_irq(&hdspm->lock);
5262
5263 /* how to make sure that the rate matches an externally-set one ? */
5264
5265 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005266 err = hdspm_set_rate(hdspm, params_rate(params), 0);
5267 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005268 snd_printk(KERN_INFO "err on hdspm_set_rate: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005269 spin_unlock_irq(&hdspm->lock);
5270 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005271 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005272 return err;
5273 }
5274 spin_unlock_irq(&hdspm->lock);
5275
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005276 err = hdspm_set_interrupt_interval(hdspm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005277 params_period_size(params));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005278 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005279 snd_printk(KERN_INFO "err on hdspm_set_interrupt_interval: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005280 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005281 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005282 return err;
5283 }
5284
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005285 /* Memory allocation, takashi's method, dont know if we should
5286 * spinlock
5287 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005288 /* malloc all buffer even if not enabled to get sure */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005289 /* Update for MADI rev 204: we need to allocate for all channels,
5290 * otherwise it doesn't work at 96kHz */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005291
Takashi Iwai763f3562005-06-03 11:25:34 +02005292 err =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005293 snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
5294 if (err < 0) {
5295 snd_printk(KERN_INFO "err on snd_pcm_lib_malloc_pages: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005296 return err;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005297 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005298
Takashi Iwai763f3562005-06-03 11:25:34 +02005299 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5300
Takashi Iwai77a23f22008-08-21 13:00:13 +02005301 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferOut,
Takashi Iwai763f3562005-06-03 11:25:34 +02005302 params_channels(params));
5303
5304 for (i = 0; i < params_channels(params); ++i)
5305 snd_hdspm_enable_out(hdspm, i, 1);
5306
5307 hdspm->playback_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005308 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005309 snd_printdd("Allocated sample buffer for playback at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005310 hdspm->playback_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005311 } else {
Takashi Iwai77a23f22008-08-21 13:00:13 +02005312 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn,
Takashi Iwai763f3562005-06-03 11:25:34 +02005313 params_channels(params));
5314
5315 for (i = 0; i < params_channels(params); ++i)
5316 snd_hdspm_enable_in(hdspm, i, 1);
5317
5318 hdspm->capture_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005319 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005320 snd_printdd("Allocated sample buffer for capture at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005321 hdspm->capture_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005322 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005323
Remy Bruno3cee5a62006-10-16 12:46:32 +02005324 /*
5325 snd_printdd("Allocated sample buffer for %s at 0x%08X\n",
5326 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5327 "playback" : "capture",
Takashi Iwai77a23f22008-08-21 13:00:13 +02005328 snd_pcm_sgbuf_get_addr(substream, 0));
Adrian Knoth0dca1792011-01-26 19:32:14 +01005329 */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005330 /*
Adrian Knoth0dca1792011-01-26 19:32:14 +01005331 snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n",
5332 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5333 "playback" : "capture",
5334 params_rate(params), params_channels(params),
5335 params_buffer_size(params));
5336 */
5337
5338
5339 /* Switch to native float format if requested */
5340 if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) {
5341 if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT))
5342 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE float format.\n");
5343
5344 hdspm->control_register |= HDSPe_FLOAT_FORMAT;
5345 } else if (SNDRV_PCM_FORMAT_S32_LE == params_format(params)) {
5346 if (hdspm->control_register & HDSPe_FLOAT_FORMAT)
5347 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE integer format.\n");
5348
5349 hdspm->control_register &= ~HDSPe_FLOAT_FORMAT;
5350 }
5351 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5352
Takashi Iwai763f3562005-06-03 11:25:34 +02005353 return 0;
5354}
5355
Takashi Iwai98274f02005-11-17 14:52:34 +01005356static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005357{
5358 int i;
Takashi Iwai98274f02005-11-17 14:52:34 +01005359 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005360
5361 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5362
Adrian Knoth0dca1792011-01-26 19:32:14 +01005363 /* params_channels(params) should be enough,
Takashi Iwai763f3562005-06-03 11:25:34 +02005364 but to get sure in case of error */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005365 for (i = 0; i < hdspm->max_channels_out; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005366 snd_hdspm_enable_out(hdspm, i, 0);
5367
5368 hdspm->playback_buffer = NULL;
5369 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005370 for (i = 0; i < hdspm->max_channels_in; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005371 snd_hdspm_enable_in(hdspm, i, 0);
5372
5373 hdspm->capture_buffer = NULL;
5374
5375 }
5376
5377 snd_pcm_lib_free_pages(substream);
5378
5379 return 0;
5380}
5381
Adrian Knoth0dca1792011-01-26 19:32:14 +01005382
Takashi Iwai98274f02005-11-17 14:52:34 +01005383static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005384 struct snd_pcm_channel_info *info)
Takashi Iwai763f3562005-06-03 11:25:34 +02005385{
Takashi Iwai98274f02005-11-17 14:52:34 +01005386 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005387
Adrian Knoth0dca1792011-01-26 19:32:14 +01005388 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5389 if (snd_BUG_ON(info->channel >= hdspm->max_channels_out)) {
5390 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel out of range (%d)\n", info->channel);
5391 return -EINVAL;
5392 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005393
Adrian Knoth0dca1792011-01-26 19:32:14 +01005394 if (hdspm->channel_map_out[info->channel] < 0) {
5395 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel %d mapped out\n", info->channel);
5396 return -EINVAL;
5397 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005398
Adrian Knoth0dca1792011-01-26 19:32:14 +01005399 info->offset = hdspm->channel_map_out[info->channel] *
5400 HDSPM_CHANNEL_BUFFER_BYTES;
5401 } else {
5402 if (snd_BUG_ON(info->channel >= hdspm->max_channels_in)) {
5403 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel out of range (%d)\n", info->channel);
5404 return -EINVAL;
5405 }
5406
5407 if (hdspm->channel_map_in[info->channel] < 0) {
5408 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel %d mapped out\n", info->channel);
5409 return -EINVAL;
5410 }
5411
5412 info->offset = hdspm->channel_map_in[info->channel] *
5413 HDSPM_CHANNEL_BUFFER_BYTES;
5414 }
5415
Takashi Iwai763f3562005-06-03 11:25:34 +02005416 info->first = 0;
5417 info->step = 32;
5418 return 0;
5419}
5420
Adrian Knoth0dca1792011-01-26 19:32:14 +01005421
Takashi Iwai98274f02005-11-17 14:52:34 +01005422static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005423 unsigned int cmd, void *arg)
Takashi Iwai763f3562005-06-03 11:25:34 +02005424{
5425 switch (cmd) {
5426 case SNDRV_PCM_IOCTL1_RESET:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005427 return snd_hdspm_reset(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005428
5429 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Adrian Knoth0dca1792011-01-26 19:32:14 +01005430 {
5431 struct snd_pcm_channel_info *info = arg;
5432 return snd_hdspm_channel_info(substream, info);
5433 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005434 default:
5435 break;
5436 }
5437
5438 return snd_pcm_lib_ioctl(substream, cmd, arg);
5439}
5440
Takashi Iwai98274f02005-11-17 14:52:34 +01005441static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
Takashi Iwai763f3562005-06-03 11:25:34 +02005442{
Takashi Iwai98274f02005-11-17 14:52:34 +01005443 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5444 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005445 int running;
5446
5447 spin_lock(&hdspm->lock);
5448 running = hdspm->running;
5449 switch (cmd) {
5450 case SNDRV_PCM_TRIGGER_START:
5451 running |= 1 << substream->stream;
5452 break;
5453 case SNDRV_PCM_TRIGGER_STOP:
5454 running &= ~(1 << substream->stream);
5455 break;
5456 default:
5457 snd_BUG();
5458 spin_unlock(&hdspm->lock);
5459 return -EINVAL;
5460 }
5461 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5462 other = hdspm->capture_substream;
5463 else
5464 other = hdspm->playback_substream;
5465
5466 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005467 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01005468 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005469 if (s == other) {
5470 snd_pcm_trigger_done(s, substream);
5471 if (cmd == SNDRV_PCM_TRIGGER_START)
5472 running |= 1 << s->stream;
5473 else
5474 running &= ~(1 << s->stream);
5475 goto _ok;
5476 }
5477 }
5478 if (cmd == SNDRV_PCM_TRIGGER_START) {
5479 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005480 && substream->stream ==
5481 SNDRV_PCM_STREAM_CAPTURE)
Takashi Iwai763f3562005-06-03 11:25:34 +02005482 hdspm_silence_playback(hdspm);
5483 } else {
5484 if (running &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01005485 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Takashi Iwai763f3562005-06-03 11:25:34 +02005486 hdspm_silence_playback(hdspm);
5487 }
5488 } else {
5489 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
5490 hdspm_silence_playback(hdspm);
5491 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005492_ok:
Takashi Iwai763f3562005-06-03 11:25:34 +02005493 snd_pcm_trigger_done(substream, substream);
5494 if (!hdspm->running && running)
5495 hdspm_start_audio(hdspm);
5496 else if (hdspm->running && !running)
5497 hdspm_stop_audio(hdspm);
5498 hdspm->running = running;
5499 spin_unlock(&hdspm->lock);
5500
5501 return 0;
5502}
5503
Takashi Iwai98274f02005-11-17 14:52:34 +01005504static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005505{
5506 return 0;
5507}
5508
Adrian Knoth0dca1792011-01-26 19:32:14 +01005509static unsigned int period_sizes_old[] = {
5510 64, 128, 256, 512, 1024, 2048, 4096
5511};
5512
5513static unsigned int period_sizes_new[] = {
5514 32, 64, 128, 256, 512, 1024, 2048, 4096
5515};
5516
5517/* RayDAT and AIO always have a buffer of 16384 samples per channel */
5518static unsigned int raydat_aio_buffer_sizes[] = {
5519 16384
5520};
Takashi Iwai763f3562005-06-03 11:25:34 +02005521
Takashi Iwai98274f02005-11-17 14:52:34 +01005522static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005523 .info = (SNDRV_PCM_INFO_MMAP |
5524 SNDRV_PCM_INFO_MMAP_VALID |
5525 SNDRV_PCM_INFO_NONINTERLEAVED |
5526 SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
5527 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5528 .rates = (SNDRV_PCM_RATE_32000 |
5529 SNDRV_PCM_RATE_44100 |
5530 SNDRV_PCM_RATE_48000 |
5531 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005532 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5533 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ),
Takashi Iwai763f3562005-06-03 11:25:34 +02005534 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005535 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005536 .channels_min = 1,
5537 .channels_max = HDSPM_MAX_CHANNELS,
5538 .buffer_bytes_max =
5539 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
5540 .period_bytes_min = (64 * 4),
Adrian Knoth0dca1792011-01-26 19:32:14 +01005541 .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005542 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005543 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005544 .fifo_size = 0
5545};
5546
Takashi Iwai98274f02005-11-17 14:52:34 +01005547static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005548 .info = (SNDRV_PCM_INFO_MMAP |
5549 SNDRV_PCM_INFO_MMAP_VALID |
5550 SNDRV_PCM_INFO_NONINTERLEAVED |
5551 SNDRV_PCM_INFO_SYNC_START),
5552 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5553 .rates = (SNDRV_PCM_RATE_32000 |
5554 SNDRV_PCM_RATE_44100 |
5555 SNDRV_PCM_RATE_48000 |
5556 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005557 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5558 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
Takashi Iwai763f3562005-06-03 11:25:34 +02005559 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005560 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005561 .channels_min = 1,
5562 .channels_max = HDSPM_MAX_CHANNELS,
5563 .buffer_bytes_max =
5564 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
5565 .period_bytes_min = (64 * 4),
Adrian Knoth0dca1792011-01-26 19:32:14 +01005566 .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005567 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005568 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005569 .fifo_size = 0
5570};
5571
Adrian Knoth0dca1792011-01-26 19:32:14 +01005572static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_old = {
5573 .count = ARRAY_SIZE(period_sizes_old),
5574 .list = period_sizes_old,
Takashi Iwai763f3562005-06-03 11:25:34 +02005575 .mask = 0
5576};
5577
Adrian Knoth0dca1792011-01-26 19:32:14 +01005578static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_new = {
5579 .count = ARRAY_SIZE(period_sizes_new),
5580 .list = period_sizes_new,
5581 .mask = 0
5582};
Takashi Iwai763f3562005-06-03 11:25:34 +02005583
Adrian Knoth0dca1792011-01-26 19:32:14 +01005584static struct snd_pcm_hw_constraint_list hw_constraints_raydat_io_buffer = {
5585 .count = ARRAY_SIZE(raydat_aio_buffer_sizes),
5586 .list = raydat_aio_buffer_sizes,
5587 .mask = 0
5588};
5589
5590static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
5591 struct snd_pcm_hw_rule *rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005592{
Takashi Iwai98274f02005-11-17 14:52:34 +01005593 struct hdspm *hdspm = rule->private;
5594 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005595 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005596 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005597 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5598
Adrian Knoth0dca1792011-01-26 19:32:14 +01005599 if (r->min > 96000 && r->max <= 192000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005600 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005601 .min = hdspm->qs_in_channels,
5602 .max = hdspm->qs_in_channels,
5603 .integer = 1,
5604 };
5605 return snd_interval_refine(c, &t);
5606 } else if (r->min > 48000 && r->max <= 96000) {
5607 struct snd_interval t = {
5608 .min = hdspm->ds_in_channels,
5609 .max = hdspm->ds_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005610 .integer = 1,
5611 };
5612 return snd_interval_refine(c, &t);
5613 } else if (r->max < 64000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005614 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005615 .min = hdspm->ss_in_channels,
5616 .max = hdspm->ss_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005617 .integer = 1,
5618 };
5619 return snd_interval_refine(c, &t);
5620 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005621
Takashi Iwai763f3562005-06-03 11:25:34 +02005622 return 0;
5623}
5624
Adrian Knoth0dca1792011-01-26 19:32:14 +01005625static int snd_hdspm_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
Takashi Iwai98274f02005-11-17 14:52:34 +01005626 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005627{
Takashi Iwai98274f02005-11-17 14:52:34 +01005628 struct hdspm *hdspm = rule->private;
5629 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005630 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005631 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005632 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5633
Adrian Knoth0dca1792011-01-26 19:32:14 +01005634 if (r->min > 96000 && r->max <= 192000) {
5635 struct snd_interval t = {
5636 .min = hdspm->qs_out_channels,
5637 .max = hdspm->qs_out_channels,
5638 .integer = 1,
5639 };
5640 return snd_interval_refine(c, &t);
5641 } else if (r->min > 48000 && r->max <= 96000) {
5642 struct snd_interval t = {
5643 .min = hdspm->ds_out_channels,
5644 .max = hdspm->ds_out_channels,
5645 .integer = 1,
5646 };
5647 return snd_interval_refine(c, &t);
5648 } else if (r->max < 64000) {
5649 struct snd_interval t = {
5650 .min = hdspm->ss_out_channels,
5651 .max = hdspm->ss_out_channels,
5652 .integer = 1,
5653 };
5654 return snd_interval_refine(c, &t);
5655 } else {
5656 }
5657 return 0;
5658}
5659
5660static int snd_hdspm_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
5661 struct snd_pcm_hw_rule * rule)
5662{
5663 struct hdspm *hdspm = rule->private;
5664 struct snd_interval *c =
5665 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5666 struct snd_interval *r =
5667 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5668
5669 if (c->min >= hdspm->ss_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005670 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005671 .min = 32000,
5672 .max = 48000,
5673 .integer = 1,
5674 };
5675 return snd_interval_refine(r, &t);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005676 } else if (c->max <= hdspm->qs_in_channels) {
5677 struct snd_interval t = {
5678 .min = 128000,
5679 .max = 192000,
5680 .integer = 1,
5681 };
5682 return snd_interval_refine(r, &t);
5683 } else if (c->max <= hdspm->ds_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005684 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005685 .min = 64000,
5686 .max = 96000,
5687 .integer = 1,
5688 };
Takashi Iwai763f3562005-06-03 11:25:34 +02005689 return snd_interval_refine(r, &t);
5690 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005691
5692 return 0;
5693}
5694static int snd_hdspm_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
5695 struct snd_pcm_hw_rule *rule)
5696{
5697 struct hdspm *hdspm = rule->private;
5698 struct snd_interval *c =
5699 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5700 struct snd_interval *r =
5701 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5702
5703 if (c->min >= hdspm->ss_out_channels) {
5704 struct snd_interval t = {
5705 .min = 32000,
5706 .max = 48000,
5707 .integer = 1,
5708 };
5709 return snd_interval_refine(r, &t);
5710 } else if (c->max <= hdspm->qs_out_channels) {
5711 struct snd_interval t = {
5712 .min = 128000,
5713 .max = 192000,
5714 .integer = 1,
5715 };
5716 return snd_interval_refine(r, &t);
5717 } else if (c->max <= hdspm->ds_out_channels) {
5718 struct snd_interval t = {
5719 .min = 64000,
5720 .max = 96000,
5721 .integer = 1,
5722 };
5723 return snd_interval_refine(r, &t);
5724 }
5725
Takashi Iwai763f3562005-06-03 11:25:34 +02005726 return 0;
5727}
5728
Adrian Knoth0dca1792011-01-26 19:32:14 +01005729static int snd_hdspm_hw_rule_in_channels(struct snd_pcm_hw_params *params,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005730 struct snd_pcm_hw_rule *rule)
5731{
5732 unsigned int list[3];
5733 struct hdspm *hdspm = rule->private;
5734 struct snd_interval *c = hw_param_interval(params,
5735 SNDRV_PCM_HW_PARAM_CHANNELS);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005736
5737 list[0] = hdspm->qs_in_channels;
5738 list[1] = hdspm->ds_in_channels;
5739 list[2] = hdspm->ss_in_channels;
5740 return snd_interval_list(c, 3, list, 0);
5741}
5742
5743static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params,
5744 struct snd_pcm_hw_rule *rule)
5745{
5746 unsigned int list[3];
5747 struct hdspm *hdspm = rule->private;
5748 struct snd_interval *c = hw_param_interval(params,
5749 SNDRV_PCM_HW_PARAM_CHANNELS);
5750
5751 list[0] = hdspm->qs_out_channels;
5752 list[1] = hdspm->ds_out_channels;
5753 list[2] = hdspm->ss_out_channels;
5754 return snd_interval_list(c, 3, list, 0);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005755}
5756
5757
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005758static unsigned int hdspm_aes32_sample_rates[] = {
5759 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000
5760};
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005761
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005762static struct snd_pcm_hw_constraint_list
5763hdspm_hw_constraints_aes32_sample_rates = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005764 .count = ARRAY_SIZE(hdspm_aes32_sample_rates),
5765 .list = hdspm_aes32_sample_rates,
5766 .mask = 0
5767};
5768
Takashi Iwai98274f02005-11-17 14:52:34 +01005769static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005770{
Takashi Iwai98274f02005-11-17 14:52:34 +01005771 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5772 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02005773
Takashi Iwai763f3562005-06-03 11:25:34 +02005774 spin_lock_irq(&hdspm->lock);
5775
5776 snd_pcm_set_sync(substream);
5777
Adrian Knoth0dca1792011-01-26 19:32:14 +01005778
Takashi Iwai763f3562005-06-03 11:25:34 +02005779 runtime->hw = snd_hdspm_playback_subinfo;
5780
5781 if (hdspm->capture_substream == NULL)
5782 hdspm_stop_audio(hdspm);
5783
5784 hdspm->playback_pid = current->pid;
5785 hdspm->playback_substream = substream;
5786
5787 spin_unlock_irq(&hdspm->lock);
5788
5789 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
5790
Adrian Knoth0dca1792011-01-26 19:32:14 +01005791 switch (hdspm->io_type) {
5792 case AIO:
5793 case RayDAT:
5794 snd_pcm_hw_constraint_list(runtime, 0,
5795 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5796 &hw_constraints_period_sizes_new);
5797 snd_pcm_hw_constraint_list(runtime, 0,
5798 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
5799 &hw_constraints_raydat_io_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005800
Adrian Knoth0dca1792011-01-26 19:32:14 +01005801 break;
5802
5803 default:
5804 snd_pcm_hw_constraint_list(runtime, 0,
5805 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5806 &hw_constraints_period_sizes_old);
5807 }
5808
5809 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005810 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
5811 &hdspm_hw_constraints_aes32_sample_rates);
5812 } else {
5813 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005814 snd_hdspm_hw_rule_out_channels, hdspm,
5815 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005816 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005817 snd_hdspm_hw_rule_out_channels_rate, hdspm,
5818 SNDRV_PCM_HW_PARAM_RATE, -1);
Takashi Iwai763f3562005-06-03 11:25:34 +02005819
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005820 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005821 snd_hdspm_hw_rule_rate_out_channels, hdspm,
5822 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005823 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005824 return 0;
5825}
5826
Takashi Iwai98274f02005-11-17 14:52:34 +01005827static int snd_hdspm_playback_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005828{
Takashi Iwai98274f02005-11-17 14:52:34 +01005829 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005830
5831 spin_lock_irq(&hdspm->lock);
5832
5833 hdspm->playback_pid = -1;
5834 hdspm->playback_substream = NULL;
5835
5836 spin_unlock_irq(&hdspm->lock);
5837
5838 return 0;
5839}
5840
5841
Takashi Iwai98274f02005-11-17 14:52:34 +01005842static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005843{
Takashi Iwai98274f02005-11-17 14:52:34 +01005844 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5845 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02005846
5847 spin_lock_irq(&hdspm->lock);
5848 snd_pcm_set_sync(substream);
5849 runtime->hw = snd_hdspm_capture_subinfo;
5850
5851 if (hdspm->playback_substream == NULL)
5852 hdspm_stop_audio(hdspm);
5853
5854 hdspm->capture_pid = current->pid;
5855 hdspm->capture_substream = substream;
5856
5857 spin_unlock_irq(&hdspm->lock);
5858
5859 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005860 switch (hdspm->io_type) {
5861 case AIO:
5862 case RayDAT:
5863 snd_pcm_hw_constraint_list(runtime, 0,
5864 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5865 &hw_constraints_period_sizes_new);
5866 snd_pcm_hw_constraint_list(runtime, 0,
5867 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
5868 &hw_constraints_raydat_io_buffer);
5869 break;
5870
5871 default:
5872 snd_pcm_hw_constraint_list(runtime, 0,
5873 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5874 &hw_constraints_period_sizes_old);
5875 }
5876
5877 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005878 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
5879 &hdspm_hw_constraints_aes32_sample_rates);
5880 } else {
5881 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005882 snd_hdspm_hw_rule_in_channels, hdspm,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005883 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
5884 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005885 snd_hdspm_hw_rule_in_channels_rate, hdspm,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005886 SNDRV_PCM_HW_PARAM_RATE, -1);
Takashi Iwai763f3562005-06-03 11:25:34 +02005887
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005888 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005889 snd_hdspm_hw_rule_rate_in_channels, hdspm,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005890 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
5891 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005892 return 0;
5893}
5894
Takashi Iwai98274f02005-11-17 14:52:34 +01005895static int snd_hdspm_capture_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005896{
Takashi Iwai98274f02005-11-17 14:52:34 +01005897 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005898
5899 spin_lock_irq(&hdspm->lock);
5900
5901 hdspm->capture_pid = -1;
5902 hdspm->capture_substream = NULL;
5903
5904 spin_unlock_irq(&hdspm->lock);
5905 return 0;
5906}
5907
Adrian Knoth0dca1792011-01-26 19:32:14 +01005908static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
Takashi Iwai763f3562005-06-03 11:25:34 +02005909{
Adrian Knoth0dca1792011-01-26 19:32:14 +01005910 /* we have nothing to initialize but the call is required */
5911 return 0;
5912}
5913
5914static inline int copy_u32_le(void __user *dest, void __iomem *src)
5915{
5916 u32 val = readl(src);
5917 return copy_to_user(dest, &val, 4);
5918}
5919
5920static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
5921 unsigned int cmd, unsigned long __user arg)
5922{
5923 void __user *argp = (void __user *)arg;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005924 struct hdspm *hdspm = hw->private_data;
Takashi Iwai98274f02005-11-17 14:52:34 +01005925 struct hdspm_mixer_ioctl mixer;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005926 struct hdspm_config info;
5927 struct hdspm_status status;
Takashi Iwai98274f02005-11-17 14:52:34 +01005928 struct hdspm_version hdspm_version;
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005929 struct hdspm_peak_rms *levels;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005930 struct hdspm_ltc ltc;
5931 unsigned int statusregister;
5932 long unsigned int s;
5933 int i = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005934
5935 switch (cmd) {
5936
Takashi Iwai763f3562005-06-03 11:25:34 +02005937 case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005938 levels = &hdspm->peak_rms;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005939 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005940 levels->input_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005941 readl(hdspm->iobase +
5942 HDSPM_MADI_INPUT_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005943 levels->playback_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005944 readl(hdspm->iobase +
5945 HDSPM_MADI_PLAYBACK_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005946 levels->output_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005947 readl(hdspm->iobase +
5948 HDSPM_MADI_OUTPUT_PEAK + i*4);
5949
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005950 levels->input_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005951 ((uint64_t) readl(hdspm->iobase +
5952 HDSPM_MADI_INPUT_RMS_H + i*4) << 32) |
5953 (uint64_t) readl(hdspm->iobase +
5954 HDSPM_MADI_INPUT_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005955 levels->playback_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005956 ((uint64_t)readl(hdspm->iobase +
5957 HDSPM_MADI_PLAYBACK_RMS_H+i*4) << 32) |
5958 (uint64_t)readl(hdspm->iobase +
5959 HDSPM_MADI_PLAYBACK_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005960 levels->output_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005961 ((uint64_t)readl(hdspm->iobase +
5962 HDSPM_MADI_OUTPUT_RMS_H + i*4) << 32) |
5963 (uint64_t)readl(hdspm->iobase +
5964 HDSPM_MADI_OUTPUT_RMS_L + i*4);
5965 }
5966
5967 if (hdspm->system_sample_rate > 96000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005968 levels->speed = qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005969 } else if (hdspm->system_sample_rate > 48000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005970 levels->speed = ds;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005971 } else {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005972 levels->speed = ss;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005973 }
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005974 levels->status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005975
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005976 s = copy_to_user(argp, levels, sizeof(struct hdspm_peak_rms));
Adrian Knoth0dca1792011-01-26 19:32:14 +01005977 if (0 != s) {
5978 /* snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu
5979 [Levels]\n", sizeof(struct hdspm_peak_rms), s);
5980 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005981 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005982 }
5983 break;
5984
5985 case SNDRV_HDSPM_IOCTL_GET_LTC:
5986 ltc.ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
5987 i = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
5988 if (i & HDSPM_TCO1_LTC_Input_valid) {
5989 switch (i & (HDSPM_TCO1_LTC_Format_LSB |
5990 HDSPM_TCO1_LTC_Format_MSB)) {
5991 case 0:
5992 ltc.format = fps_24;
5993 break;
5994 case HDSPM_TCO1_LTC_Format_LSB:
5995 ltc.format = fps_25;
5996 break;
5997 case HDSPM_TCO1_LTC_Format_MSB:
5998 ltc.format = fps_2997;
5999 break;
6000 default:
6001 ltc.format = 30;
6002 break;
6003 }
6004 if (i & HDSPM_TCO1_set_drop_frame_flag) {
6005 ltc.frame = drop_frame;
6006 } else {
6007 ltc.frame = full_frame;
6008 }
6009 } else {
6010 ltc.format = format_invalid;
6011 ltc.frame = frame_invalid;
6012 }
6013 if (i & HDSPM_TCO1_Video_Input_Format_NTSC) {
6014 ltc.input_format = ntsc;
6015 } else if (i & HDSPM_TCO1_Video_Input_Format_PAL) {
6016 ltc.input_format = pal;
6017 } else {
6018 ltc.input_format = no_video;
6019 }
6020
6021 s = copy_to_user(argp, &ltc, sizeof(struct hdspm_ltc));
6022 if (0 != s) {
6023 /*
6024 snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */
Takashi Iwai763f3562005-06-03 11:25:34 +02006025 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006026 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006027
6028 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02006029
Adrian Knoth0dca1792011-01-26 19:32:14 +01006030 case SNDRV_HDSPM_IOCTL_GET_CONFIG:
Takashi Iwai763f3562005-06-03 11:25:34 +02006031
6032 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006033 info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
6034 info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006035
6036 info.system_sample_rate = hdspm->system_sample_rate;
6037 info.autosync_sample_rate =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006038 hdspm_external_sample_rate(hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006039 info.system_clock_mode = hdspm_system_clock_mode(hdspm);
6040 info.clock_source = hdspm_clock_source(hdspm);
6041 info.autosync_ref = hdspm_autosync_ref(hdspm);
6042 info.line_out = hdspm_line_out(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006043 info.passthru = 0;
6044 spin_unlock_irq(&hdspm->lock);
6045 if (copy_to_user((void __user *) arg, &info, sizeof(info)))
6046 return -EFAULT;
6047 break;
6048
Adrian Knoth0dca1792011-01-26 19:32:14 +01006049 case SNDRV_HDSPM_IOCTL_GET_STATUS:
6050 status.card_type = hdspm->io_type;
6051
6052 status.autosync_source = hdspm_autosync_ref(hdspm);
6053
6054 status.card_clock = 110069313433624ULL;
6055 status.master_period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
6056
6057 switch (hdspm->io_type) {
6058 case MADI:
6059 case MADIface:
6060 status.card_specific.madi.sync_wc =
6061 hdspm_wc_sync_check(hdspm);
6062 status.card_specific.madi.sync_madi =
6063 hdspm_madi_sync_check(hdspm);
6064 status.card_specific.madi.sync_tco =
6065 hdspm_tco_sync_check(hdspm);
6066 status.card_specific.madi.sync_in =
6067 hdspm_sync_in_sync_check(hdspm);
6068
6069 statusregister =
6070 hdspm_read(hdspm, HDSPM_statusRegister);
6071 status.card_specific.madi.madi_input =
6072 (statusregister & HDSPM_AB_int) ? 1 : 0;
6073 status.card_specific.madi.channel_format =
6074 (statusregister & HDSPM_TX_64ch) ? 1 : 0;
6075 /* TODO: Mac driver sets it when f_s>48kHz */
6076 status.card_specific.madi.frame_format = 0;
6077
6078 default:
6079 break;
6080 }
6081
6082 if (copy_to_user((void __user *) arg, &status, sizeof(status)))
6083 return -EFAULT;
6084
6085
6086 break;
6087
Takashi Iwai763f3562005-06-03 11:25:34 +02006088 case SNDRV_HDSPM_IOCTL_GET_VERSION:
Adrian Knoth0dca1792011-01-26 19:32:14 +01006089 hdspm_version.card_type = hdspm->io_type;
6090 strncpy(hdspm_version.cardname, hdspm->card_name,
6091 sizeof(hdspm_version.cardname));
6092 hdspm_version.serial = (hdspm_read(hdspm,
6093 HDSPM_midiStatusIn0)>>8) & 0xFFFFFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02006094 hdspm_version.firmware_rev = hdspm->firmware_rev;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006095 hdspm_version.addons = 0;
6096 if (hdspm->tco)
6097 hdspm_version.addons |= HDSPM_ADDON_TCO;
6098
Takashi Iwai763f3562005-06-03 11:25:34 +02006099 if (copy_to_user((void __user *) arg, &hdspm_version,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006100 sizeof(hdspm_version)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006101 return -EFAULT;
6102 break;
6103
6104 case SNDRV_HDSPM_IOCTL_GET_MIXER:
6105 if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer)))
6106 return -EFAULT;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006107 if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006108 sizeof(struct hdspm_mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006109 return -EFAULT;
6110 break;
6111
6112 default:
6113 return -EINVAL;
6114 }
6115 return 0;
6116}
6117
Takashi Iwai98274f02005-11-17 14:52:34 +01006118static struct snd_pcm_ops snd_hdspm_playback_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006119 .open = snd_hdspm_playback_open,
6120 .close = snd_hdspm_playback_release,
6121 .ioctl = snd_hdspm_ioctl,
6122 .hw_params = snd_hdspm_hw_params,
6123 .hw_free = snd_hdspm_hw_free,
6124 .prepare = snd_hdspm_prepare,
6125 .trigger = snd_hdspm_trigger,
6126 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006127 .page = snd_pcm_sgbuf_ops_page,
6128};
6129
Takashi Iwai98274f02005-11-17 14:52:34 +01006130static struct snd_pcm_ops snd_hdspm_capture_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006131 .open = snd_hdspm_capture_open,
6132 .close = snd_hdspm_capture_release,
6133 .ioctl = snd_hdspm_ioctl,
6134 .hw_params = snd_hdspm_hw_params,
6135 .hw_free = snd_hdspm_hw_free,
6136 .prepare = snd_hdspm_prepare,
6137 .trigger = snd_hdspm_trigger,
6138 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006139 .page = snd_pcm_sgbuf_ops_page,
6140};
6141
Takashi Iwai98274f02005-11-17 14:52:34 +01006142static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
6143 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006144{
Takashi Iwai98274f02005-11-17 14:52:34 +01006145 struct snd_hwdep *hw;
Takashi Iwai763f3562005-06-03 11:25:34 +02006146 int err;
6147
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006148 err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw);
6149 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006150 return err;
6151
6152 hdspm->hwdep = hw;
6153 hw->private_data = hdspm;
6154 strcpy(hw->name, "HDSPM hwdep interface");
6155
Adrian Knoth0dca1792011-01-26 19:32:14 +01006156 hw->ops.open = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006157 hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006158 hw->ops.release = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006159
6160 return 0;
6161}
6162
6163
6164/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01006165 memory interface
Takashi Iwai763f3562005-06-03 11:25:34 +02006166 ------------------------------------------------------------*/
Adrian Knoth0dca1792011-01-26 19:32:14 +01006167static int __devinit snd_hdspm_preallocate_memory(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006168{
6169 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01006170 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006171 size_t wanted;
6172
6173 pcm = hdspm->pcm;
6174
Remy Bruno3cee5a62006-10-16 12:46:32 +02006175 wanted = HDSPM_DMA_AREA_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02006176
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006177 err =
Takashi Iwai763f3562005-06-03 11:25:34 +02006178 snd_pcm_lib_preallocate_pages_for_all(pcm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006179 SNDRV_DMA_TYPE_DEV_SG,
Takashi Iwai763f3562005-06-03 11:25:34 +02006180 snd_dma_pci_data(hdspm->pci),
6181 wanted,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006182 wanted);
6183 if (err < 0) {
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006184 snd_printdd("Could not preallocate %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006185
6186 return err;
6187 } else
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006188 snd_printdd(" Preallocated %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006189
6190 return 0;
6191}
6192
Adrian Knoth0dca1792011-01-26 19:32:14 +01006193
6194static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +02006195 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02006196 unsigned int reg, int channels)
6197{
6198 int i;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006199
6200 /* continuous memory segment */
Takashi Iwai763f3562005-06-03 11:25:34 +02006201 for (i = 0; i < (channels * 16); i++)
6202 hdspm_write(hdspm, reg + 4 * i,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006203 snd_pcm_sgbuf_get_addr(substream, 4096 * i));
Takashi Iwai763f3562005-06-03 11:25:34 +02006204}
6205
Adrian Knoth0dca1792011-01-26 19:32:14 +01006206
Takashi Iwai763f3562005-06-03 11:25:34 +02006207/* ------------- ALSA Devices ---------------------------- */
Takashi Iwai98274f02005-11-17 14:52:34 +01006208static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006209 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006210{
Takashi Iwai98274f02005-11-17 14:52:34 +01006211 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006212 int err;
6213
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006214 err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm);
6215 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006216 return err;
6217
6218 hdspm->pcm = pcm;
6219 pcm->private_data = hdspm;
6220 strcpy(pcm->name, hdspm->card_name);
6221
6222 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
6223 &snd_hdspm_playback_ops);
6224 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
6225 &snd_hdspm_capture_ops);
6226
6227 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
6228
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006229 err = snd_hdspm_preallocate_memory(hdspm);
6230 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006231 return err;
6232
6233 return 0;
6234}
6235
Takashi Iwai98274f02005-11-17 14:52:34 +01006236static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006237{
6238 snd_hdspm_flush_midi_input(hdspm, 0);
6239 snd_hdspm_flush_midi_input(hdspm, 1);
6240}
6241
Takashi Iwai98274f02005-11-17 14:52:34 +01006242static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
6243 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006244{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006245 int err, i;
Takashi Iwai763f3562005-06-03 11:25:34 +02006246
6247 snd_printdd("Create card...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006248 err = snd_hdspm_create_pcm(card, hdspm);
6249 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006250 return err;
6251
Adrian Knoth0dca1792011-01-26 19:32:14 +01006252 i = 0;
6253 while (i < hdspm->midiPorts) {
6254 err = snd_hdspm_create_midi(card, hdspm, i);
6255 if (err < 0) {
6256 return err;
6257 }
6258 i++;
6259 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006260
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006261 err = snd_hdspm_create_controls(card, hdspm);
6262 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006263 return err;
6264
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006265 err = snd_hdspm_create_hwdep(card, hdspm);
6266 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006267 return err;
6268
6269 snd_printdd("proc init...\n");
6270 snd_hdspm_proc_init(hdspm);
6271
6272 hdspm->system_sample_rate = -1;
6273 hdspm->last_external_sample_rate = -1;
6274 hdspm->last_internal_sample_rate = -1;
6275 hdspm->playback_pid = -1;
6276 hdspm->capture_pid = -1;
6277 hdspm->capture_substream = NULL;
6278 hdspm->playback_substream = NULL;
6279
6280 snd_printdd("Set defaults...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006281 err = snd_hdspm_set_defaults(hdspm);
6282 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006283 return err;
6284
6285 snd_printdd("Update mixer controls...\n");
6286 hdspm_update_simple_mixer_controls(hdspm);
6287
6288 snd_printdd("Initializeing complete ???\n");
6289
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006290 err = snd_card_register(card);
6291 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006292 snd_printk(KERN_ERR "HDSPM: error registering card\n");
6293 return err;
6294 }
6295
6296 snd_printdd("... yes now\n");
6297
6298 return 0;
6299}
6300
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006301static int __devinit snd_hdspm_create(struct snd_card *card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006302 struct hdspm *hdspm) {
6303
Takashi Iwai763f3562005-06-03 11:25:34 +02006304 struct pci_dev *pci = hdspm->pci;
6305 int err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006306 unsigned long io_extent;
6307
6308 hdspm->irq = -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02006309 hdspm->card = card;
6310
6311 spin_lock_init(&hdspm->lock);
6312
Takashi Iwai763f3562005-06-03 11:25:34 +02006313 pci_read_config_word(hdspm->pci,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006314 PCI_CLASS_REVISION, &hdspm->firmware_rev);
Remy Bruno3cee5a62006-10-16 12:46:32 +02006315
Takashi Iwai763f3562005-06-03 11:25:34 +02006316 strcpy(card->mixername, "Xilinx FPGA");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006317 strcpy(card->driver, "HDSPM");
6318
6319 switch (hdspm->firmware_rev) {
6320 case HDSPM_MADI_REV:
6321 hdspm->io_type = MADI;
6322 hdspm->card_name = "RME MADI";
6323 hdspm->midiPorts = 3;
6324 break;
6325 case HDSPM_RAYDAT_REV:
6326 hdspm->io_type = RayDAT;
6327 hdspm->card_name = "RME RayDAT";
6328 hdspm->midiPorts = 2;
6329 break;
6330 case HDSPM_AIO_REV:
6331 hdspm->io_type = AIO;
6332 hdspm->card_name = "RME AIO";
6333 hdspm->midiPorts = 1;
6334 break;
6335 case HDSPM_MADIFACE_REV:
6336 hdspm->io_type = MADIface;
6337 hdspm->card_name = "RME MADIface";
6338 hdspm->midiPorts = 1;
6339 break;
6340 case HDSPM_AES_REV:
6341 hdspm->io_type = AES32;
6342 hdspm->card_name = "RME AES32";
6343 hdspm->midiPorts = 2;
6344 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02006345 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006346
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006347 err = pci_enable_device(pci);
6348 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006349 return err;
6350
6351 pci_set_master(hdspm->pci);
6352
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006353 err = pci_request_regions(pci, "hdspm");
6354 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006355 return err;
6356
6357 hdspm->port = pci_resource_start(pci, 0);
6358 io_extent = pci_resource_len(pci, 0);
6359
6360 snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006361 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006362
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006363 hdspm->iobase = ioremap_nocache(hdspm->port, io_extent);
6364 if (!hdspm->iobase) {
6365 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006366 "unable to remap region 0x%lx-0x%lx\n",
6367 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006368 return -EBUSY;
6369 }
6370 snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006371 (unsigned long)hdspm->iobase, hdspm->port,
6372 hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006373
6374 if (request_irq(pci->irq, snd_hdspm_interrupt,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006375 IRQF_SHARED, "hdspm", hdspm)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006376 snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
6377 return -EBUSY;
6378 }
6379
6380 snd_printdd("use IRQ %d\n", pci->irq);
6381
6382 hdspm->irq = pci->irq;
Takashi Iwai763f3562005-06-03 11:25:34 +02006383
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006384 snd_printdd("kmalloc Mixer memory of %zd Bytes\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006385 sizeof(struct hdspm_mixer));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006386 hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL);
6387 if (!hdspm->mixer) {
6388 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006389 "unable to kmalloc Mixer memory of %d Bytes\n",
6390 (int)sizeof(struct hdspm_mixer));
Takashi Iwai763f3562005-06-03 11:25:34 +02006391 return err;
6392 }
6393
Adrian Knoth0dca1792011-01-26 19:32:14 +01006394 hdspm->port_names_in = NULL;
6395 hdspm->port_names_out = NULL;
6396
6397 switch (hdspm->io_type) {
6398 case AES32:
6399 break;
6400
6401 case MADI:
6402 case MADIface:
6403 hdspm->ss_in_channels = hdspm->ss_out_channels =
6404 MADI_SS_CHANNELS;
6405 hdspm->ds_in_channels = hdspm->ds_out_channels =
6406 MADI_DS_CHANNELS;
6407 hdspm->qs_in_channels = hdspm->qs_out_channels =
6408 MADI_QS_CHANNELS;
6409
6410 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6411 channel_map_unity_ss;
6412 hdspm->channel_map_in_ds = hdspm->channel_map_out_ss =
6413 channel_map_unity_ss;
6414 hdspm->channel_map_in_qs = hdspm->channel_map_out_ss =
6415 channel_map_unity_ss;
6416
6417 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6418 texts_ports_madi;
6419 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6420 texts_ports_madi;
6421 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6422 texts_ports_madi;
6423 break;
6424
6425 case AIO:
6426 if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) {
6427 snd_printk(KERN_INFO "HDSPM: AEB input board found, but not supported\n");
6428 }
6429
6430 hdspm->ss_in_channels = AIO_IN_SS_CHANNELS;
6431 hdspm->ds_in_channels = AIO_IN_DS_CHANNELS;
6432 hdspm->qs_in_channels = AIO_IN_QS_CHANNELS;
6433 hdspm->ss_out_channels = AIO_OUT_SS_CHANNELS;
6434 hdspm->ds_out_channels = AIO_OUT_DS_CHANNELS;
6435 hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS;
6436
6437 hdspm->channel_map_out_ss = channel_map_aio_out_ss;
6438 hdspm->channel_map_out_ds = channel_map_aio_out_ds;
6439 hdspm->channel_map_out_qs = channel_map_aio_out_qs;
6440
6441 hdspm->channel_map_in_ss = channel_map_aio_in_ss;
6442 hdspm->channel_map_in_ds = channel_map_aio_in_ds;
6443 hdspm->channel_map_in_qs = channel_map_aio_in_qs;
6444
6445 hdspm->port_names_in_ss = texts_ports_aio_in_ss;
6446 hdspm->port_names_out_ss = texts_ports_aio_out_ss;
6447 hdspm->port_names_in_ds = texts_ports_aio_in_ds;
6448 hdspm->port_names_out_ds = texts_ports_aio_out_ds;
6449 hdspm->port_names_in_qs = texts_ports_aio_in_qs;
6450 hdspm->port_names_out_qs = texts_ports_aio_out_qs;
6451
6452 break;
6453
6454 case RayDAT:
6455 hdspm->ss_in_channels = hdspm->ss_out_channels =
6456 RAYDAT_SS_CHANNELS;
6457 hdspm->ds_in_channels = hdspm->ds_out_channels =
6458 RAYDAT_DS_CHANNELS;
6459 hdspm->qs_in_channels = hdspm->qs_out_channels =
6460 RAYDAT_QS_CHANNELS;
6461
6462 hdspm->max_channels_in = RAYDAT_SS_CHANNELS;
6463 hdspm->max_channels_out = RAYDAT_SS_CHANNELS;
6464
6465 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6466 channel_map_raydat_ss;
6467 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6468 channel_map_raydat_ds;
6469 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6470 channel_map_raydat_qs;
6471 hdspm->channel_map_in = hdspm->channel_map_out =
6472 channel_map_raydat_ss;
6473
6474 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6475 texts_ports_raydat_ss;
6476 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6477 texts_ports_raydat_ds;
6478 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6479 texts_ports_raydat_qs;
6480
6481
6482 break;
6483
6484 }
6485
6486 /* TCO detection */
6487 switch (hdspm->io_type) {
6488 case AIO:
6489 case RayDAT:
6490 if (hdspm_read(hdspm, HDSPM_statusRegister2) &
6491 HDSPM_s2_tco_detect) {
6492 hdspm->midiPorts++;
6493 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6494 GFP_KERNEL);
6495 if (NULL != hdspm->tco) {
6496 hdspm_tco_write(hdspm);
6497 }
6498 snd_printk(KERN_INFO "HDSPM: AIO/RayDAT TCO module found\n");
6499 } else {
6500 hdspm->tco = NULL;
6501 }
6502 break;
6503
6504 case MADI:
6505 if (hdspm_read(hdspm, HDSPM_statusRegister) & HDSPM_tco_detect) {
6506 hdspm->midiPorts++;
6507 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6508 GFP_KERNEL);
6509 if (NULL != hdspm->tco) {
6510 hdspm_tco_write(hdspm);
6511 }
6512 snd_printk(KERN_INFO "HDSPM: MADI TCO module found\n");
6513 } else {
6514 hdspm->tco = NULL;
6515 }
6516 break;
6517
6518 default:
6519 hdspm->tco = NULL;
6520 }
6521
6522 /* texts */
6523 switch (hdspm->io_type) {
6524 case AES32:
6525 if (hdspm->tco) {
6526 hdspm->texts_autosync = texts_autosync_aes_tco;
6527 hdspm->texts_autosync_items = 10;
6528 } else {
6529 hdspm->texts_autosync = texts_autosync_aes;
6530 hdspm->texts_autosync_items = 9;
6531 }
6532 break;
6533
6534 case MADI:
6535 if (hdspm->tco) {
6536 hdspm->texts_autosync = texts_autosync_madi_tco;
6537 hdspm->texts_autosync_items = 4;
6538 } else {
6539 hdspm->texts_autosync = texts_autosync_madi;
6540 hdspm->texts_autosync_items = 3;
6541 }
6542 break;
6543
6544 case MADIface:
6545
6546 break;
6547
6548 case RayDAT:
6549 if (hdspm->tco) {
6550 hdspm->texts_autosync = texts_autosync_raydat_tco;
6551 hdspm->texts_autosync_items = 9;
6552 } else {
6553 hdspm->texts_autosync = texts_autosync_raydat;
6554 hdspm->texts_autosync_items = 8;
6555 }
6556 break;
6557
6558 case AIO:
6559 if (hdspm->tco) {
6560 hdspm->texts_autosync = texts_autosync_aio_tco;
6561 hdspm->texts_autosync_items = 6;
6562 } else {
6563 hdspm->texts_autosync = texts_autosync_aio;
6564 hdspm->texts_autosync_items = 5;
6565 }
6566 break;
6567
6568 }
6569
6570 tasklet_init(&hdspm->midi_tasklet,
6571 hdspm_midi_tasklet, (unsigned long) hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006572
6573 snd_printdd("create alsa devices.\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006574 err = snd_hdspm_create_alsa_devices(card, hdspm);
6575 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006576 return err;
6577
6578 snd_hdspm_initialize_midi_flush(hdspm);
6579
6580 return 0;
6581}
6582
Adrian Knoth0dca1792011-01-26 19:32:14 +01006583
Takashi Iwai98274f02005-11-17 14:52:34 +01006584static int snd_hdspm_free(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006585{
6586
6587 if (hdspm->port) {
6588
6589 /* stop th audio, and cancel all interrupts */
6590 hdspm->control_register &=
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006591 ~(HDSPM_Start | HDSPM_AudioInterruptEnable |
Adrian Knoth0dca1792011-01-26 19:32:14 +01006592 HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable |
6593 HDSPM_Midi2InterruptEnable | HDSPM_Midi3InterruptEnable);
Takashi Iwai763f3562005-06-03 11:25:34 +02006594 hdspm_write(hdspm, HDSPM_controlRegister,
6595 hdspm->control_register);
6596 }
6597
6598 if (hdspm->irq >= 0)
6599 free_irq(hdspm->irq, (void *) hdspm);
6600
Jesper Juhlfc584222005-10-24 15:11:28 +02006601 kfree(hdspm->mixer);
Takashi Iwai763f3562005-06-03 11:25:34 +02006602
6603 if (hdspm->iobase)
6604 iounmap(hdspm->iobase);
6605
Takashi Iwai763f3562005-06-03 11:25:34 +02006606 if (hdspm->port)
6607 pci_release_regions(hdspm->pci);
6608
6609 pci_disable_device(hdspm->pci);
6610 return 0;
6611}
6612
Adrian Knoth0dca1792011-01-26 19:32:14 +01006613
Takashi Iwai98274f02005-11-17 14:52:34 +01006614static void snd_hdspm_card_free(struct snd_card *card)
Takashi Iwai763f3562005-06-03 11:25:34 +02006615{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006616 struct hdspm *hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006617
6618 if (hdspm)
6619 snd_hdspm_free(hdspm);
6620}
6621
Adrian Knoth0dca1792011-01-26 19:32:14 +01006622
Takashi Iwai763f3562005-06-03 11:25:34 +02006623static int __devinit snd_hdspm_probe(struct pci_dev *pci,
6624 const struct pci_device_id *pci_id)
6625{
6626 static int dev;
Takashi Iwai98274f02005-11-17 14:52:34 +01006627 struct hdspm *hdspm;
6628 struct snd_card *card;
Takashi Iwai763f3562005-06-03 11:25:34 +02006629 int err;
6630
6631 if (dev >= SNDRV_CARDS)
6632 return -ENODEV;
6633 if (!enable[dev]) {
6634 dev++;
6635 return -ENOENT;
6636 }
6637
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006638 err = snd_card_create(index[dev], id[dev],
Adrian Knoth0dca1792011-01-26 19:32:14 +01006639 THIS_MODULE, sizeof(struct hdspm), &card);
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006640 if (err < 0)
6641 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006642
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006643 hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006644 card->private_free = snd_hdspm_card_free;
6645 hdspm->dev = dev;
6646 hdspm->pci = pci;
6647
Takashi Iwaic187c042007-02-19 15:27:33 +01006648 snd_card_set_dev(card, &pci->dev);
6649
Adrian Knoth0dca1792011-01-26 19:32:14 +01006650 err = snd_hdspm_create(card, hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006651 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006652 snd_card_free(card);
6653 return err;
6654 }
6655
Adrian Knoth0dca1792011-01-26 19:32:14 +01006656 if (hdspm->io_type != MADIface) {
6657 sprintf(card->shortname, "%s_%x",
6658 hdspm->card_name,
6659 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF);
6660 sprintf(card->longname, "%s S/N 0x%x at 0x%lx, irq %d",
6661 hdspm->card_name,
6662 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF,
6663 hdspm->port, hdspm->irq);
6664 } else {
6665 sprintf(card->shortname, "%s", hdspm->card_name);
6666 sprintf(card->longname, "%s at 0x%lx, irq %d",
6667 hdspm->card_name, hdspm->port, hdspm->irq);
6668 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006669
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006670 err = snd_card_register(card);
6671 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006672 snd_card_free(card);
6673 return err;
6674 }
6675
6676 pci_set_drvdata(pci, card);
6677
6678 dev++;
6679 return 0;
6680}
6681
6682static void __devexit snd_hdspm_remove(struct pci_dev *pci)
6683{
6684 snd_card_free(pci_get_drvdata(pci));
6685 pci_set_drvdata(pci, NULL);
6686}
6687
6688static struct pci_driver driver = {
6689 .name = "RME Hammerfall DSP MADI",
Takashi Iwai763f3562005-06-03 11:25:34 +02006690 .id_table = snd_hdspm_ids,
6691 .probe = snd_hdspm_probe,
6692 .remove = __devexit_p(snd_hdspm_remove),
6693};
6694
6695
6696static int __init alsa_card_hdspm_init(void)
6697{
6698 return pci_register_driver(&driver);
6699}
6700
6701static void __exit alsa_card_hdspm_exit(void)
6702{
6703 pci_unregister_driver(&driver);
6704}
6705
6706module_init(alsa_card_hdspm_init)
6707module_exit(alsa_card_hdspm_exit)