blob: 32d80af012cc4ce4bd27cf3254028aa1aa2140c4 [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
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300394#define HDSPM_version0 (1<<0) /* not really defined but I guess */
Takashi Iwai763f3562005-06-03 11:25:34 +0200395#define HDSPM_version1 (1<<1) /* in former cards it was ??? */
396#define HDSPM_version2 (1<<2)
397
398#define HDSPM_wcLock (1<<3) /* Wordclock is detected and locked */
399#define HDSPM_wcSync (1<<4) /* Wordclock is in sync with systemclock */
400
401#define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */
402#define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */
403#define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, */
404/* missing Bit for 111=128, 1000=176.4, 1001=192 */
405
Adrian Knoth0dca1792011-01-26 19:32:14 +0100406#define HDSPM_SyncRef0 0x10000 /* Sync Reference */
407#define HDSPM_SyncRef1 0x20000
408
409#define HDSPM_SelSyncRef0 (1<<8) /* AutoSync Source */
Takashi Iwai763f3562005-06-03 11:25:34 +0200410#define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */
411#define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */
412
413#define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync)
414
415#define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2)
416#define HDSPM_wcFreq32 (HDSPM_wc_freq0)
417#define HDSPM_wcFreq44_1 (HDSPM_wc_freq1)
418#define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1)
419#define HDSPM_wcFreq64 (HDSPM_wc_freq2)
420#define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2)
421#define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2)
422
Adrian Knoth0dca1792011-01-26 19:32:14 +0100423#define HDSPM_status1_F_0 0x0400000
424#define HDSPM_status1_F_1 0x0800000
425#define HDSPM_status1_F_2 0x1000000
426#define HDSPM_status1_F_3 0x2000000
427#define HDSPM_status1_freqMask (HDSPM_status1_F_0|HDSPM_status1_F_1|HDSPM_status1_F_2|HDSPM_status1_F_3)
428
Takashi Iwai763f3562005-06-03 11:25:34 +0200429
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200430#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
431 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200432#define HDSPM_SelSyncRef_WORD 0
433#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0)
Adrian Knoth0dca1792011-01-26 19:32:14 +0100434#define HDSPM_SelSyncRef_TCO (HDSPM_SelSyncRef1)
435#define HDSPM_SelSyncRef_SyncIn (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200436#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
437 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200438
Remy Bruno3cee5a62006-10-16 12:46:32 +0200439/*
440 For AES32, bits for status, status2 and timecode are different
441*/
442/* status */
443#define HDSPM_AES32_wcLock 0x0200000
444#define HDSPM_AES32_wcFreq_bit 22
Adrian Knoth0dca1792011-01-26 19:32:14 +0100445/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function
Remy Bruno3cee5a62006-10-16 12:46:32 +0200446 HDSPM_bit2freq */
447#define HDSPM_AES32_syncref_bit 16
448/* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */
449
450#define HDSPM_AES32_AUTOSYNC_FROM_WORD 0
451#define HDSPM_AES32_AUTOSYNC_FROM_AES1 1
452#define HDSPM_AES32_AUTOSYNC_FROM_AES2 2
453#define HDSPM_AES32_AUTOSYNC_FROM_AES3 3
454#define HDSPM_AES32_AUTOSYNC_FROM_AES4 4
455#define HDSPM_AES32_AUTOSYNC_FROM_AES5 5
456#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6
457#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7
458#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8
Remy Bruno65345992007-08-31 12:21:08 +0200459#define HDSPM_AES32_AUTOSYNC_FROM_NONE 9
Remy Bruno3cee5a62006-10-16 12:46:32 +0200460
461/* status2 */
462/* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */
463#define HDSPM_LockAES 0x80
464#define HDSPM_LockAES1 0x80
465#define HDSPM_LockAES2 0x40
466#define HDSPM_LockAES3 0x20
467#define HDSPM_LockAES4 0x10
468#define HDSPM_LockAES5 0x8
469#define HDSPM_LockAES6 0x4
470#define HDSPM_LockAES7 0x2
471#define HDSPM_LockAES8 0x1
472/*
473 Timecode
474 After windows driver sources, bits 4*i to 4*i+3 give the input frequency on
475 AES i+1
476 bits 3210
477 0001 32kHz
478 0010 44.1kHz
479 0011 48kHz
480 0100 64kHz
481 0101 88.2kHz
482 0110 96kHz
483 0111 128kHz
484 1000 176.4kHz
485 1001 192kHz
486 NB: Timecode register doesn't seem to work on AES32 card revision 230
487*/
488
Takashi Iwai763f3562005-06-03 11:25:34 +0200489/* Mixer Values */
490#define UNITY_GAIN 32768 /* = 65536/2 */
491#define MINUS_INFINITY_GAIN 0
492
Takashi Iwai763f3562005-06-03 11:25:34 +0200493/* Number of channels for different Speed Modes */
494#define MADI_SS_CHANNELS 64
495#define MADI_DS_CHANNELS 32
496#define MADI_QS_CHANNELS 16
497
Adrian Knoth0dca1792011-01-26 19:32:14 +0100498#define RAYDAT_SS_CHANNELS 36
499#define RAYDAT_DS_CHANNELS 20
500#define RAYDAT_QS_CHANNELS 12
501
502#define AIO_IN_SS_CHANNELS 14
503#define AIO_IN_DS_CHANNELS 10
504#define AIO_IN_QS_CHANNELS 8
505#define AIO_OUT_SS_CHANNELS 16
506#define AIO_OUT_DS_CHANNELS 12
507#define AIO_OUT_QS_CHANNELS 10
508
Adrian Knothd2d10a22011-02-28 15:14:47 +0100509#define AES32_CHANNELS 16
510
Takashi Iwai763f3562005-06-03 11:25:34 +0200511/* the size of a substream (1 mono data stream) */
512#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024)
513#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
514
515/* the size of the area we need to allocate for DMA transfers. the
516 size is the same regardless of the number of channels, and
Adrian Knoth0dca1792011-01-26 19:32:14 +0100517 also the latency to use.
Takashi Iwai763f3562005-06-03 11:25:34 +0200518 for one direction !!!
519*/
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100520#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
Takashi Iwai763f3562005-06-03 11:25:34 +0200521#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
522
Remy Bruno3cee5a62006-10-16 12:46:32 +0200523/* revisions >= 230 indicate AES32 card */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100524#define HDSPM_MADI_REV 210
525#define HDSPM_RAYDAT_REV 211
526#define HDSPM_AIO_REV 212
527#define HDSPM_MADIFACE_REV 213
528#define HDSPM_AES_REV 240
Adrian Knoth526ea862011-02-28 15:14:48 +0100529#define HDSPM_AES32_REV 234
Adrian Knothbdd32552011-03-07 19:10:11 +0100530#define HDSPM_AES32_OLD_REV 233
Remy Bruno3cee5a62006-10-16 12:46:32 +0200531
Remy Bruno65345992007-08-31 12:21:08 +0200532/* speed factor modes */
533#define HDSPM_SPEED_SINGLE 0
534#define HDSPM_SPEED_DOUBLE 1
535#define HDSPM_SPEED_QUAD 2
Adrian Knoth0dca1792011-01-26 19:32:14 +0100536
Remy Bruno65345992007-08-31 12:21:08 +0200537/* names for speed modes */
538static char *hdspm_speed_names[] = { "single", "double", "quad" };
539
Adrian Knoth0dca1792011-01-26 19:32:14 +0100540static char *texts_autosync_aes_tco[] = { "Word Clock",
541 "AES1", "AES2", "AES3", "AES4",
542 "AES5", "AES6", "AES7", "AES8",
543 "TCO" };
544static char *texts_autosync_aes[] = { "Word Clock",
545 "AES1", "AES2", "AES3", "AES4",
546 "AES5", "AES6", "AES7", "AES8" };
547static char *texts_autosync_madi_tco[] = { "Word Clock",
548 "MADI", "TCO", "Sync In" };
549static char *texts_autosync_madi[] = { "Word Clock",
550 "MADI", "Sync In" };
551
552static char *texts_autosync_raydat_tco[] = {
553 "Word Clock",
554 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
555 "AES", "SPDIF", "TCO", "Sync In"
556};
557static char *texts_autosync_raydat[] = {
558 "Word Clock",
559 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
560 "AES", "SPDIF", "Sync In"
561};
562static char *texts_autosync_aio_tco[] = {
563 "Word Clock",
564 "ADAT", "AES", "SPDIF", "TCO", "Sync In"
565};
566static char *texts_autosync_aio[] = { "Word Clock",
567 "ADAT", "AES", "SPDIF", "Sync In" };
568
569static char *texts_freq[] = {
570 "No Lock",
571 "32 kHz",
572 "44.1 kHz",
573 "48 kHz",
574 "64 kHz",
575 "88.2 kHz",
576 "96 kHz",
577 "128 kHz",
578 "176.4 kHz",
579 "192 kHz"
580};
581
Adrian Knoth0dca1792011-01-26 19:32:14 +0100582static char *texts_ports_madi[] = {
583 "MADI.1", "MADI.2", "MADI.3", "MADI.4", "MADI.5", "MADI.6",
584 "MADI.7", "MADI.8", "MADI.9", "MADI.10", "MADI.11", "MADI.12",
585 "MADI.13", "MADI.14", "MADI.15", "MADI.16", "MADI.17", "MADI.18",
586 "MADI.19", "MADI.20", "MADI.21", "MADI.22", "MADI.23", "MADI.24",
587 "MADI.25", "MADI.26", "MADI.27", "MADI.28", "MADI.29", "MADI.30",
588 "MADI.31", "MADI.32", "MADI.33", "MADI.34", "MADI.35", "MADI.36",
589 "MADI.37", "MADI.38", "MADI.39", "MADI.40", "MADI.41", "MADI.42",
590 "MADI.43", "MADI.44", "MADI.45", "MADI.46", "MADI.47", "MADI.48",
591 "MADI.49", "MADI.50", "MADI.51", "MADI.52", "MADI.53", "MADI.54",
592 "MADI.55", "MADI.56", "MADI.57", "MADI.58", "MADI.59", "MADI.60",
593 "MADI.61", "MADI.62", "MADI.63", "MADI.64",
594};
595
596
597static char *texts_ports_raydat_ss[] = {
598 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT1.5", "ADAT1.6",
599 "ADAT1.7", "ADAT1.8", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
600 "ADAT2.5", "ADAT2.6", "ADAT2.7", "ADAT2.8", "ADAT3.1", "ADAT3.2",
601 "ADAT3.3", "ADAT3.4", "ADAT3.5", "ADAT3.6", "ADAT3.7", "ADAT3.8",
602 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4", "ADAT4.5", "ADAT4.6",
603 "ADAT4.7", "ADAT4.8",
604 "AES.L", "AES.R",
605 "SPDIF.L", "SPDIF.R"
606};
607
608static char *texts_ports_raydat_ds[] = {
609 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4",
610 "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
611 "ADAT3.1", "ADAT3.2", "ADAT3.3", "ADAT3.4",
612 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4",
613 "AES.L", "AES.R",
614 "SPDIF.L", "SPDIF.R"
615};
616
617static char *texts_ports_raydat_qs[] = {
618 "ADAT1.1", "ADAT1.2",
619 "ADAT2.1", "ADAT2.2",
620 "ADAT3.1", "ADAT3.2",
621 "ADAT4.1", "ADAT4.2",
622 "AES.L", "AES.R",
623 "SPDIF.L", "SPDIF.R"
624};
625
626
627static char *texts_ports_aio_in_ss[] = {
628 "Analogue.L", "Analogue.R",
629 "AES.L", "AES.R",
630 "SPDIF.L", "SPDIF.R",
631 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
632 "ADAT.7", "ADAT.8"
633};
634
635static char *texts_ports_aio_out_ss[] = {
636 "Analogue.L", "Analogue.R",
637 "AES.L", "AES.R",
638 "SPDIF.L", "SPDIF.R",
639 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
640 "ADAT.7", "ADAT.8",
641 "Phone.L", "Phone.R"
642};
643
644static char *texts_ports_aio_in_ds[] = {
645 "Analogue.L", "Analogue.R",
646 "AES.L", "AES.R",
647 "SPDIF.L", "SPDIF.R",
648 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
649};
650
651static char *texts_ports_aio_out_ds[] = {
652 "Analogue.L", "Analogue.R",
653 "AES.L", "AES.R",
654 "SPDIF.L", "SPDIF.R",
655 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
656 "Phone.L", "Phone.R"
657};
658
659static char *texts_ports_aio_in_qs[] = {
660 "Analogue.L", "Analogue.R",
661 "AES.L", "AES.R",
662 "SPDIF.L", "SPDIF.R",
663 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
664};
665
666static char *texts_ports_aio_out_qs[] = {
667 "Analogue.L", "Analogue.R",
668 "AES.L", "AES.R",
669 "SPDIF.L", "SPDIF.R",
670 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
671 "Phone.L", "Phone.R"
672};
673
Adrian Knoth432d2502011-02-23 11:43:08 +0100674static char *texts_ports_aes32[] = {
675 "AES.1", "AES.2", "AES.3", "AES.4", "AES.5", "AES.6", "AES.7",
676 "AES.8", "AES.9.", "AES.10", "AES.11", "AES.12", "AES.13", "AES.14",
677 "AES.15", "AES.16"
678};
679
Adrian Knoth55a57602011-01-27 11:23:15 +0100680/* These tables map the ALSA channels 1..N to the channels that we
681 need to use in order to find the relevant channel buffer. RME
682 refers to this kind of mapping as between "the ADAT channel and
683 the DMA channel." We index it using the logical audio channel,
684 and the value is the DMA channel (i.e. channel buffer number)
685 where the data for that channel can be read/written from/to.
686*/
687
688static char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = {
689 0, 1, 2, 3, 4, 5, 6, 7,
690 8, 9, 10, 11, 12, 13, 14, 15,
691 16, 17, 18, 19, 20, 21, 22, 23,
692 24, 25, 26, 27, 28, 29, 30, 31,
693 32, 33, 34, 35, 36, 37, 38, 39,
694 40, 41, 42, 43, 44, 45, 46, 47,
695 48, 49, 50, 51, 52, 53, 54, 55,
696 56, 57, 58, 59, 60, 61, 62, 63
697};
698
Adrian Knoth55a57602011-01-27 11:23:15 +0100699static char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = {
700 4, 5, 6, 7, 8, 9, 10, 11, /* ADAT 1 */
701 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT 2 */
702 20, 21, 22, 23, 24, 25, 26, 27, /* ADAT 3 */
703 28, 29, 30, 31, 32, 33, 34, 35, /* ADAT 4 */
704 0, 1, /* AES */
705 2, 3, /* SPDIF */
706 -1, -1, -1, -1,
707 -1, -1, -1, -1, -1, -1, -1, -1,
708 -1, -1, -1, -1, -1, -1, -1, -1,
709 -1, -1, -1, -1, -1, -1, -1, -1,
710};
711
712static char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = {
713 4, 5, 6, 7, /* ADAT 1 */
714 8, 9, 10, 11, /* ADAT 2 */
715 12, 13, 14, 15, /* ADAT 3 */
716 16, 17, 18, 19, /* ADAT 4 */
717 0, 1, /* AES */
718 2, 3, /* SPDIF */
719 -1, -1, -1, -1,
720 -1, -1, -1, -1, -1, -1, -1, -1,
721 -1, -1, -1, -1, -1, -1, -1, -1,
722 -1, -1, -1, -1, -1, -1, -1, -1,
723 -1, -1, -1, -1, -1, -1, -1, -1,
724 -1, -1, -1, -1, -1, -1, -1, -1,
725};
726
727static char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = {
728 4, 5, /* ADAT 1 */
729 6, 7, /* ADAT 2 */
730 8, 9, /* ADAT 3 */
731 10, 11, /* ADAT 4 */
732 0, 1, /* AES */
733 2, 3, /* SPDIF */
734 -1, -1, -1, -1,
735 -1, -1, -1, -1, -1, -1, -1, -1,
736 -1, -1, -1, -1, -1, -1, -1, -1,
737 -1, -1, -1, -1, -1, -1, -1, -1,
738 -1, -1, -1, -1, -1, -1, -1, -1,
739 -1, -1, -1, -1, -1, -1, -1, -1,
740 -1, -1, -1, -1, -1, -1, -1, -1,
741};
742
743static char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = {
744 0, 1, /* line in */
745 8, 9, /* aes in, */
746 10, 11, /* spdif in */
747 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT in */
748 -1, -1,
749 -1, -1, -1, -1, -1, -1, -1, -1,
750 -1, -1, -1, -1, -1, -1, -1, -1,
751 -1, -1, -1, -1, -1, -1, -1, -1,
752 -1, -1, -1, -1, -1, -1, -1, -1,
753 -1, -1, -1, -1, -1, -1, -1, -1,
754 -1, -1, -1, -1, -1, -1, -1, -1,
755};
756
757static char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = {
758 0, 1, /* line out */
759 8, 9, /* aes out */
760 10, 11, /* spdif out */
761 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT out */
762 6, 7, /* phone out */
763 -1, -1, -1, -1, -1, -1, -1, -1,
764 -1, -1, -1, -1, -1, -1, -1, -1,
765 -1, -1, -1, -1, -1, -1, -1, -1,
766 -1, -1, -1, -1, -1, -1, -1, -1,
767 -1, -1, -1, -1, -1, -1, -1, -1,
768 -1, -1, -1, -1, -1, -1, -1, -1,
769};
770
771static char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = {
772 0, 1, /* line in */
773 8, 9, /* aes in */
774 10, 11, /* spdif in */
775 12, 14, 16, 18, /* adat in */
776 -1, -1, -1, -1, -1, -1,
777 -1, -1, -1, -1, -1, -1, -1, -1,
778 -1, -1, -1, -1, -1, -1, -1, -1,
779 -1, -1, -1, -1, -1, -1, -1, -1,
780 -1, -1, -1, -1, -1, -1, -1, -1,
781 -1, -1, -1, -1, -1, -1, -1, -1,
782 -1, -1, -1, -1, -1, -1, -1, -1
783};
784
785static char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = {
786 0, 1, /* line out */
787 8, 9, /* aes out */
788 10, 11, /* spdif out */
789 12, 14, 16, 18, /* adat out */
790 6, 7, /* phone out */
791 -1, -1, -1, -1,
792 -1, -1, -1, -1, -1, -1, -1, -1,
793 -1, -1, -1, -1, -1, -1, -1, -1,
794 -1, -1, -1, -1, -1, -1, -1, -1,
795 -1, -1, -1, -1, -1, -1, -1, -1,
796 -1, -1, -1, -1, -1, -1, -1, -1,
797 -1, -1, -1, -1, -1, -1, -1, -1
798};
799
800static char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = {
801 0, 1, /* line in */
802 8, 9, /* aes in */
803 10, 11, /* spdif in */
804 12, 16, /* adat in */
805 -1, -1, -1, -1, -1, -1, -1, -1,
806 -1, -1, -1, -1, -1, -1, -1, -1,
807 -1, -1, -1, -1, -1, -1, -1, -1,
808 -1, -1, -1, -1, -1, -1, -1, -1,
809 -1, -1, -1, -1, -1, -1, -1, -1,
810 -1, -1, -1, -1, -1, -1, -1, -1,
811 -1, -1, -1, -1, -1, -1, -1, -1
812};
813
814static char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = {
815 0, 1, /* line out */
816 8, 9, /* aes out */
817 10, 11, /* spdif out */
818 12, 16, /* adat out */
819 6, 7, /* phone out */
820 -1, -1, -1, -1, -1, -1,
821 -1, -1, -1, -1, -1, -1, -1, -1,
822 -1, -1, -1, -1, -1, -1, -1, -1,
823 -1, -1, -1, -1, -1, -1, -1, -1,
824 -1, -1, -1, -1, -1, -1, -1, -1,
825 -1, -1, -1, -1, -1, -1, -1, -1,
826 -1, -1, -1, -1, -1, -1, -1, -1
827};
828
Adrian Knoth432d2502011-02-23 11:43:08 +0100829static char channel_map_aes32[HDSPM_MAX_CHANNELS] = {
830 0, 1, 2, 3, 4, 5, 6, 7,
831 8, 9, 10, 11, 12, 13, 14, 15,
832 -1, -1, -1, -1, -1, -1, -1, -1,
833 -1, -1, -1, -1, -1, -1, -1, -1,
834 -1, -1, -1, -1, -1, -1, -1, -1,
835 -1, -1, -1, -1, -1, -1, -1, -1,
836 -1, -1, -1, -1, -1, -1, -1, -1,
837 -1, -1, -1, -1, -1, -1, -1, -1
838};
839
Takashi Iwai98274f02005-11-17 14:52:34 +0100840struct hdspm_midi {
841 struct hdspm *hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +0200842 int id;
Takashi Iwai98274f02005-11-17 14:52:34 +0100843 struct snd_rawmidi *rmidi;
844 struct snd_rawmidi_substream *input;
845 struct snd_rawmidi_substream *output;
Takashi Iwai763f3562005-06-03 11:25:34 +0200846 char istimer; /* timer in use */
847 struct timer_list timer;
848 spinlock_t lock;
849 int pending;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100850 int dataIn;
851 int statusIn;
852 int dataOut;
853 int statusOut;
854 int ie;
855 int irq;
856};
857
858struct hdspm_tco {
859 int input;
860 int framerate;
861 int wordclock;
862 int samplerate;
863 int pull;
864 int term; /* 0 = off, 1 = on */
Takashi Iwai763f3562005-06-03 11:25:34 +0200865};
866
Takashi Iwai98274f02005-11-17 14:52:34 +0100867struct hdspm {
Takashi Iwai763f3562005-06-03 11:25:34 +0200868 spinlock_t lock;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200869 /* only one playback and/or capture stream */
870 struct snd_pcm_substream *capture_substream;
871 struct snd_pcm_substream *playback_substream;
Takashi Iwai763f3562005-06-03 11:25:34 +0200872
873 char *card_name; /* for procinfo */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200874 unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
875
Adrian Knoth0dca1792011-01-26 19:32:14 +0100876 uint8_t io_type;
Takashi Iwai763f3562005-06-03 11:25:34 +0200877
Takashi Iwai763f3562005-06-03 11:25:34 +0200878 int monitor_outs; /* set up monitoring outs init flag */
879
880 u32 control_register; /* cached value */
881 u32 control2_register; /* cached value */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100882 u32 settings_register;
Takashi Iwai763f3562005-06-03 11:25:34 +0200883
Adrian Knoth0dca1792011-01-26 19:32:14 +0100884 struct hdspm_midi midi[4];
Takashi Iwai763f3562005-06-03 11:25:34 +0200885 struct tasklet_struct midi_tasklet;
886
887 size_t period_bytes;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100888 unsigned char ss_in_channels;
889 unsigned char ds_in_channels;
890 unsigned char qs_in_channels;
891 unsigned char ss_out_channels;
892 unsigned char ds_out_channels;
893 unsigned char qs_out_channels;
894
895 unsigned char max_channels_in;
896 unsigned char max_channels_out;
897
898 char *channel_map_in;
899 char *channel_map_out;
900
901 char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs;
902 char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs;
903
904 char **port_names_in;
905 char **port_names_out;
906
907 char **port_names_in_ss, **port_names_in_ds, **port_names_in_qs;
908 char **port_names_out_ss, **port_names_out_ds, **port_names_out_qs;
Takashi Iwai763f3562005-06-03 11:25:34 +0200909
910 unsigned char *playback_buffer; /* suitably aligned address */
911 unsigned char *capture_buffer; /* suitably aligned address */
912
913 pid_t capture_pid; /* process id which uses capture */
914 pid_t playback_pid; /* process id which uses capture */
915 int running; /* running status */
916
917 int last_external_sample_rate; /* samplerate mystic ... */
918 int last_internal_sample_rate;
919 int system_sample_rate;
920
Takashi Iwai763f3562005-06-03 11:25:34 +0200921 int dev; /* Hardware vars... */
922 int irq;
923 unsigned long port;
924 void __iomem *iobase;
925
926 int irq_count; /* for debug */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100927 int midiPorts;
Takashi Iwai763f3562005-06-03 11:25:34 +0200928
Takashi Iwai98274f02005-11-17 14:52:34 +0100929 struct snd_card *card; /* one card */
930 struct snd_pcm *pcm; /* has one pcm */
931 struct snd_hwdep *hwdep; /* and a hwdep for additional ioctl */
Takashi Iwai763f3562005-06-03 11:25:34 +0200932 struct pci_dev *pci; /* and an pci info */
933
934 /* Mixer vars */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200935 /* fast alsa mixer */
936 struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS];
937 /* but input to much, so not used */
938 struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS];
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300939 /* full mixer accessible over mixer ioctl or hwdep-device */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200940 struct hdspm_mixer *mixer;
Takashi Iwai763f3562005-06-03 11:25:34 +0200941
Adrian Knoth0dca1792011-01-26 19:32:14 +0100942 struct hdspm_tco *tco; /* NULL if no TCO detected */
Takashi Iwai763f3562005-06-03 11:25:34 +0200943
Adrian Knoth0dca1792011-01-26 19:32:14 +0100944 char **texts_autosync;
945 int texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +0200946
Adrian Knoth0dca1792011-01-26 19:32:14 +0100947 cycles_t last_interrupt;
Jaroslav Kysela730a5862011-01-27 13:03:15 +0100948
949 struct hdspm_peak_rms peak_rms;
Takashi Iwai763f3562005-06-03 11:25:34 +0200950};
951
Takashi Iwai763f3562005-06-03 11:25:34 +0200952
Alexey Dobriyancebe41d2010-02-06 00:21:03 +0200953static DEFINE_PCI_DEVICE_TABLE(snd_hdspm_ids) = {
Takashi Iwai763f3562005-06-03 11:25:34 +0200954 {
955 .vendor = PCI_VENDOR_ID_XILINX,
956 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
957 .subvendor = PCI_ANY_ID,
958 .subdevice = PCI_ANY_ID,
959 .class = 0,
960 .class_mask = 0,
961 .driver_data = 0},
962 {0,}
963};
964
965MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
966
967/* prototypes */
Takashi Iwai98274f02005-11-17 14:52:34 +0100968static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
969 struct hdspm * hdspm);
970static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
971 struct hdspm * hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +0200972
Adrian Knoth0dca1792011-01-26 19:32:14 +0100973static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
974static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
975static int hdspm_autosync_ref(struct hdspm *hdspm);
976static int snd_hdspm_set_defaults(struct hdspm *hdspm);
977static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +0200978 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +0200979 unsigned int reg, int channels);
980
Remy Bruno3cee5a62006-10-16 12:46:32 +0200981static inline int HDSPM_bit2freq(int n)
982{
Denys Vlasenko62cef822008-04-14 13:04:18 +0200983 static const int bit2freq_tab[] = {
984 0, 32000, 44100, 48000, 64000, 88200,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200985 96000, 128000, 176400, 192000 };
986 if (n < 1 || n > 9)
987 return 0;
988 return bit2freq_tab[n];
989}
990
Adrian Knoth0dca1792011-01-26 19:32:14 +0100991/* Write/read to/from HDSPM with Adresses in Bytes
Takashi Iwai763f3562005-06-03 11:25:34 +0200992 not words but only 32Bit writes are allowed */
993
Takashi Iwai98274f02005-11-17 14:52:34 +0100994static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
Takashi Iwai763f3562005-06-03 11:25:34 +0200995 unsigned int val)
996{
997 writel(val, hdspm->iobase + reg);
998}
999
Takashi Iwai98274f02005-11-17 14:52:34 +01001000static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
Takashi Iwai763f3562005-06-03 11:25:34 +02001001{
1002 return readl(hdspm->iobase + reg);
1003}
1004
Adrian Knoth0dca1792011-01-26 19:32:14 +01001005/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
1006 mixer is write only on hardware so we have to cache him for read
Takashi Iwai763f3562005-06-03 11:25:34 +02001007 each fader is a u32, but uses only the first 16 bit */
1008
Takashi Iwai98274f02005-11-17 14:52:34 +01001009static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001010 unsigned int in)
1011{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001012 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001013 return 0;
1014
1015 return hdspm->mixer->ch[chan].in[in];
1016}
1017
Takashi Iwai98274f02005-11-17 14:52:34 +01001018static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001019 unsigned int pb)
1020{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001021 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001022 return 0;
1023 return hdspm->mixer->ch[chan].pb[pb];
1024}
1025
Denys Vlasenko62cef822008-04-14 13:04:18 +02001026static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001027 unsigned int in, unsigned short data)
1028{
1029 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
1030 return -1;
1031
1032 hdspm_write(hdspm,
1033 HDSPM_MADI_mixerBase +
1034 ((in + 128 * chan) * sizeof(u32)),
1035 (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
1036 return 0;
1037}
1038
Denys Vlasenko62cef822008-04-14 13:04:18 +02001039static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001040 unsigned int pb, unsigned short data)
1041{
1042 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
1043 return -1;
1044
1045 hdspm_write(hdspm,
1046 HDSPM_MADI_mixerBase +
1047 ((64 + pb + 128 * chan) * sizeof(u32)),
1048 (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
1049 return 0;
1050}
1051
1052
1053/* enable DMA for specific channels, now available for DSP-MADI */
Takashi Iwai98274f02005-11-17 14:52:34 +01001054static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001055{
1056 hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
1057}
1058
Takashi Iwai98274f02005-11-17 14:52:34 +01001059static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001060{
1061 hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
1062}
1063
1064/* check if same process is writing and reading */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001065static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001066{
1067 unsigned long flags;
1068 int ret = 1;
1069
1070 spin_lock_irqsave(&hdspm->lock, flags);
1071 if ((hdspm->playback_pid != hdspm->capture_pid) &&
1072 (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
1073 ret = 0;
1074 }
1075 spin_unlock_irqrestore(&hdspm->lock, flags);
1076 return ret;
1077}
1078
1079/* check for external sample rate */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001080static int hdspm_external_sample_rate(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001081{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001082 unsigned int status, status2, timecode;
1083 int syncref, rate = 0, rate_bits;
Takashi Iwai763f3562005-06-03 11:25:34 +02001084
Adrian Knoth0dca1792011-01-26 19:32:14 +01001085 switch (hdspm->io_type) {
1086 case AES32:
1087 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1088 status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01001089 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001090
1091 syncref = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001092
Remy Bruno3cee5a62006-10-16 12:46:32 +02001093 if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD &&
1094 status & HDSPM_AES32_wcLock)
Adrian Knoth0dca1792011-01-26 19:32:14 +01001095 return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF);
1096
Remy Bruno3cee5a62006-10-16 12:46:32 +02001097 if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001098 syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
1099 status2 & (HDSPM_LockAES >>
1100 (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1)))
1101 return HDSPM_bit2freq((timecode >> (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF);
Remy Bruno3cee5a62006-10-16 12:46:32 +02001102 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001103 break;
1104
1105 case MADIface:
1106 status = hdspm_read(hdspm, HDSPM_statusRegister);
1107
1108 if (!(status & HDSPM_madiLock)) {
1109 rate = 0; /* no lock */
1110 } else {
1111 switch (status & (HDSPM_status1_freqMask)) {
1112 case HDSPM_status1_F_0*1:
1113 rate = 32000; break;
1114 case HDSPM_status1_F_0*2:
1115 rate = 44100; break;
1116 case HDSPM_status1_F_0*3:
1117 rate = 48000; break;
1118 case HDSPM_status1_F_0*4:
1119 rate = 64000; break;
1120 case HDSPM_status1_F_0*5:
1121 rate = 88200; break;
1122 case HDSPM_status1_F_0*6:
1123 rate = 96000; break;
1124 case HDSPM_status1_F_0*7:
1125 rate = 128000; break;
1126 case HDSPM_status1_F_0*8:
1127 rate = 176400; break;
1128 case HDSPM_status1_F_0*9:
1129 rate = 192000; break;
1130 default:
1131 rate = 0; break;
1132 }
1133 }
1134
1135 break;
1136
1137 case MADI:
1138 case AIO:
1139 case RayDAT:
1140 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1141 status = hdspm_read(hdspm, HDSPM_statusRegister);
1142 rate = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02001143
Remy Bruno3cee5a62006-10-16 12:46:32 +02001144 /* if wordclock has synced freq and wordclock is valid */
1145 if ((status2 & HDSPM_wcLock) != 0 &&
1146 (status & HDSPM_SelSyncRef0) == 0) {
1147
1148 rate_bits = status2 & HDSPM_wcFreqMask;
1149
Adrian Knoth0dca1792011-01-26 19:32:14 +01001150
Remy Bruno3cee5a62006-10-16 12:46:32 +02001151 switch (rate_bits) {
1152 case HDSPM_wcFreq32:
1153 rate = 32000;
1154 break;
1155 case HDSPM_wcFreq44_1:
1156 rate = 44100;
1157 break;
1158 case HDSPM_wcFreq48:
1159 rate = 48000;
1160 break;
1161 case HDSPM_wcFreq64:
1162 rate = 64000;
1163 break;
1164 case HDSPM_wcFreq88_2:
1165 rate = 88200;
1166 break;
1167 case HDSPM_wcFreq96:
1168 rate = 96000;
1169 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001170 default:
1171 rate = 0;
1172 break;
1173 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001174 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001175
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001176 /* if rate detected and Syncref is Word than have it,
1177 * word has priority to MADI
1178 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001179 if (rate != 0 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001180 (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
Remy Bruno3cee5a62006-10-16 12:46:32 +02001181 return rate;
1182
Adrian Knoth0dca1792011-01-26 19:32:14 +01001183 /* maybe a madi input (which is taken if sel sync is madi) */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001184 if (status & HDSPM_madiLock) {
1185 rate_bits = status & HDSPM_madiFreqMask;
1186
1187 switch (rate_bits) {
1188 case HDSPM_madiFreq32:
1189 rate = 32000;
1190 break;
1191 case HDSPM_madiFreq44_1:
1192 rate = 44100;
1193 break;
1194 case HDSPM_madiFreq48:
1195 rate = 48000;
1196 break;
1197 case HDSPM_madiFreq64:
1198 rate = 64000;
1199 break;
1200 case HDSPM_madiFreq88_2:
1201 rate = 88200;
1202 break;
1203 case HDSPM_madiFreq96:
1204 rate = 96000;
1205 break;
1206 case HDSPM_madiFreq128:
1207 rate = 128000;
1208 break;
1209 case HDSPM_madiFreq176_4:
1210 rate = 176400;
1211 break;
1212 case HDSPM_madiFreq192:
1213 rate = 192000;
1214 break;
1215 default:
1216 rate = 0;
1217 break;
1218 }
1219 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001220 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001221 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001222
1223 return rate;
Takashi Iwai763f3562005-06-03 11:25:34 +02001224}
1225
1226/* Latency function */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001227static inline void hdspm_compute_period_size(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001228{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001229 hdspm->period_bytes = 1 << ((hdspm_decode_latency(hdspm->control_register) + 8));
Takashi Iwai763f3562005-06-03 11:25:34 +02001230}
1231
Adrian Knoth0dca1792011-01-26 19:32:14 +01001232
1233static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001234{
1235 int position;
1236
1237 position = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth483cee72011-02-23 11:43:09 +01001238
1239 switch (hdspm->io_type) {
1240 case RayDAT:
1241 case AIO:
1242 position &= HDSPM_BufferPositionMask;
1243 position /= 4; /* Bytes per sample */
1244 break;
1245 default:
1246 position = (position & HDSPM_BufferID) ?
1247 (hdspm->period_bytes / 4) : 0;
1248 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001249
1250 return position;
1251}
1252
1253
Takashi Iwai98274f02005-11-17 14:52:34 +01001254static inline void hdspm_start_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001255{
1256 s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
1257 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1258}
1259
Takashi Iwai98274f02005-11-17 14:52:34 +01001260static inline void hdspm_stop_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001261{
1262 s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
1263 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1264}
1265
1266/* should I silence all or only opened ones ? doit all for first even is 4MB*/
Denys Vlasenko62cef822008-04-14 13:04:18 +02001267static void hdspm_silence_playback(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001268{
1269 int i;
1270 int n = hdspm->period_bytes;
1271 void *buf = hdspm->playback_buffer;
1272
Remy Bruno3cee5a62006-10-16 12:46:32 +02001273 if (buf == NULL)
1274 return;
Takashi Iwai763f3562005-06-03 11:25:34 +02001275
1276 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
1277 memset(buf, 0, n);
1278 buf += HDSPM_CHANNEL_BUFFER_BYTES;
1279 }
1280}
1281
Adrian Knoth0dca1792011-01-26 19:32:14 +01001282static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames)
Takashi Iwai763f3562005-06-03 11:25:34 +02001283{
1284 int n;
1285
1286 spin_lock_irq(&s->lock);
1287
1288 frames >>= 7;
1289 n = 0;
1290 while (frames) {
1291 n++;
1292 frames >>= 1;
1293 }
1294 s->control_register &= ~HDSPM_LatencyMask;
1295 s->control_register |= hdspm_encode_latency(n);
1296
1297 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1298
1299 hdspm_compute_period_size(s);
1300
1301 spin_unlock_irq(&s->lock);
1302
1303 return 0;
1304}
1305
Adrian Knoth0dca1792011-01-26 19:32:14 +01001306static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period)
1307{
1308 u64 freq_const;
1309
1310 if (period == 0)
1311 return 0;
1312
1313 switch (hdspm->io_type) {
1314 case MADI:
1315 case AES32:
1316 freq_const = 110069313433624ULL;
1317 break;
1318 case RayDAT:
1319 case AIO:
1320 freq_const = 104857600000000ULL;
1321 break;
1322 case MADIface:
1323 freq_const = 131072000000000ULL;
1324 }
1325
1326 return div_u64(freq_const, period);
1327}
1328
1329
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001330static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
1331{
1332 u64 n;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001333
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001334 if (rate >= 112000)
1335 rate /= 4;
1336 else if (rate >= 56000)
1337 rate /= 2;
1338
Adrian Knoth0dca1792011-01-26 19:32:14 +01001339 switch (hdspm->io_type) {
1340 case MADIface:
1341 n = 131072000000000ULL; /* 125 MHz */
1342 break;
1343 case MADI:
1344 case AES32:
1345 n = 110069313433624ULL; /* 105 MHz */
1346 break;
1347 case RayDAT:
1348 case AIO:
1349 n = 104857600000000ULL; /* 100 MHz */
1350 break;
1351 }
1352
Takashi Iwai3f7440a2009-06-05 17:40:04 +02001353 n = div_u64(n, rate);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001354 /* n should be less than 2^32 for being written to FREQ register */
Takashi Iwaida3cec32008-08-08 17:12:14 +02001355 snd_BUG_ON(n >> 32);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001356 hdspm_write(hdspm, HDSPM_freqReg, (u32)n);
1357}
Takashi Iwai763f3562005-06-03 11:25:34 +02001358
1359/* dummy set rate lets see what happens */
Takashi Iwai98274f02005-11-17 14:52:34 +01001360static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
Takashi Iwai763f3562005-06-03 11:25:34 +02001361{
Takashi Iwai763f3562005-06-03 11:25:34 +02001362 int current_rate;
1363 int rate_bits;
1364 int not_set = 0;
Remy Bruno65345992007-08-31 12:21:08 +02001365 int current_speed, target_speed;
Takashi Iwai763f3562005-06-03 11:25:34 +02001366
1367 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
1368 it (e.g. during module initialization).
1369 */
1370
1371 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
1372
Adrian Knoth0dca1792011-01-26 19:32:14 +01001373 /* SLAVE --- */
Takashi Iwai763f3562005-06-03 11:25:34 +02001374 if (called_internally) {
1375
Adrian Knoth0dca1792011-01-26 19:32:14 +01001376 /* request from ctl or card initialization
1377 just make a warning an remember setting
1378 for future master mode switching */
1379
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001380 snd_printk(KERN_WARNING "HDSPM: "
1381 "Warning: device is not running "
1382 "as a clock master.\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001383 not_set = 1;
1384 } else {
1385
1386 /* hw_param request while in AutoSync mode */
1387 int external_freq =
1388 hdspm_external_sample_rate(hdspm);
1389
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001390 if (hdspm_autosync_ref(hdspm) ==
1391 HDSPM_AUTOSYNC_FROM_NONE) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001392
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001393 snd_printk(KERN_WARNING "HDSPM: "
1394 "Detected no Externel Sync \n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001395 not_set = 1;
1396
1397 } else if (rate != external_freq) {
1398
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001399 snd_printk(KERN_WARNING "HDSPM: "
1400 "Warning: No AutoSync source for "
1401 "requested rate\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001402 not_set = 1;
1403 }
1404 }
1405 }
1406
1407 current_rate = hdspm->system_sample_rate;
1408
1409 /* Changing between Singe, Double and Quad speed is not
1410 allowed if any substreams are open. This is because such a change
1411 causes a shift in the location of the DMA buffers and a reduction
1412 in the number of available buffers.
1413
1414 Note that a similar but essentially insoluble problem exists for
1415 externally-driven rate changes. All we can do is to flag rate
Adrian Knoth0dca1792011-01-26 19:32:14 +01001416 changes in the read/write routines.
Takashi Iwai763f3562005-06-03 11:25:34 +02001417 */
1418
Remy Bruno65345992007-08-31 12:21:08 +02001419 if (current_rate <= 48000)
1420 current_speed = HDSPM_SPEED_SINGLE;
1421 else if (current_rate <= 96000)
1422 current_speed = HDSPM_SPEED_DOUBLE;
1423 else
1424 current_speed = HDSPM_SPEED_QUAD;
1425
1426 if (rate <= 48000)
1427 target_speed = HDSPM_SPEED_SINGLE;
1428 else if (rate <= 96000)
1429 target_speed = HDSPM_SPEED_DOUBLE;
1430 else
1431 target_speed = HDSPM_SPEED_QUAD;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001432
Takashi Iwai763f3562005-06-03 11:25:34 +02001433 switch (rate) {
1434 case 32000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001435 rate_bits = HDSPM_Frequency32KHz;
1436 break;
1437 case 44100:
Takashi Iwai763f3562005-06-03 11:25:34 +02001438 rate_bits = HDSPM_Frequency44_1KHz;
1439 break;
1440 case 48000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001441 rate_bits = HDSPM_Frequency48KHz;
1442 break;
1443 case 64000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001444 rate_bits = HDSPM_Frequency64KHz;
1445 break;
1446 case 88200:
Takashi Iwai763f3562005-06-03 11:25:34 +02001447 rate_bits = HDSPM_Frequency88_2KHz;
1448 break;
1449 case 96000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001450 rate_bits = HDSPM_Frequency96KHz;
1451 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001452 case 128000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001453 rate_bits = HDSPM_Frequency128KHz;
1454 break;
1455 case 176400:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001456 rate_bits = HDSPM_Frequency176_4KHz;
1457 break;
1458 case 192000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001459 rate_bits = HDSPM_Frequency192KHz;
1460 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001461 default:
1462 return -EINVAL;
1463 }
1464
Remy Bruno65345992007-08-31 12:21:08 +02001465 if (current_speed != target_speed
Takashi Iwai763f3562005-06-03 11:25:34 +02001466 && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
1467 snd_printk
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001468 (KERN_ERR "HDSPM: "
Remy Bruno65345992007-08-31 12:21:08 +02001469 "cannot change from %s speed to %s speed mode "
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001470 "(capture PID = %d, playback PID = %d)\n",
Remy Bruno65345992007-08-31 12:21:08 +02001471 hdspm_speed_names[current_speed],
1472 hdspm_speed_names[target_speed],
Takashi Iwai763f3562005-06-03 11:25:34 +02001473 hdspm->capture_pid, hdspm->playback_pid);
1474 return -EBUSY;
1475 }
1476
1477 hdspm->control_register &= ~HDSPM_FrequencyMask;
1478 hdspm->control_register |= rate_bits;
1479 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1480
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001481 /* For AES32, need to set DDS value in FREQ register
1482 For MADI, also apparently */
1483 hdspm_set_dds_value(hdspm, rate);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001484
1485 if (AES32 == hdspm->io_type && rate != current_rate)
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001486 hdspm_write(hdspm, HDSPM_eeprom_wr, 0);
Takashi Iwai763f3562005-06-03 11:25:34 +02001487
1488 hdspm->system_sample_rate = rate;
1489
Adrian Knoth0dca1792011-01-26 19:32:14 +01001490 if (rate <= 48000) {
1491 hdspm->channel_map_in = hdspm->channel_map_in_ss;
1492 hdspm->channel_map_out = hdspm->channel_map_out_ss;
1493 hdspm->max_channels_in = hdspm->ss_in_channels;
1494 hdspm->max_channels_out = hdspm->ss_out_channels;
1495 hdspm->port_names_in = hdspm->port_names_in_ss;
1496 hdspm->port_names_out = hdspm->port_names_out_ss;
1497 } else if (rate <= 96000) {
1498 hdspm->channel_map_in = hdspm->channel_map_in_ds;
1499 hdspm->channel_map_out = hdspm->channel_map_out_ds;
1500 hdspm->max_channels_in = hdspm->ds_in_channels;
1501 hdspm->max_channels_out = hdspm->ds_out_channels;
1502 hdspm->port_names_in = hdspm->port_names_in_ds;
1503 hdspm->port_names_out = hdspm->port_names_out_ds;
1504 } else {
1505 hdspm->channel_map_in = hdspm->channel_map_in_qs;
1506 hdspm->channel_map_out = hdspm->channel_map_out_qs;
1507 hdspm->max_channels_in = hdspm->qs_in_channels;
1508 hdspm->max_channels_out = hdspm->qs_out_channels;
1509 hdspm->port_names_in = hdspm->port_names_in_qs;
1510 hdspm->port_names_out = hdspm->port_names_out_qs;
1511 }
1512
Takashi Iwai763f3562005-06-03 11:25:34 +02001513 if (not_set != 0)
1514 return -1;
1515
1516 return 0;
1517}
1518
1519/* mainly for init to 0 on load */
Takashi Iwai98274f02005-11-17 14:52:34 +01001520static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
Takashi Iwai763f3562005-06-03 11:25:34 +02001521{
1522 int i, j;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001523 unsigned int gain;
1524
1525 if (sgain > UNITY_GAIN)
1526 gain = UNITY_GAIN;
1527 else if (sgain < 0)
1528 gain = 0;
1529 else
1530 gain = sgain;
Takashi Iwai763f3562005-06-03 11:25:34 +02001531
1532 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
1533 for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
1534 hdspm_write_in_gain(hdspm, i, j, gain);
1535 hdspm_write_pb_gain(hdspm, i, j, gain);
1536 }
1537}
1538
1539/*----------------------------------------------------------------------------
1540 MIDI
1541 ----------------------------------------------------------------------------*/
1542
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001543static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm,
1544 int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001545{
1546 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001547 return hdspm_read(hdspm, hdspm->midi[id].dataIn);
Takashi Iwai763f3562005-06-03 11:25:34 +02001548}
1549
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001550static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
1551 int val)
Takashi Iwai763f3562005-06-03 11:25:34 +02001552{
1553 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001554 return hdspm_write(hdspm, hdspm->midi[id].dataOut, val);
Takashi Iwai763f3562005-06-03 11:25:34 +02001555}
1556
Takashi Iwai98274f02005-11-17 14:52:34 +01001557static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001558{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001559 return hdspm_read(hdspm, hdspm->midi[id].statusIn) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001560}
1561
Takashi Iwai98274f02005-11-17 14:52:34 +01001562static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001563{
1564 int fifo_bytes_used;
1565
Adrian Knoth0dca1792011-01-26 19:32:14 +01001566 fifo_bytes_used = hdspm_read(hdspm, hdspm->midi[id].statusOut) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001567
1568 if (fifo_bytes_used < 128)
1569 return 128 - fifo_bytes_used;
1570 else
1571 return 0;
1572}
1573
Denys Vlasenko62cef822008-04-14 13:04:18 +02001574static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001575{
1576 while (snd_hdspm_midi_input_available (hdspm, id))
1577 snd_hdspm_midi_read_byte (hdspm, id);
1578}
1579
Takashi Iwai98274f02005-11-17 14:52:34 +01001580static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001581{
1582 unsigned long flags;
1583 int n_pending;
1584 int to_write;
1585 int i;
1586 unsigned char buf[128];
1587
1588 /* Output is not interrupt driven */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001589
Takashi Iwai763f3562005-06-03 11:25:34 +02001590 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001591 if (hmidi->output &&
1592 !snd_rawmidi_transmit_empty (hmidi->output)) {
1593 n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm,
1594 hmidi->id);
1595 if (n_pending > 0) {
1596 if (n_pending > (int)sizeof (buf))
1597 n_pending = sizeof (buf);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001598
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001599 to_write = snd_rawmidi_transmit (hmidi->output, buf,
1600 n_pending);
1601 if (to_write > 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001602 for (i = 0; i < to_write; ++i)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001603 snd_hdspm_midi_write_byte (hmidi->hdspm,
1604 hmidi->id,
1605 buf[i]);
Takashi Iwai763f3562005-06-03 11:25:34 +02001606 }
1607 }
1608 }
1609 spin_unlock_irqrestore (&hmidi->lock, flags);
1610 return 0;
1611}
1612
Takashi Iwai98274f02005-11-17 14:52:34 +01001613static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001614{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001615 unsigned char buf[128]; /* this buffer is designed to match the MIDI
1616 * input FIFO size
1617 */
Takashi Iwai763f3562005-06-03 11:25:34 +02001618 unsigned long flags;
1619 int n_pending;
1620 int i;
1621
1622 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001623 n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id);
1624 if (n_pending > 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001625 if (hmidi->input) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001626 if (n_pending > (int)sizeof (buf))
Takashi Iwai763f3562005-06-03 11:25:34 +02001627 n_pending = sizeof (buf);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001628 for (i = 0; i < n_pending; ++i)
1629 buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm,
1630 hmidi->id);
1631 if (n_pending)
1632 snd_rawmidi_receive (hmidi->input, buf,
1633 n_pending);
Takashi Iwai763f3562005-06-03 11:25:34 +02001634 } else {
1635 /* flush the MIDI input FIFO */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001636 while (n_pending--)
1637 snd_hdspm_midi_read_byte (hmidi->hdspm,
1638 hmidi->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02001639 }
1640 }
1641 hmidi->pending = 0;
Adrian Knothc0da0012011-06-12 17:26:17 +02001642 spin_unlock_irqrestore(&hmidi->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001643
Adrian Knothc0da0012011-06-12 17:26:17 +02001644 spin_lock_irqsave(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001645 hmidi->hdspm->control_register |= hmidi->ie;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001646 hdspm_write(hmidi->hdspm, HDSPM_controlRegister,
1647 hmidi->hdspm->control_register);
Adrian Knothc0da0012011-06-12 17:26:17 +02001648 spin_unlock_irqrestore(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001649
Takashi Iwai763f3562005-06-03 11:25:34 +02001650 return snd_hdspm_midi_output_write (hmidi);
1651}
1652
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001653static void
1654snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001655{
Takashi Iwai98274f02005-11-17 14:52:34 +01001656 struct hdspm *hdspm;
1657 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001658 unsigned long flags;
Takashi Iwai763f3562005-06-03 11:25:34 +02001659
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001660 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001661 hdspm = hmidi->hdspm;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001662
Takashi Iwai763f3562005-06-03 11:25:34 +02001663 spin_lock_irqsave (&hdspm->lock, flags);
1664 if (up) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001665 if (!(hdspm->control_register & hmidi->ie)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001666 snd_hdspm_flush_midi_input (hdspm, hmidi->id);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001667 hdspm->control_register |= hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001668 }
1669 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001670 hdspm->control_register &= ~hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001671 }
1672
1673 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1674 spin_unlock_irqrestore (&hdspm->lock, flags);
1675}
1676
1677static void snd_hdspm_midi_output_timer(unsigned long data)
1678{
Takashi Iwai98274f02005-11-17 14:52:34 +01001679 struct hdspm_midi *hmidi = (struct hdspm_midi *) data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001680 unsigned long flags;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001681
Takashi Iwai763f3562005-06-03 11:25:34 +02001682 snd_hdspm_midi_output_write(hmidi);
1683 spin_lock_irqsave (&hmidi->lock, flags);
1684
1685 /* this does not bump hmidi->istimer, because the
1686 kernel automatically removed the timer when it
1687 expired, and we are now adding it back, thus
Adrian Knoth0dca1792011-01-26 19:32:14 +01001688 leaving istimer wherever it was set before.
Takashi Iwai763f3562005-06-03 11:25:34 +02001689 */
1690
1691 if (hmidi->istimer) {
1692 hmidi->timer.expires = 1 + jiffies;
1693 add_timer(&hmidi->timer);
1694 }
1695
1696 spin_unlock_irqrestore (&hmidi->lock, flags);
1697}
1698
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001699static void
1700snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001701{
Takashi Iwai98274f02005-11-17 14:52:34 +01001702 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001703 unsigned long flags;
1704
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001705 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001706 spin_lock_irqsave (&hmidi->lock, flags);
1707 if (up) {
1708 if (!hmidi->istimer) {
1709 init_timer(&hmidi->timer);
1710 hmidi->timer.function = snd_hdspm_midi_output_timer;
1711 hmidi->timer.data = (unsigned long) hmidi;
1712 hmidi->timer.expires = 1 + jiffies;
1713 add_timer(&hmidi->timer);
1714 hmidi->istimer++;
1715 }
1716 } else {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001717 if (hmidi->istimer && --hmidi->istimer <= 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02001718 del_timer (&hmidi->timer);
Takashi Iwai763f3562005-06-03 11:25:34 +02001719 }
1720 spin_unlock_irqrestore (&hmidi->lock, flags);
1721 if (up)
1722 snd_hdspm_midi_output_write(hmidi);
1723}
1724
Takashi Iwai98274f02005-11-17 14:52:34 +01001725static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001726{
Takashi Iwai98274f02005-11-17 14:52:34 +01001727 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001728
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001729 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001730 spin_lock_irq (&hmidi->lock);
1731 snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
1732 hmidi->input = substream;
1733 spin_unlock_irq (&hmidi->lock);
1734
1735 return 0;
1736}
1737
Takashi Iwai98274f02005-11-17 14:52:34 +01001738static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001739{
Takashi Iwai98274f02005-11-17 14:52:34 +01001740 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001741
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001742 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001743 spin_lock_irq (&hmidi->lock);
1744 hmidi->output = substream;
1745 spin_unlock_irq (&hmidi->lock);
1746
1747 return 0;
1748}
1749
Takashi Iwai98274f02005-11-17 14:52:34 +01001750static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001751{
Takashi Iwai98274f02005-11-17 14:52:34 +01001752 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001753
1754 snd_hdspm_midi_input_trigger (substream, 0);
1755
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001756 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001757 spin_lock_irq (&hmidi->lock);
1758 hmidi->input = NULL;
1759 spin_unlock_irq (&hmidi->lock);
1760
1761 return 0;
1762}
1763
Takashi Iwai98274f02005-11-17 14:52:34 +01001764static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001765{
Takashi Iwai98274f02005-11-17 14:52:34 +01001766 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001767
1768 snd_hdspm_midi_output_trigger (substream, 0);
1769
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001770 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001771 spin_lock_irq (&hmidi->lock);
1772 hmidi->output = NULL;
1773 spin_unlock_irq (&hmidi->lock);
1774
1775 return 0;
1776}
1777
Takashi Iwai98274f02005-11-17 14:52:34 +01001778static struct snd_rawmidi_ops snd_hdspm_midi_output =
Takashi Iwai763f3562005-06-03 11:25:34 +02001779{
1780 .open = snd_hdspm_midi_output_open,
1781 .close = snd_hdspm_midi_output_close,
1782 .trigger = snd_hdspm_midi_output_trigger,
1783};
1784
Takashi Iwai98274f02005-11-17 14:52:34 +01001785static struct snd_rawmidi_ops snd_hdspm_midi_input =
Takashi Iwai763f3562005-06-03 11:25:34 +02001786{
1787 .open = snd_hdspm_midi_input_open,
1788 .close = snd_hdspm_midi_input_close,
1789 .trigger = snd_hdspm_midi_input_trigger,
1790};
1791
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001792static int __devinit snd_hdspm_create_midi (struct snd_card *card,
1793 struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001794{
1795 int err;
1796 char buf[32];
1797
1798 hdspm->midi[id].id = id;
Takashi Iwai763f3562005-06-03 11:25:34 +02001799 hdspm->midi[id].hdspm = hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +02001800 spin_lock_init (&hdspm->midi[id].lock);
1801
Adrian Knoth0dca1792011-01-26 19:32:14 +01001802 if (0 == id) {
1803 if (MADIface == hdspm->io_type) {
1804 /* MIDI-over-MADI on HDSPe MADIface */
1805 hdspm->midi[0].dataIn = HDSPM_midiDataIn2;
1806 hdspm->midi[0].statusIn = HDSPM_midiStatusIn2;
1807 hdspm->midi[0].dataOut = HDSPM_midiDataOut2;
1808 hdspm->midi[0].statusOut = HDSPM_midiStatusOut2;
1809 hdspm->midi[0].ie = HDSPM_Midi2InterruptEnable;
1810 hdspm->midi[0].irq = HDSPM_midi2IRQPending;
1811 } else {
1812 hdspm->midi[0].dataIn = HDSPM_midiDataIn0;
1813 hdspm->midi[0].statusIn = HDSPM_midiStatusIn0;
1814 hdspm->midi[0].dataOut = HDSPM_midiDataOut0;
1815 hdspm->midi[0].statusOut = HDSPM_midiStatusOut0;
1816 hdspm->midi[0].ie = HDSPM_Midi0InterruptEnable;
1817 hdspm->midi[0].irq = HDSPM_midi0IRQPending;
1818 }
1819 } else if (1 == id) {
1820 hdspm->midi[1].dataIn = HDSPM_midiDataIn1;
1821 hdspm->midi[1].statusIn = HDSPM_midiStatusIn1;
1822 hdspm->midi[1].dataOut = HDSPM_midiDataOut1;
1823 hdspm->midi[1].statusOut = HDSPM_midiStatusOut1;
1824 hdspm->midi[1].ie = HDSPM_Midi1InterruptEnable;
1825 hdspm->midi[1].irq = HDSPM_midi1IRQPending;
1826 } else if ((2 == id) && (MADI == hdspm->io_type)) {
1827 /* MIDI-over-MADI on HDSPe MADI */
1828 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1829 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1830 hdspm->midi[2].dataOut = HDSPM_midiDataOut2;
1831 hdspm->midi[2].statusOut = HDSPM_midiStatusOut2;
1832 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1833 hdspm->midi[2].irq = HDSPM_midi2IRQPending;
1834 } else if (2 == id) {
1835 /* TCO MTC, read only */
1836 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1837 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1838 hdspm->midi[2].dataOut = -1;
1839 hdspm->midi[2].statusOut = -1;
1840 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1841 hdspm->midi[2].irq = HDSPM_midi2IRQPendingAES;
1842 } else if (3 == id) {
1843 /* TCO MTC on HDSPe MADI */
1844 hdspm->midi[3].dataIn = HDSPM_midiDataIn3;
1845 hdspm->midi[3].statusIn = HDSPM_midiStatusIn3;
1846 hdspm->midi[3].dataOut = -1;
1847 hdspm->midi[3].statusOut = -1;
1848 hdspm->midi[3].ie = HDSPM_Midi3InterruptEnable;
1849 hdspm->midi[3].irq = HDSPM_midi3IRQPending;
1850 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001851
Adrian Knoth0dca1792011-01-26 19:32:14 +01001852 if ((id < 2) || ((2 == id) && ((MADI == hdspm->io_type) ||
1853 (MADIface == hdspm->io_type)))) {
1854 if ((id == 0) && (MADIface == hdspm->io_type)) {
1855 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1856 } else if ((id == 2) && (MADI == hdspm->io_type)) {
1857 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1858 } else {
1859 sprintf(buf, "%s MIDI %d", card->shortname, id+1);
1860 }
1861 err = snd_rawmidi_new(card, buf, id, 1, 1,
1862 &hdspm->midi[id].rmidi);
1863 if (err < 0)
1864 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02001865
Adrian Knoth0dca1792011-01-26 19:32:14 +01001866 sprintf(hdspm->midi[id].rmidi->name, "%s MIDI %d",
1867 card->id, id+1);
1868 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
Takashi Iwai763f3562005-06-03 11:25:34 +02001869
Adrian Knoth0dca1792011-01-26 19:32:14 +01001870 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1871 SNDRV_RAWMIDI_STREAM_OUTPUT,
1872 &snd_hdspm_midi_output);
1873 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1874 SNDRV_RAWMIDI_STREAM_INPUT,
1875 &snd_hdspm_midi_input);
1876
1877 hdspm->midi[id].rmidi->info_flags |=
1878 SNDRV_RAWMIDI_INFO_OUTPUT |
1879 SNDRV_RAWMIDI_INFO_INPUT |
1880 SNDRV_RAWMIDI_INFO_DUPLEX;
1881 } else {
1882 /* TCO MTC, read only */
1883 sprintf(buf, "%s MTC %d", card->shortname, id+1);
1884 err = snd_rawmidi_new(card, buf, id, 1, 1,
1885 &hdspm->midi[id].rmidi);
1886 if (err < 0)
1887 return err;
1888
1889 sprintf(hdspm->midi[id].rmidi->name,
1890 "%s MTC %d", card->id, id+1);
1891 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
1892
1893 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1894 SNDRV_RAWMIDI_STREAM_INPUT,
1895 &snd_hdspm_midi_input);
1896
1897 hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
1898 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001899
1900 return 0;
1901}
1902
1903
1904static void hdspm_midi_tasklet(unsigned long arg)
1905{
Takashi Iwai98274f02005-11-17 14:52:34 +01001906 struct hdspm *hdspm = (struct hdspm *)arg;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001907 int i = 0;
1908
1909 while (i < hdspm->midiPorts) {
1910 if (hdspm->midi[i].pending)
1911 snd_hdspm_midi_input_read(&hdspm->midi[i]);
1912
1913 i++;
1914 }
1915}
Takashi Iwai763f3562005-06-03 11:25:34 +02001916
1917
1918/*-----------------------------------------------------------------------------
1919 Status Interface
1920 ----------------------------------------------------------------------------*/
1921
1922/* get the system sample rate which is set */
1923
Adrian Knoth0dca1792011-01-26 19:32:14 +01001924
1925/**
1926 * Calculate the real sample rate from the
1927 * current DDS value.
1928 **/
1929static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
1930{
1931 unsigned int period, rate;
1932
1933 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
1934 rate = hdspm_calc_dds_value(hdspm, period);
1935
1936 return rate;
1937}
1938
1939
Takashi Iwai763f3562005-06-03 11:25:34 +02001940#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001941{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001942 .name = xname, \
1943 .index = xindex, \
1944 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1945 .info = snd_hdspm_info_system_sample_rate, \
1946 .get = snd_hdspm_get_system_sample_rate \
1947}
1948
Takashi Iwai98274f02005-11-17 14:52:34 +01001949static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
1950 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001951{
1952 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1953 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001954 uinfo->value.integer.min = 27000;
1955 uinfo->value.integer.max = 207000;
1956 uinfo->value.integer.step = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02001957 return 0;
1958}
1959
Adrian Knoth0dca1792011-01-26 19:32:14 +01001960
Takashi Iwai98274f02005-11-17 14:52:34 +01001961static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
1962 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02001963 ucontrol)
1964{
Takashi Iwai98274f02005-11-17 14:52:34 +01001965 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001966
Adrian Knoth0dca1792011-01-26 19:32:14 +01001967 ucontrol->value.integer.value[0] = hdspm_get_system_sample_rate(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001968 return 0;
1969}
1970
Adrian Knoth0dca1792011-01-26 19:32:14 +01001971
1972/**
1973 * Returns the WordClock sample rate class for the given card.
1974 **/
1975static int hdspm_get_wc_sample_rate(struct hdspm *hdspm)
1976{
1977 int status;
1978
1979 switch (hdspm->io_type) {
1980 case RayDAT:
1981 case AIO:
1982 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
1983 return (status >> 16) & 0xF;
1984 break;
1985 default:
1986 break;
1987 }
1988
1989
1990 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02001991}
1992
Adrian Knoth0dca1792011-01-26 19:32:14 +01001993
1994/**
1995 * Returns the TCO sample rate class for the given card.
1996 **/
1997static int hdspm_get_tco_sample_rate(struct hdspm *hdspm)
1998{
1999 int status;
2000
2001 if (hdspm->tco) {
2002 switch (hdspm->io_type) {
2003 case RayDAT:
2004 case AIO:
2005 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2006 return (status >> 20) & 0xF;
2007 break;
2008 default:
2009 break;
2010 }
2011 }
2012
2013 return 0;
2014}
2015
2016
2017/**
2018 * Returns the SYNC_IN sample rate class for the given card.
2019 **/
2020static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm)
2021{
2022 int status;
2023
2024 if (hdspm->tco) {
2025 switch (hdspm->io_type) {
2026 case RayDAT:
2027 case AIO:
2028 status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2029 return (status >> 12) & 0xF;
2030 break;
2031 default:
2032 break;
2033 }
2034 }
2035
2036 return 0;
2037}
2038
2039
2040/**
2041 * Returns the sample rate class for input source <idx> for
2042 * 'new style' cards like the AIO and RayDAT.
2043 **/
2044static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
2045{
2046 int status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2047
2048 return (status >> (idx*4)) & 0xF;
2049}
2050
2051
2052
2053#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
2054{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2055 .name = xname, \
2056 .private_value = xindex, \
2057 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2058 .info = snd_hdspm_info_autosync_sample_rate, \
2059 .get = snd_hdspm_get_autosync_sample_rate \
2060}
2061
2062
Takashi Iwai98274f02005-11-17 14:52:34 +01002063static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2064 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002065{
Takashi Iwai763f3562005-06-03 11:25:34 +02002066 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2067 uinfo->count = 1;
2068 uinfo->value.enumerated.items = 10;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002069
Takashi Iwai763f3562005-06-03 11:25:34 +02002070 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
Adrian Knoth0dca1792011-01-26 19:32:14 +01002071 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002072 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002073 texts_freq[uinfo->value.enumerated.item]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002074 return 0;
2075}
2076
Adrian Knoth0dca1792011-01-26 19:32:14 +01002077
Takashi Iwai98274f02005-11-17 14:52:34 +01002078static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2079 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002080 ucontrol)
2081{
Takashi Iwai98274f02005-11-17 14:52:34 +01002082 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002083
Adrian Knoth0dca1792011-01-26 19:32:14 +01002084 switch (hdspm->io_type) {
2085 case RayDAT:
2086 switch (kcontrol->private_value) {
2087 case 0:
2088 ucontrol->value.enumerated.item[0] =
2089 hdspm_get_wc_sample_rate(hdspm);
2090 break;
2091 case 7:
2092 ucontrol->value.enumerated.item[0] =
2093 hdspm_get_tco_sample_rate(hdspm);
2094 break;
2095 case 8:
2096 ucontrol->value.enumerated.item[0] =
2097 hdspm_get_sync_in_sample_rate(hdspm);
2098 break;
2099 default:
2100 ucontrol->value.enumerated.item[0] =
2101 hdspm_get_s1_sample_rate(hdspm,
2102 kcontrol->private_value-1);
2103 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002104
Adrian Knoth0dca1792011-01-26 19:32:14 +01002105 case AIO:
2106 switch (kcontrol->private_value) {
2107 case 0: /* WC */
2108 ucontrol->value.enumerated.item[0] =
2109 hdspm_get_wc_sample_rate(hdspm);
2110 break;
2111 case 4: /* TCO */
2112 ucontrol->value.enumerated.item[0] =
2113 hdspm_get_tco_sample_rate(hdspm);
2114 break;
2115 case 5: /* SYNC_IN */
2116 ucontrol->value.enumerated.item[0] =
2117 hdspm_get_sync_in_sample_rate(hdspm);
2118 break;
2119 default:
2120 ucontrol->value.enumerated.item[0] =
2121 hdspm_get_s1_sample_rate(hdspm,
2122 ucontrol->id.index-1);
2123 }
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002124
2125 case AES32:
2126
2127 switch (kcontrol->private_value) {
2128 case 0: /* WC */
2129 ucontrol->value.enumerated.item[0] =
2130 hdspm_get_wc_sample_rate(hdspm);
2131 break;
2132 case 9: /* TCO */
2133 ucontrol->value.enumerated.item[0] =
2134 hdspm_get_tco_sample_rate(hdspm);
2135 break;
2136 case 10: /* SYNC_IN */
2137 ucontrol->value.enumerated.item[0] =
2138 hdspm_get_sync_in_sample_rate(hdspm);
2139 break;
2140 default: /* AES1 to AES8 */
2141 ucontrol->value.enumerated.item[0] =
2142 hdspm_get_s1_sample_rate(hdspm,
2143 kcontrol->private_value-1);
2144 break;
2145
2146 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002147 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002148 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002149 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002150
Takashi Iwai763f3562005-06-03 11:25:34 +02002151 return 0;
2152}
2153
Adrian Knoth0dca1792011-01-26 19:32:14 +01002154
Takashi Iwai763f3562005-06-03 11:25:34 +02002155#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002156{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2157 .name = xname, \
2158 .index = xindex, \
2159 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2160 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2161 .info = snd_hdspm_info_system_clock_mode, \
2162 .get = snd_hdspm_get_system_clock_mode, \
2163 .put = snd_hdspm_put_system_clock_mode, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002164}
2165
2166
Adrian Knoth0dca1792011-01-26 19:32:14 +01002167/**
2168 * Returns the system clock mode for the given card.
2169 * @returns 0 - master, 1 - slave
2170 **/
2171static int hdspm_system_clock_mode(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002172{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002173 switch (hdspm->io_type) {
2174 case AIO:
2175 case RayDAT:
2176 if (hdspm->settings_register & HDSPM_c0Master)
2177 return 0;
2178 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002179
Adrian Knoth0dca1792011-01-26 19:32:14 +01002180 default:
2181 if (hdspm->control_register & HDSPM_ClockModeMaster)
2182 return 0;
2183 }
2184
Takashi Iwai763f3562005-06-03 11:25:34 +02002185 return 1;
2186}
2187
Adrian Knoth0dca1792011-01-26 19:32:14 +01002188
2189/**
2190 * Sets the system clock mode.
2191 * @param mode 0 - master, 1 - slave
2192 **/
2193static void hdspm_set_system_clock_mode(struct hdspm *hdspm, int mode)
2194{
2195 switch (hdspm->io_type) {
2196 case AIO:
2197 case RayDAT:
2198 if (0 == mode)
2199 hdspm->settings_register |= HDSPM_c0Master;
2200 else
2201 hdspm->settings_register &= ~HDSPM_c0Master;
2202
2203 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2204 break;
2205
2206 default:
2207 if (0 == mode)
2208 hdspm->control_register |= HDSPM_ClockModeMaster;
2209 else
2210 hdspm->control_register &= ~HDSPM_ClockModeMaster;
2211
2212 hdspm_write(hdspm, HDSPM_controlRegister,
2213 hdspm->control_register);
2214 }
2215}
2216
2217
Takashi Iwai98274f02005-11-17 14:52:34 +01002218static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
2219 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002220{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002221 static char *texts[] = { "Master", "AutoSync" };
Takashi Iwai763f3562005-06-03 11:25:34 +02002222
2223 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2224 uinfo->count = 1;
2225 uinfo->value.enumerated.items = 2;
2226 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2227 uinfo->value.enumerated.item =
2228 uinfo->value.enumerated.items - 1;
2229 strcpy(uinfo->value.enumerated.name,
2230 texts[uinfo->value.enumerated.item]);
2231 return 0;
2232}
2233
Takashi Iwai98274f02005-11-17 14:52:34 +01002234static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
2235 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002236{
Takashi Iwai98274f02005-11-17 14:52:34 +01002237 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002238
Adrian Knoth0dca1792011-01-26 19:32:14 +01002239 ucontrol->value.enumerated.item[0] = hdspm_system_clock_mode(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002240 return 0;
2241}
2242
Adrian Knoth0dca1792011-01-26 19:32:14 +01002243static int snd_hdspm_put_system_clock_mode(struct snd_kcontrol *kcontrol,
2244 struct snd_ctl_elem_value *ucontrol)
2245{
2246 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2247 int val;
2248
2249 if (!snd_hdspm_use_is_exclusive(hdspm))
2250 return -EBUSY;
2251
2252 val = ucontrol->value.enumerated.item[0];
2253 if (val < 0)
2254 val = 0;
2255 else if (val > 1)
2256 val = 1;
2257
2258 hdspm_set_system_clock_mode(hdspm, val);
2259
2260 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002261}
2262
Adrian Knoth0dca1792011-01-26 19:32:14 +01002263
2264#define HDSPM_INTERNAL_CLOCK(xname, xindex) \
2265{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2266 .name = xname, \
2267 .index = xindex, \
2268 .info = snd_hdspm_info_clock_source, \
2269 .get = snd_hdspm_get_clock_source, \
2270 .put = snd_hdspm_put_clock_source \
2271}
2272
2273
Takashi Iwai98274f02005-11-17 14:52:34 +01002274static int hdspm_clock_source(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002275{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002276 switch (hdspm->system_sample_rate) {
2277 case 32000: return 0;
2278 case 44100: return 1;
2279 case 48000: return 2;
2280 case 64000: return 3;
2281 case 88200: return 4;
2282 case 96000: return 5;
2283 case 128000: return 6;
2284 case 176400: return 7;
2285 case 192000: return 8;
Takashi Iwai763f3562005-06-03 11:25:34 +02002286 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002287
2288 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002289}
2290
Takashi Iwai98274f02005-11-17 14:52:34 +01002291static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
Takashi Iwai763f3562005-06-03 11:25:34 +02002292{
2293 int rate;
2294 switch (mode) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002295 case 0:
2296 rate = 32000; break;
2297 case 1:
2298 rate = 44100; break;
2299 case 2:
2300 rate = 48000; break;
2301 case 3:
2302 rate = 64000; break;
2303 case 4:
2304 rate = 88200; break;
2305 case 5:
2306 rate = 96000; break;
2307 case 6:
2308 rate = 128000; break;
2309 case 7:
2310 rate = 176400; break;
2311 case 8:
2312 rate = 192000; break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002313 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002314 rate = 48000;
Takashi Iwai763f3562005-06-03 11:25:34 +02002315 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002316 hdspm_set_rate(hdspm, rate, 1);
2317 return 0;
2318}
2319
Takashi Iwai98274f02005-11-17 14:52:34 +01002320static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
2321 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002322{
Takashi Iwai763f3562005-06-03 11:25:34 +02002323 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2324 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002325 uinfo->value.enumerated.items = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002326
2327 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2328 uinfo->value.enumerated.item =
2329 uinfo->value.enumerated.items - 1;
2330
2331 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002332 texts_freq[uinfo->value.enumerated.item+1]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002333
2334 return 0;
2335}
2336
Takashi Iwai98274f02005-11-17 14:52:34 +01002337static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
2338 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002339{
Takashi Iwai98274f02005-11-17 14:52:34 +01002340 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002341
2342 ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
2343 return 0;
2344}
2345
Takashi Iwai98274f02005-11-17 14:52:34 +01002346static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
2347 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002348{
Takashi Iwai98274f02005-11-17 14:52:34 +01002349 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002350 int change;
2351 int val;
2352
2353 if (!snd_hdspm_use_is_exclusive(hdspm))
2354 return -EBUSY;
2355 val = ucontrol->value.enumerated.item[0];
2356 if (val < 0)
2357 val = 0;
Remy Bruno65345992007-08-31 12:21:08 +02002358 if (val > 9)
2359 val = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002360 spin_lock_irq(&hdspm->lock);
2361 if (val != hdspm_clock_source(hdspm))
2362 change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
2363 else
2364 change = 0;
2365 spin_unlock_irq(&hdspm->lock);
2366 return change;
2367}
2368
Adrian Knoth0dca1792011-01-26 19:32:14 +01002369
Takashi Iwai763f3562005-06-03 11:25:34 +02002370#define HDSPM_PREF_SYNC_REF(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002371{.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2372 .name = xname, \
2373 .index = xindex, \
2374 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2375 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2376 .info = snd_hdspm_info_pref_sync_ref, \
2377 .get = snd_hdspm_get_pref_sync_ref, \
2378 .put = snd_hdspm_put_pref_sync_ref \
Takashi Iwai763f3562005-06-03 11:25:34 +02002379}
2380
Adrian Knoth0dca1792011-01-26 19:32:14 +01002381
2382/**
2383 * Returns the current preferred sync reference setting.
2384 * The semantics of the return value are depending on the
2385 * card, please see the comments for clarification.
2386 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002387static int hdspm_pref_sync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002388{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002389 switch (hdspm->io_type) {
2390 case AES32:
Remy Bruno3cee5a62006-10-16 12:46:32 +02002391 switch (hdspm->control_register & HDSPM_SyncRefMask) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002392 case 0: return 0; /* WC */
2393 case HDSPM_SyncRef0: return 1; /* AES 1 */
2394 case HDSPM_SyncRef1: return 2; /* AES 2 */
2395 case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; /* AES 3 */
2396 case HDSPM_SyncRef2: return 4; /* AES 4 */
2397 case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; /* AES 5 */
2398 case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; /* AES 6 */
2399 case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0:
2400 return 7; /* AES 7 */
2401 case HDSPM_SyncRef3: return 8; /* AES 8 */
2402 case HDSPM_SyncRef3+HDSPM_SyncRef0: return 9; /* TCO */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002403 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002404 break;
2405
2406 case MADI:
2407 case MADIface:
2408 if (hdspm->tco) {
2409 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2410 case 0: return 0; /* WC */
2411 case HDSPM_SyncRef0: return 1; /* MADI */
2412 case HDSPM_SyncRef1: return 2; /* TCO */
2413 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2414 return 3; /* SYNC_IN */
2415 }
2416 } else {
2417 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2418 case 0: return 0; /* WC */
2419 case HDSPM_SyncRef0: return 1; /* MADI */
2420 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2421 return 2; /* SYNC_IN */
2422 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02002423 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002424 break;
2425
2426 case RayDAT:
2427 if (hdspm->tco) {
2428 switch ((hdspm->settings_register &
2429 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2430 case 0: return 0; /* WC */
2431 case 3: return 1; /* ADAT 1 */
2432 case 4: return 2; /* ADAT 2 */
2433 case 5: return 3; /* ADAT 3 */
2434 case 6: return 4; /* ADAT 4 */
2435 case 1: return 5; /* AES */
2436 case 2: return 6; /* SPDIF */
2437 case 9: return 7; /* TCO */
2438 case 10: return 8; /* SYNC_IN */
2439 }
2440 } else {
2441 switch ((hdspm->settings_register &
2442 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2443 case 0: return 0; /* WC */
2444 case 3: return 1; /* ADAT 1 */
2445 case 4: return 2; /* ADAT 2 */
2446 case 5: return 3; /* ADAT 3 */
2447 case 6: return 4; /* ADAT 4 */
2448 case 1: return 5; /* AES */
2449 case 2: return 6; /* SPDIF */
2450 case 10: return 7; /* SYNC_IN */
2451 }
2452 }
2453
2454 break;
2455
2456 case AIO:
2457 if (hdspm->tco) {
2458 switch ((hdspm->settings_register &
2459 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2460 case 0: return 0; /* WC */
2461 case 3: return 1; /* ADAT */
2462 case 1: return 2; /* AES */
2463 case 2: return 3; /* SPDIF */
2464 case 9: return 4; /* TCO */
2465 case 10: return 5; /* SYNC_IN */
2466 }
2467 } else {
2468 switch ((hdspm->settings_register &
2469 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2470 case 0: return 0; /* WC */
2471 case 3: return 1; /* ADAT */
2472 case 1: return 2; /* AES */
2473 case 2: return 3; /* SPDIF */
2474 case 10: return 4; /* SYNC_IN */
2475 }
2476 }
2477
2478 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002479 }
2480
Adrian Knoth0dca1792011-01-26 19:32:14 +01002481 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002482}
2483
Adrian Knoth0dca1792011-01-26 19:32:14 +01002484
2485/**
2486 * Set the preferred sync reference to <pref>. The semantics
2487 * of <pref> are depending on the card type, see the comments
2488 * for clarification.
2489 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002490static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
Takashi Iwai763f3562005-06-03 11:25:34 +02002491{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002492 int p = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002493
Adrian Knoth0dca1792011-01-26 19:32:14 +01002494 switch (hdspm->io_type) {
2495 case AES32:
2496 hdspm->control_register &= ~HDSPM_SyncRefMask;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002497 switch (pref) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002498 case 0: /* WC */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002499 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002500 case 1: /* AES 1 */
2501 hdspm->control_register |= HDSPM_SyncRef0;
2502 break;
2503 case 2: /* AES 2 */
2504 hdspm->control_register |= HDSPM_SyncRef1;
2505 break;
2506 case 3: /* AES 3 */
2507 hdspm->control_register |=
2508 HDSPM_SyncRef1+HDSPM_SyncRef0;
2509 break;
2510 case 4: /* AES 4 */
2511 hdspm->control_register |= HDSPM_SyncRef2;
2512 break;
2513 case 5: /* AES 5 */
2514 hdspm->control_register |=
2515 HDSPM_SyncRef2+HDSPM_SyncRef0;
2516 break;
2517 case 6: /* AES 6 */
2518 hdspm->control_register |=
2519 HDSPM_SyncRef2+HDSPM_SyncRef1;
2520 break;
2521 case 7: /* AES 7 */
2522 hdspm->control_register |=
2523 HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
2524 break;
2525 case 8: /* AES 8 */
2526 hdspm->control_register |= HDSPM_SyncRef3;
2527 break;
2528 case 9: /* TCO */
2529 hdspm->control_register |=
2530 HDSPM_SyncRef3+HDSPM_SyncRef0;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002531 break;
2532 default:
2533 return -1;
2534 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002535
2536 break;
2537
2538 case MADI:
2539 case MADIface:
2540 hdspm->control_register &= ~HDSPM_SyncRefMask;
2541 if (hdspm->tco) {
2542 switch (pref) {
2543 case 0: /* WC */
2544 break;
2545 case 1: /* MADI */
2546 hdspm->control_register |= HDSPM_SyncRef0;
2547 break;
2548 case 2: /* TCO */
2549 hdspm->control_register |= HDSPM_SyncRef1;
2550 break;
2551 case 3: /* SYNC_IN */
2552 hdspm->control_register |=
2553 HDSPM_SyncRef0+HDSPM_SyncRef1;
2554 break;
2555 default:
2556 return -1;
2557 }
2558 } else {
2559 switch (pref) {
2560 case 0: /* WC */
2561 break;
2562 case 1: /* MADI */
2563 hdspm->control_register |= HDSPM_SyncRef0;
2564 break;
2565 case 2: /* SYNC_IN */
2566 hdspm->control_register |=
2567 HDSPM_SyncRef0+HDSPM_SyncRef1;
2568 break;
2569 default:
2570 return -1;
2571 }
2572 }
2573
2574 break;
2575
2576 case RayDAT:
2577 if (hdspm->tco) {
2578 switch (pref) {
2579 case 0: p = 0; break; /* WC */
2580 case 1: p = 3; break; /* ADAT 1 */
2581 case 2: p = 4; break; /* ADAT 2 */
2582 case 3: p = 5; break; /* ADAT 3 */
2583 case 4: p = 6; break; /* ADAT 4 */
2584 case 5: p = 1; break; /* AES */
2585 case 6: p = 2; break; /* SPDIF */
2586 case 7: p = 9; break; /* TCO */
2587 case 8: p = 10; break; /* SYNC_IN */
2588 default: return -1;
2589 }
2590 } else {
2591 switch (pref) {
2592 case 0: p = 0; break; /* WC */
2593 case 1: p = 3; break; /* ADAT 1 */
2594 case 2: p = 4; break; /* ADAT 2 */
2595 case 3: p = 5; break; /* ADAT 3 */
2596 case 4: p = 6; break; /* ADAT 4 */
2597 case 5: p = 1; break; /* AES */
2598 case 6: p = 2; break; /* SPDIF */
2599 case 7: p = 10; break; /* SYNC_IN */
2600 default: return -1;
2601 }
2602 }
2603 break;
2604
2605 case AIO:
2606 if (hdspm->tco) {
2607 switch (pref) {
2608 case 0: p = 0; break; /* WC */
2609 case 1: p = 3; break; /* ADAT */
2610 case 2: p = 1; break; /* AES */
2611 case 3: p = 2; break; /* SPDIF */
2612 case 4: p = 9; break; /* TCO */
2613 case 5: p = 10; break; /* SYNC_IN */
2614 default: return -1;
2615 }
2616 } else {
2617 switch (pref) {
2618 case 0: p = 0; break; /* WC */
2619 case 1: p = 3; break; /* ADAT */
2620 case 2: p = 1; break; /* AES */
2621 case 3: p = 2; break; /* SPDIF */
2622 case 4: p = 10; break; /* SYNC_IN */
2623 default: return -1;
2624 }
2625 }
2626 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002627 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002628
2629 switch (hdspm->io_type) {
2630 case RayDAT:
2631 case AIO:
2632 hdspm->settings_register &= ~HDSPM_c0_SyncRefMask;
2633 hdspm->settings_register |= HDSPM_c0_SyncRef0 * p;
2634 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2635 break;
2636
2637 case MADI:
2638 case MADIface:
2639 case AES32:
2640 hdspm_write(hdspm, HDSPM_controlRegister,
2641 hdspm->control_register);
2642 }
2643
Takashi Iwai763f3562005-06-03 11:25:34 +02002644 return 0;
2645}
2646
Adrian Knoth0dca1792011-01-26 19:32:14 +01002647
Takashi Iwai98274f02005-11-17 14:52:34 +01002648static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
2649 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002650{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002651 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002652
Adrian Knoth0dca1792011-01-26 19:32:14 +01002653 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2654 uinfo->count = 1;
2655 uinfo->value.enumerated.items = hdspm->texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +02002656
Adrian Knoth0dca1792011-01-26 19:32:14 +01002657 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2658 uinfo->value.enumerated.item =
2659 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002660
Adrian Knoth0dca1792011-01-26 19:32:14 +01002661 strcpy(uinfo->value.enumerated.name,
2662 hdspm->texts_autosync[uinfo->value.enumerated.item]);
Remy Bruno3cee5a62006-10-16 12:46:32 +02002663
Takashi Iwai763f3562005-06-03 11:25:34 +02002664 return 0;
2665}
2666
Takashi Iwai98274f02005-11-17 14:52:34 +01002667static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
2668 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002669{
Takashi Iwai98274f02005-11-17 14:52:34 +01002670 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002671 int psf = hdspm_pref_sync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002672
Adrian Knoth0dca1792011-01-26 19:32:14 +01002673 if (psf >= 0) {
2674 ucontrol->value.enumerated.item[0] = psf;
2675 return 0;
2676 }
2677
2678 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002679}
2680
Takashi Iwai98274f02005-11-17 14:52:34 +01002681static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
2682 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002683{
Takashi Iwai98274f02005-11-17 14:52:34 +01002684 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002685 int val, change = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002686
2687 if (!snd_hdspm_use_is_exclusive(hdspm))
2688 return -EBUSY;
2689
Adrian Knoth0dca1792011-01-26 19:32:14 +01002690 val = ucontrol->value.enumerated.item[0];
2691
2692 if (val < 0)
2693 val = 0;
2694 else if (val >= hdspm->texts_autosync_items)
2695 val = hdspm->texts_autosync_items-1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002696
2697 spin_lock_irq(&hdspm->lock);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002698 if (val != hdspm_pref_sync_ref(hdspm))
2699 change = (0 == hdspm_set_pref_sync_ref(hdspm, val)) ? 1 : 0;
2700
Takashi Iwai763f3562005-06-03 11:25:34 +02002701 spin_unlock_irq(&hdspm->lock);
2702 return change;
2703}
2704
Adrian Knoth0dca1792011-01-26 19:32:14 +01002705
Takashi Iwai763f3562005-06-03 11:25:34 +02002706#define HDSPM_AUTOSYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002707{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002708 .name = xname, \
2709 .index = xindex, \
2710 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2711 .info = snd_hdspm_info_autosync_ref, \
2712 .get = snd_hdspm_get_autosync_ref, \
2713}
2714
Adrian Knoth0dca1792011-01-26 19:32:14 +01002715static int hdspm_autosync_ref(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002716{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002717 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002718 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002719 unsigned int syncref =
2720 (status >> HDSPM_AES32_syncref_bit) & 0xF;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002721 if (syncref == 0)
2722 return HDSPM_AES32_AUTOSYNC_FROM_WORD;
2723 if (syncref <= 8)
2724 return syncref;
2725 return HDSPM_AES32_AUTOSYNC_FROM_NONE;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002726 } else if (MADI == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002727 /* This looks at the autosync selected sync reference */
2728 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Takashi Iwai763f3562005-06-03 11:25:34 +02002729
Remy Bruno3cee5a62006-10-16 12:46:32 +02002730 switch (status2 & HDSPM_SelSyncRefMask) {
2731 case HDSPM_SelSyncRef_WORD:
2732 return HDSPM_AUTOSYNC_FROM_WORD;
2733 case HDSPM_SelSyncRef_MADI:
2734 return HDSPM_AUTOSYNC_FROM_MADI;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002735 case HDSPM_SelSyncRef_TCO:
2736 return HDSPM_AUTOSYNC_FROM_TCO;
2737 case HDSPM_SelSyncRef_SyncIn:
2738 return HDSPM_AUTOSYNC_FROM_SYNC_IN;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002739 case HDSPM_SelSyncRef_NVALID:
2740 return HDSPM_AUTOSYNC_FROM_NONE;
2741 default:
2742 return 0;
2743 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002744
Takashi Iwai763f3562005-06-03 11:25:34 +02002745 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002746 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002747}
2748
Adrian Knoth0dca1792011-01-26 19:32:14 +01002749
Takashi Iwai98274f02005-11-17 14:52:34 +01002750static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
2751 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002752{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002753 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002754
Adrian Knoth0dca1792011-01-26 19:32:14 +01002755 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002756 static char *texts[] = { "WordClock", "AES1", "AES2", "AES3",
2757 "AES4", "AES5", "AES6", "AES7", "AES8", "None"};
2758
2759 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2760 uinfo->count = 1;
2761 uinfo->value.enumerated.items = 10;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002762 if (uinfo->value.enumerated.item >=
2763 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002764 uinfo->value.enumerated.item =
2765 uinfo->value.enumerated.items - 1;
2766 strcpy(uinfo->value.enumerated.name,
2767 texts[uinfo->value.enumerated.item]);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002768 } else if (MADI == hdspm->io_type) {
2769 static char *texts[] = {"Word Clock", "MADI", "TCO",
2770 "Sync In", "None" };
Remy Bruno3cee5a62006-10-16 12:46:32 +02002771
2772 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2773 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002774 uinfo->value.enumerated.items = 5;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002775 if (uinfo->value.enumerated.item >=
Adrian Knoth0dca1792011-01-26 19:32:14 +01002776 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002777 uinfo->value.enumerated.item =
2778 uinfo->value.enumerated.items - 1;
2779 strcpy(uinfo->value.enumerated.name,
2780 texts[uinfo->value.enumerated.item]);
2781 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002782 return 0;
2783}
2784
Takashi Iwai98274f02005-11-17 14:52:34 +01002785static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
2786 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002787{
Takashi Iwai98274f02005-11-17 14:52:34 +01002788 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002789
Remy Bruno65345992007-08-31 12:21:08 +02002790 ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002791 return 0;
2792}
2793
Adrian Knoth0dca1792011-01-26 19:32:14 +01002794
Takashi Iwai763f3562005-06-03 11:25:34 +02002795#define HDSPM_LINE_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002796{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002797 .name = xname, \
2798 .index = xindex, \
2799 .info = snd_hdspm_info_line_out, \
2800 .get = snd_hdspm_get_line_out, \
2801 .put = snd_hdspm_put_line_out \
2802}
2803
Takashi Iwai98274f02005-11-17 14:52:34 +01002804static int hdspm_line_out(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002805{
2806 return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0;
2807}
2808
2809
Takashi Iwai98274f02005-11-17 14:52:34 +01002810static int hdspm_set_line_output(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002811{
2812 if (out)
2813 hdspm->control_register |= HDSPM_LineOut;
2814 else
2815 hdspm->control_register &= ~HDSPM_LineOut;
2816 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2817
2818 return 0;
2819}
2820
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002821#define snd_hdspm_info_line_out snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002822
Takashi Iwai98274f02005-11-17 14:52:34 +01002823static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol,
2824 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002825{
Takashi Iwai98274f02005-11-17 14:52:34 +01002826 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002827
2828 spin_lock_irq(&hdspm->lock);
2829 ucontrol->value.integer.value[0] = hdspm_line_out(hdspm);
2830 spin_unlock_irq(&hdspm->lock);
2831 return 0;
2832}
2833
Takashi Iwai98274f02005-11-17 14:52:34 +01002834static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
2835 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002836{
Takashi Iwai98274f02005-11-17 14:52:34 +01002837 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002838 int change;
2839 unsigned int val;
2840
2841 if (!snd_hdspm_use_is_exclusive(hdspm))
2842 return -EBUSY;
2843 val = ucontrol->value.integer.value[0] & 1;
2844 spin_lock_irq(&hdspm->lock);
2845 change = (int) val != hdspm_line_out(hdspm);
2846 hdspm_set_line_output(hdspm, val);
2847 spin_unlock_irq(&hdspm->lock);
2848 return change;
2849}
2850
Adrian Knoth0dca1792011-01-26 19:32:14 +01002851
Takashi Iwai763f3562005-06-03 11:25:34 +02002852#define HDSPM_TX_64(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002853{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002854 .name = xname, \
2855 .index = xindex, \
2856 .info = snd_hdspm_info_tx_64, \
2857 .get = snd_hdspm_get_tx_64, \
2858 .put = snd_hdspm_put_tx_64 \
2859}
2860
Takashi Iwai98274f02005-11-17 14:52:34 +01002861static int hdspm_tx_64(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002862{
2863 return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0;
2864}
2865
Takashi Iwai98274f02005-11-17 14:52:34 +01002866static int hdspm_set_tx_64(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002867{
2868 if (out)
2869 hdspm->control_register |= HDSPM_TX_64ch;
2870 else
2871 hdspm->control_register &= ~HDSPM_TX_64ch;
2872 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2873
2874 return 0;
2875}
2876
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002877#define snd_hdspm_info_tx_64 snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002878
Takashi Iwai98274f02005-11-17 14:52:34 +01002879static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol,
2880 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002881{
Takashi Iwai98274f02005-11-17 14:52:34 +01002882 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002883
2884 spin_lock_irq(&hdspm->lock);
2885 ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm);
2886 spin_unlock_irq(&hdspm->lock);
2887 return 0;
2888}
2889
Takashi Iwai98274f02005-11-17 14:52:34 +01002890static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
2891 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002892{
Takashi Iwai98274f02005-11-17 14:52:34 +01002893 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002894 int change;
2895 unsigned int val;
2896
2897 if (!snd_hdspm_use_is_exclusive(hdspm))
2898 return -EBUSY;
2899 val = ucontrol->value.integer.value[0] & 1;
2900 spin_lock_irq(&hdspm->lock);
2901 change = (int) val != hdspm_tx_64(hdspm);
2902 hdspm_set_tx_64(hdspm, val);
2903 spin_unlock_irq(&hdspm->lock);
2904 return change;
2905}
2906
Adrian Knoth0dca1792011-01-26 19:32:14 +01002907
Takashi Iwai763f3562005-06-03 11:25:34 +02002908#define HDSPM_C_TMS(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002909{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002910 .name = xname, \
2911 .index = xindex, \
2912 .info = snd_hdspm_info_c_tms, \
2913 .get = snd_hdspm_get_c_tms, \
2914 .put = snd_hdspm_put_c_tms \
2915}
2916
Takashi Iwai98274f02005-11-17 14:52:34 +01002917static int hdspm_c_tms(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002918{
2919 return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0;
2920}
2921
Takashi Iwai98274f02005-11-17 14:52:34 +01002922static int hdspm_set_c_tms(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002923{
2924 if (out)
2925 hdspm->control_register |= HDSPM_clr_tms;
2926 else
2927 hdspm->control_register &= ~HDSPM_clr_tms;
2928 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2929
2930 return 0;
2931}
2932
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002933#define snd_hdspm_info_c_tms snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002934
Takashi Iwai98274f02005-11-17 14:52:34 +01002935static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol,
2936 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002937{
Takashi Iwai98274f02005-11-17 14:52:34 +01002938 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002939
2940 spin_lock_irq(&hdspm->lock);
2941 ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm);
2942 spin_unlock_irq(&hdspm->lock);
2943 return 0;
2944}
2945
Takashi Iwai98274f02005-11-17 14:52:34 +01002946static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,
2947 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002948{
Takashi Iwai98274f02005-11-17 14:52:34 +01002949 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002950 int change;
2951 unsigned int val;
2952
2953 if (!snd_hdspm_use_is_exclusive(hdspm))
2954 return -EBUSY;
2955 val = ucontrol->value.integer.value[0] & 1;
2956 spin_lock_irq(&hdspm->lock);
2957 change = (int) val != hdspm_c_tms(hdspm);
2958 hdspm_set_c_tms(hdspm, val);
2959 spin_unlock_irq(&hdspm->lock);
2960 return change;
2961}
2962
Adrian Knoth0dca1792011-01-26 19:32:14 +01002963
Takashi Iwai763f3562005-06-03 11:25:34 +02002964#define HDSPM_SAFE_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002965{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002966 .name = xname, \
2967 .index = xindex, \
2968 .info = snd_hdspm_info_safe_mode, \
2969 .get = snd_hdspm_get_safe_mode, \
2970 .put = snd_hdspm_put_safe_mode \
2971}
2972
Takashi Iwai98274f02005-11-17 14:52:34 +01002973static int hdspm_safe_mode(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002974{
2975 return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0;
2976}
2977
Takashi Iwai98274f02005-11-17 14:52:34 +01002978static int hdspm_set_safe_mode(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002979{
2980 if (out)
2981 hdspm->control_register |= HDSPM_AutoInp;
2982 else
2983 hdspm->control_register &= ~HDSPM_AutoInp;
2984 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2985
2986 return 0;
2987}
2988
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002989#define snd_hdspm_info_safe_mode snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002990
Takashi Iwai98274f02005-11-17 14:52:34 +01002991static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol,
2992 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002993{
Takashi Iwai98274f02005-11-17 14:52:34 +01002994 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002995
2996 spin_lock_irq(&hdspm->lock);
2997 ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm);
2998 spin_unlock_irq(&hdspm->lock);
2999 return 0;
3000}
3001
Takashi Iwai98274f02005-11-17 14:52:34 +01003002static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
3003 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003004{
Takashi Iwai98274f02005-11-17 14:52:34 +01003005 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003006 int change;
3007 unsigned int val;
3008
3009 if (!snd_hdspm_use_is_exclusive(hdspm))
3010 return -EBUSY;
3011 val = ucontrol->value.integer.value[0] & 1;
3012 spin_lock_irq(&hdspm->lock);
3013 change = (int) val != hdspm_safe_mode(hdspm);
3014 hdspm_set_safe_mode(hdspm, val);
3015 spin_unlock_irq(&hdspm->lock);
3016 return change;
3017}
3018
Adrian Knoth0dca1792011-01-26 19:32:14 +01003019
Remy Bruno3cee5a62006-10-16 12:46:32 +02003020#define HDSPM_EMPHASIS(xname, xindex) \
3021{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3022 .name = xname, \
3023 .index = xindex, \
3024 .info = snd_hdspm_info_emphasis, \
3025 .get = snd_hdspm_get_emphasis, \
3026 .put = snd_hdspm_put_emphasis \
3027}
3028
3029static int hdspm_emphasis(struct hdspm * hdspm)
3030{
3031 return (hdspm->control_register & HDSPM_Emphasis) ? 1 : 0;
3032}
3033
3034static int hdspm_set_emphasis(struct hdspm * hdspm, int emp)
3035{
3036 if (emp)
3037 hdspm->control_register |= HDSPM_Emphasis;
3038 else
3039 hdspm->control_register &= ~HDSPM_Emphasis;
3040 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3041
3042 return 0;
3043}
3044
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003045#define snd_hdspm_info_emphasis snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02003046
3047static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol,
3048 struct snd_ctl_elem_value *ucontrol)
3049{
3050 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3051
3052 spin_lock_irq(&hdspm->lock);
3053 ucontrol->value.enumerated.item[0] = hdspm_emphasis(hdspm);
3054 spin_unlock_irq(&hdspm->lock);
3055 return 0;
3056}
3057
3058static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
3059 struct snd_ctl_elem_value *ucontrol)
3060{
3061 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3062 int change;
3063 unsigned int val;
3064
3065 if (!snd_hdspm_use_is_exclusive(hdspm))
3066 return -EBUSY;
3067 val = ucontrol->value.integer.value[0] & 1;
3068 spin_lock_irq(&hdspm->lock);
3069 change = (int) val != hdspm_emphasis(hdspm);
3070 hdspm_set_emphasis(hdspm, val);
3071 spin_unlock_irq(&hdspm->lock);
3072 return change;
3073}
3074
Adrian Knoth0dca1792011-01-26 19:32:14 +01003075
Remy Bruno3cee5a62006-10-16 12:46:32 +02003076#define HDSPM_DOLBY(xname, xindex) \
3077{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3078 .name = xname, \
3079 .index = xindex, \
3080 .info = snd_hdspm_info_dolby, \
3081 .get = snd_hdspm_get_dolby, \
3082 .put = snd_hdspm_put_dolby \
3083}
3084
3085static int hdspm_dolby(struct hdspm * hdspm)
3086{
3087 return (hdspm->control_register & HDSPM_Dolby) ? 1 : 0;
3088}
3089
3090static int hdspm_set_dolby(struct hdspm * hdspm, int dol)
3091{
3092 if (dol)
3093 hdspm->control_register |= HDSPM_Dolby;
3094 else
3095 hdspm->control_register &= ~HDSPM_Dolby;
3096 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3097
3098 return 0;
3099}
3100
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003101#define snd_hdspm_info_dolby snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02003102
3103static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol,
3104 struct snd_ctl_elem_value *ucontrol)
3105{
3106 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3107
3108 spin_lock_irq(&hdspm->lock);
3109 ucontrol->value.enumerated.item[0] = hdspm_dolby(hdspm);
3110 spin_unlock_irq(&hdspm->lock);
3111 return 0;
3112}
3113
3114static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
3115 struct snd_ctl_elem_value *ucontrol)
3116{
3117 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3118 int change;
3119 unsigned int val;
3120
3121 if (!snd_hdspm_use_is_exclusive(hdspm))
3122 return -EBUSY;
3123 val = ucontrol->value.integer.value[0] & 1;
3124 spin_lock_irq(&hdspm->lock);
3125 change = (int) val != hdspm_dolby(hdspm);
3126 hdspm_set_dolby(hdspm, val);
3127 spin_unlock_irq(&hdspm->lock);
3128 return change;
3129}
3130
Adrian Knoth0dca1792011-01-26 19:32:14 +01003131
Remy Bruno3cee5a62006-10-16 12:46:32 +02003132#define HDSPM_PROFESSIONAL(xname, xindex) \
3133{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3134 .name = xname, \
3135 .index = xindex, \
3136 .info = snd_hdspm_info_professional, \
3137 .get = snd_hdspm_get_professional, \
3138 .put = snd_hdspm_put_professional \
3139}
3140
3141static int hdspm_professional(struct hdspm * hdspm)
3142{
3143 return (hdspm->control_register & HDSPM_Professional) ? 1 : 0;
3144}
3145
3146static int hdspm_set_professional(struct hdspm * hdspm, int dol)
3147{
3148 if (dol)
3149 hdspm->control_register |= HDSPM_Professional;
3150 else
3151 hdspm->control_register &= ~HDSPM_Professional;
3152 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3153
3154 return 0;
3155}
3156
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003157#define snd_hdspm_info_professional snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02003158
3159static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol,
3160 struct snd_ctl_elem_value *ucontrol)
3161{
3162 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3163
3164 spin_lock_irq(&hdspm->lock);
3165 ucontrol->value.enumerated.item[0] = hdspm_professional(hdspm);
3166 spin_unlock_irq(&hdspm->lock);
3167 return 0;
3168}
3169
3170static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,
3171 struct snd_ctl_elem_value *ucontrol)
3172{
3173 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3174 int change;
3175 unsigned int val;
3176
3177 if (!snd_hdspm_use_is_exclusive(hdspm))
3178 return -EBUSY;
3179 val = ucontrol->value.integer.value[0] & 1;
3180 spin_lock_irq(&hdspm->lock);
3181 change = (int) val != hdspm_professional(hdspm);
3182 hdspm_set_professional(hdspm, val);
3183 spin_unlock_irq(&hdspm->lock);
3184 return change;
3185}
3186
Takashi Iwai763f3562005-06-03 11:25:34 +02003187#define HDSPM_INPUT_SELECT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003188{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003189 .name = xname, \
3190 .index = xindex, \
3191 .info = snd_hdspm_info_input_select, \
3192 .get = snd_hdspm_get_input_select, \
3193 .put = snd_hdspm_put_input_select \
3194}
3195
Takashi Iwai98274f02005-11-17 14:52:34 +01003196static int hdspm_input_select(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003197{
3198 return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
3199}
3200
Takashi Iwai98274f02005-11-17 14:52:34 +01003201static int hdspm_set_input_select(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02003202{
3203 if (out)
3204 hdspm->control_register |= HDSPM_InputSelect0;
3205 else
3206 hdspm->control_register &= ~HDSPM_InputSelect0;
3207 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3208
3209 return 0;
3210}
3211
Takashi Iwai98274f02005-11-17 14:52:34 +01003212static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
3213 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003214{
3215 static char *texts[] = { "optical", "coaxial" };
3216
3217 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3218 uinfo->count = 1;
3219 uinfo->value.enumerated.items = 2;
3220
3221 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3222 uinfo->value.enumerated.item =
3223 uinfo->value.enumerated.items - 1;
3224 strcpy(uinfo->value.enumerated.name,
3225 texts[uinfo->value.enumerated.item]);
3226
3227 return 0;
3228}
3229
Takashi Iwai98274f02005-11-17 14:52:34 +01003230static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
3231 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003232{
Takashi Iwai98274f02005-11-17 14:52:34 +01003233 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003234
3235 spin_lock_irq(&hdspm->lock);
3236 ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
3237 spin_unlock_irq(&hdspm->lock);
3238 return 0;
3239}
3240
Takashi Iwai98274f02005-11-17 14:52:34 +01003241static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
3242 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003243{
Takashi Iwai98274f02005-11-17 14:52:34 +01003244 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003245 int change;
3246 unsigned int val;
3247
3248 if (!snd_hdspm_use_is_exclusive(hdspm))
3249 return -EBUSY;
3250 val = ucontrol->value.integer.value[0] & 1;
3251 spin_lock_irq(&hdspm->lock);
3252 change = (int) val != hdspm_input_select(hdspm);
3253 hdspm_set_input_select(hdspm, val);
3254 spin_unlock_irq(&hdspm->lock);
3255 return change;
3256}
3257
Adrian Knoth0dca1792011-01-26 19:32:14 +01003258
Remy Bruno3cee5a62006-10-16 12:46:32 +02003259#define HDSPM_DS_WIRE(xname, xindex) \
3260{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3261 .name = xname, \
3262 .index = xindex, \
3263 .info = snd_hdspm_info_ds_wire, \
3264 .get = snd_hdspm_get_ds_wire, \
3265 .put = snd_hdspm_put_ds_wire \
3266}
3267
3268static int hdspm_ds_wire(struct hdspm * hdspm)
3269{
3270 return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
3271}
3272
3273static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
3274{
3275 if (ds)
3276 hdspm->control_register |= HDSPM_DS_DoubleWire;
3277 else
3278 hdspm->control_register &= ~HDSPM_DS_DoubleWire;
3279 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3280
3281 return 0;
3282}
3283
3284static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
3285 struct snd_ctl_elem_info *uinfo)
3286{
3287 static char *texts[] = { "Single", "Double" };
3288
3289 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3290 uinfo->count = 1;
3291 uinfo->value.enumerated.items = 2;
3292
3293 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3294 uinfo->value.enumerated.item =
3295 uinfo->value.enumerated.items - 1;
3296 strcpy(uinfo->value.enumerated.name,
3297 texts[uinfo->value.enumerated.item]);
3298
3299 return 0;
3300}
3301
3302static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
3303 struct snd_ctl_elem_value *ucontrol)
3304{
3305 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3306
3307 spin_lock_irq(&hdspm->lock);
3308 ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
3309 spin_unlock_irq(&hdspm->lock);
3310 return 0;
3311}
3312
3313static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
3314 struct snd_ctl_elem_value *ucontrol)
3315{
3316 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3317 int change;
3318 unsigned int val;
3319
3320 if (!snd_hdspm_use_is_exclusive(hdspm))
3321 return -EBUSY;
3322 val = ucontrol->value.integer.value[0] & 1;
3323 spin_lock_irq(&hdspm->lock);
3324 change = (int) val != hdspm_ds_wire(hdspm);
3325 hdspm_set_ds_wire(hdspm, val);
3326 spin_unlock_irq(&hdspm->lock);
3327 return change;
3328}
3329
Adrian Knoth0dca1792011-01-26 19:32:14 +01003330
Remy Bruno3cee5a62006-10-16 12:46:32 +02003331#define HDSPM_QS_WIRE(xname, xindex) \
3332{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3333 .name = xname, \
3334 .index = xindex, \
3335 .info = snd_hdspm_info_qs_wire, \
3336 .get = snd_hdspm_get_qs_wire, \
3337 .put = snd_hdspm_put_qs_wire \
3338}
3339
3340static int hdspm_qs_wire(struct hdspm * hdspm)
3341{
3342 if (hdspm->control_register & HDSPM_QS_DoubleWire)
3343 return 1;
3344 if (hdspm->control_register & HDSPM_QS_QuadWire)
3345 return 2;
3346 return 0;
3347}
3348
3349static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
3350{
3351 hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
3352 switch (mode) {
3353 case 0:
3354 break;
3355 case 1:
3356 hdspm->control_register |= HDSPM_QS_DoubleWire;
3357 break;
3358 case 2:
3359 hdspm->control_register |= HDSPM_QS_QuadWire;
3360 break;
3361 }
3362 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3363
3364 return 0;
3365}
3366
3367static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
3368 struct snd_ctl_elem_info *uinfo)
3369{
3370 static char *texts[] = { "Single", "Double", "Quad" };
3371
3372 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3373 uinfo->count = 1;
3374 uinfo->value.enumerated.items = 3;
3375
3376 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3377 uinfo->value.enumerated.item =
3378 uinfo->value.enumerated.items - 1;
3379 strcpy(uinfo->value.enumerated.name,
3380 texts[uinfo->value.enumerated.item]);
3381
3382 return 0;
3383}
3384
3385static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
3386 struct snd_ctl_elem_value *ucontrol)
3387{
3388 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3389
3390 spin_lock_irq(&hdspm->lock);
3391 ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
3392 spin_unlock_irq(&hdspm->lock);
3393 return 0;
3394}
3395
3396static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
3397 struct snd_ctl_elem_value *ucontrol)
3398{
3399 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3400 int change;
3401 int val;
3402
3403 if (!snd_hdspm_use_is_exclusive(hdspm))
3404 return -EBUSY;
3405 val = ucontrol->value.integer.value[0];
3406 if (val < 0)
3407 val = 0;
3408 if (val > 2)
3409 val = 2;
3410 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003411 change = val != hdspm_qs_wire(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003412 hdspm_set_qs_wire(hdspm, val);
3413 spin_unlock_irq(&hdspm->lock);
3414 return change;
3415}
3416
Takashi Iwai763f3562005-06-03 11:25:34 +02003417
3418#define HDSPM_MIXER(xname, xindex) \
3419{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
3420 .name = xname, \
3421 .index = xindex, \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003422 .device = 0, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003423 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
3424 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3425 .info = snd_hdspm_info_mixer, \
3426 .get = snd_hdspm_get_mixer, \
3427 .put = snd_hdspm_put_mixer \
3428}
3429
Takashi Iwai98274f02005-11-17 14:52:34 +01003430static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
3431 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003432{
3433 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3434 uinfo->count = 3;
3435 uinfo->value.integer.min = 0;
3436 uinfo->value.integer.max = 65535;
3437 uinfo->value.integer.step = 1;
3438 return 0;
3439}
3440
Takashi Iwai98274f02005-11-17 14:52:34 +01003441static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
3442 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003443{
Takashi Iwai98274f02005-11-17 14:52:34 +01003444 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003445 int source;
3446 int destination;
3447
3448 source = ucontrol->value.integer.value[0];
3449 if (source < 0)
3450 source = 0;
3451 else if (source >= 2 * HDSPM_MAX_CHANNELS)
3452 source = 2 * HDSPM_MAX_CHANNELS - 1;
3453
3454 destination = ucontrol->value.integer.value[1];
3455 if (destination < 0)
3456 destination = 0;
3457 else if (destination >= HDSPM_MAX_CHANNELS)
3458 destination = HDSPM_MAX_CHANNELS - 1;
3459
3460 spin_lock_irq(&hdspm->lock);
3461 if (source >= HDSPM_MAX_CHANNELS)
3462 ucontrol->value.integer.value[2] =
3463 hdspm_read_pb_gain(hdspm, destination,
3464 source - HDSPM_MAX_CHANNELS);
3465 else
3466 ucontrol->value.integer.value[2] =
3467 hdspm_read_in_gain(hdspm, destination, source);
3468
3469 spin_unlock_irq(&hdspm->lock);
3470
3471 return 0;
3472}
3473
Takashi Iwai98274f02005-11-17 14:52:34 +01003474static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
3475 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003476{
Takashi Iwai98274f02005-11-17 14:52:34 +01003477 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003478 int change;
3479 int source;
3480 int destination;
3481 int gain;
3482
3483 if (!snd_hdspm_use_is_exclusive(hdspm))
3484 return -EBUSY;
3485
3486 source = ucontrol->value.integer.value[0];
3487 destination = ucontrol->value.integer.value[1];
3488
3489 if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
3490 return -1;
3491 if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
3492 return -1;
3493
3494 gain = ucontrol->value.integer.value[2];
3495
3496 spin_lock_irq(&hdspm->lock);
3497
3498 if (source >= HDSPM_MAX_CHANNELS)
3499 change = gain != hdspm_read_pb_gain(hdspm, destination,
3500 source -
3501 HDSPM_MAX_CHANNELS);
3502 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003503 change = gain != hdspm_read_in_gain(hdspm, destination,
3504 source);
Takashi Iwai763f3562005-06-03 11:25:34 +02003505
3506 if (change) {
3507 if (source >= HDSPM_MAX_CHANNELS)
3508 hdspm_write_pb_gain(hdspm, destination,
3509 source - HDSPM_MAX_CHANNELS,
3510 gain);
3511 else
3512 hdspm_write_in_gain(hdspm, destination, source,
3513 gain);
3514 }
3515 spin_unlock_irq(&hdspm->lock);
3516
3517 return change;
3518}
3519
3520/* The simple mixer control(s) provide gain control for the
3521 basic 1:1 mappings of playback streams to output
Adrian Knoth0dca1792011-01-26 19:32:14 +01003522 streams.
Takashi Iwai763f3562005-06-03 11:25:34 +02003523*/
3524
3525#define HDSPM_PLAYBACK_MIXER \
3526{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3527 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
3528 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3529 .info = snd_hdspm_info_playback_mixer, \
3530 .get = snd_hdspm_get_playback_mixer, \
3531 .put = snd_hdspm_put_playback_mixer \
3532}
3533
Takashi Iwai98274f02005-11-17 14:52:34 +01003534static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
3535 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003536{
3537 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3538 uinfo->count = 1;
3539 uinfo->value.integer.min = 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003540 uinfo->value.integer.max = 64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003541 uinfo->value.integer.step = 1;
3542 return 0;
3543}
3544
Takashi Iwai98274f02005-11-17 14:52:34 +01003545static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
3546 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003547{
Takashi Iwai98274f02005-11-17 14:52:34 +01003548 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003549 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003550
3551 channel = ucontrol->id.index - 1;
3552
Takashi Iwaida3cec32008-08-08 17:12:14 +02003553 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3554 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003555
Takashi Iwai763f3562005-06-03 11:25:34 +02003556 spin_lock_irq(&hdspm->lock);
3557 ucontrol->value.integer.value[0] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003558 (hdspm_read_pb_gain(hdspm, channel, channel)*64)/UNITY_GAIN;
Takashi Iwai763f3562005-06-03 11:25:34 +02003559 spin_unlock_irq(&hdspm->lock);
3560
Takashi Iwai763f3562005-06-03 11:25:34 +02003561 return 0;
3562}
3563
Takashi Iwai98274f02005-11-17 14:52:34 +01003564static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
3565 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003566{
Takashi Iwai98274f02005-11-17 14:52:34 +01003567 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003568 int change;
3569 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003570 int gain;
3571
3572 if (!snd_hdspm_use_is_exclusive(hdspm))
3573 return -EBUSY;
3574
3575 channel = ucontrol->id.index - 1;
3576
Takashi Iwaida3cec32008-08-08 17:12:14 +02003577 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3578 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003579
Adrian Knoth0dca1792011-01-26 19:32:14 +01003580 gain = ucontrol->value.integer.value[0]*UNITY_GAIN/64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003581
3582 spin_lock_irq(&hdspm->lock);
3583 change =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003584 gain != hdspm_read_pb_gain(hdspm, channel,
3585 channel);
Takashi Iwai763f3562005-06-03 11:25:34 +02003586 if (change)
Adrian Knoth0dca1792011-01-26 19:32:14 +01003587 hdspm_write_pb_gain(hdspm, channel, channel,
Takashi Iwai763f3562005-06-03 11:25:34 +02003588 gain);
3589 spin_unlock_irq(&hdspm->lock);
3590 return change;
3591}
3592
Adrian Knoth0dca1792011-01-26 19:32:14 +01003593#define HDSPM_SYNC_CHECK(xname, xindex) \
3594{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3595 .name = xname, \
3596 .private_value = xindex, \
3597 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3598 .info = snd_hdspm_info_sync_check, \
3599 .get = snd_hdspm_get_sync_check \
Takashi Iwai763f3562005-06-03 11:25:34 +02003600}
3601
Adrian Knoth0dca1792011-01-26 19:32:14 +01003602
Takashi Iwai98274f02005-11-17 14:52:34 +01003603static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
3604 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003605{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003606 static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" };
Takashi Iwai763f3562005-06-03 11:25:34 +02003607 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3608 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003609 uinfo->value.enumerated.items = 4;
Takashi Iwai763f3562005-06-03 11:25:34 +02003610 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3611 uinfo->value.enumerated.item =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003612 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02003613 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01003614 texts[uinfo->value.enumerated.item]);
Takashi Iwai763f3562005-06-03 11:25:34 +02003615 return 0;
3616}
3617
Adrian Knoth0dca1792011-01-26 19:32:14 +01003618static int hdspm_wc_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003619{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003620 int status, status2;
3621
3622 switch (hdspm->io_type) {
3623 case AES32:
3624 status = hdspm_read(hdspm, HDSPM_statusRegister);
3625 if (status & HDSPM_wcSync)
Takashi Iwai763f3562005-06-03 11:25:34 +02003626 return 2;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003627 else if (status & HDSPM_wcLock)
3628 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003629 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003630 break;
3631
3632 case MADI:
3633 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003634 if (status2 & HDSPM_wcLock) {
3635 if (status2 & HDSPM_wcSync)
3636 return 2;
3637 else
3638 return 1;
3639 }
3640 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003641 break;
3642
3643 case RayDAT:
3644 case AIO:
3645 status = hdspm_read(hdspm, HDSPM_statusRegister);
3646
3647 if (status & 0x2000000)
3648 return 2;
3649 else if (status & 0x1000000)
3650 return 1;
3651 return 0;
3652
3653 break;
3654
3655 case MADIface:
3656 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02003657 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003658
Takashi Iwai763f3562005-06-03 11:25:34 +02003659
Adrian Knoth0dca1792011-01-26 19:32:14 +01003660 return 3;
Takashi Iwai763f3562005-06-03 11:25:34 +02003661}
3662
3663
Adrian Knoth0dca1792011-01-26 19:32:14 +01003664static int hdspm_madi_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003665{
3666 int status = hdspm_read(hdspm, HDSPM_statusRegister);
3667 if (status & HDSPM_madiLock) {
3668 if (status & HDSPM_madiSync)
3669 return 2;
3670 else
3671 return 1;
3672 }
3673 return 0;
3674}
3675
Adrian Knoth0dca1792011-01-26 19:32:14 +01003676
3677static int hdspm_s1_sync_check(struct hdspm *hdspm, int idx)
3678{
3679 int status, lock, sync;
3680
3681 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3682
3683 lock = (status & (0x1<<idx)) ? 1 : 0;
3684 sync = (status & (0x100<<idx)) ? 1 : 0;
3685
3686 if (lock && sync)
3687 return 2;
3688 else if (lock)
3689 return 1;
3690 return 0;
3691}
3692
3693
3694static int hdspm_sync_in_sync_check(struct hdspm *hdspm)
3695{
3696 int status, lock = 0, sync = 0;
3697
3698 switch (hdspm->io_type) {
3699 case RayDAT:
3700 case AIO:
3701 status = hdspm_read(hdspm, HDSPM_RD_STATUS_3);
3702 lock = (status & 0x400) ? 1 : 0;
3703 sync = (status & 0x800) ? 1 : 0;
3704 break;
3705
3706 case MADI:
3707 case AES32:
3708 status = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knotha7edbd52011-02-23 11:43:15 +01003709 lock = (status & HDSPM_syncInLock) ? 1 : 0;
3710 sync = (status & HDSPM_syncInSync) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003711 break;
3712
3713 case MADIface:
3714 break;
3715 }
3716
3717 if (lock && sync)
3718 return 2;
3719 else if (lock)
3720 return 1;
3721
3722 return 0;
3723}
3724
3725static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx)
3726{
3727 int status2, lock, sync;
3728 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
3729
3730 lock = (status2 & (0x0080 >> idx)) ? 1 : 0;
3731 sync = (status2 & (0x8000 >> idx)) ? 1 : 0;
3732
3733 if (sync)
3734 return 2;
3735 else if (lock)
3736 return 1;
3737 return 0;
3738}
3739
3740
3741static int hdspm_tco_sync_check(struct hdspm *hdspm)
3742{
3743 int status;
3744
3745 if (hdspm->tco) {
3746 switch (hdspm->io_type) {
3747 case MADI:
3748 case AES32:
3749 status = hdspm_read(hdspm, HDSPM_statusRegister);
3750 if (status & HDSPM_tcoLock) {
3751 if (status & HDSPM_tcoSync)
3752 return 2;
3753 else
3754 return 1;
3755 }
3756 return 0;
3757
3758 break;
3759
3760 case RayDAT:
3761 case AIO:
3762 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3763
3764 if (status & 0x8000000)
3765 return 2; /* Sync */
3766 if (status & 0x4000000)
3767 return 1; /* Lock */
3768 return 0; /* No signal */
3769 break;
3770
3771 default:
3772 break;
3773 }
3774 }
3775
3776 return 3; /* N/A */
3777}
3778
3779
3780static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
3781 struct snd_ctl_elem_value *ucontrol)
3782{
3783 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3784 int val = -1;
3785
3786 switch (hdspm->io_type) {
3787 case RayDAT:
3788 switch (kcontrol->private_value) {
3789 case 0: /* WC */
3790 val = hdspm_wc_sync_check(hdspm); break;
3791 case 7: /* TCO */
3792 val = hdspm_tco_sync_check(hdspm); break;
3793 case 8: /* SYNC IN */
3794 val = hdspm_sync_in_sync_check(hdspm); break;
3795 default:
3796 val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
3797 }
3798
3799 case AIO:
3800 switch (kcontrol->private_value) {
3801 case 0: /* WC */
3802 val = hdspm_wc_sync_check(hdspm); break;
3803 case 4: /* TCO */
3804 val = hdspm_tco_sync_check(hdspm); break;
3805 case 5: /* SYNC IN */
3806 val = hdspm_sync_in_sync_check(hdspm); break;
3807 default:
3808 val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
3809 }
3810
3811 case MADI:
3812 switch (kcontrol->private_value) {
3813 case 0: /* WC */
3814 val = hdspm_wc_sync_check(hdspm); break;
3815 case 1: /* MADI */
3816 val = hdspm_madi_sync_check(hdspm); break;
3817 case 2: /* TCO */
3818 val = hdspm_tco_sync_check(hdspm); break;
3819 case 3: /* SYNC_IN */
3820 val = hdspm_sync_in_sync_check(hdspm); break;
3821 }
3822
3823 case MADIface:
3824 val = hdspm_madi_sync_check(hdspm); /* MADI */
3825 break;
3826
3827 case AES32:
3828 switch (kcontrol->private_value) {
3829 case 0: /* WC */
3830 val = hdspm_wc_sync_check(hdspm); break;
3831 case 9: /* TCO */
3832 val = hdspm_tco_sync_check(hdspm); break;
3833 case 10 /* SYNC IN */:
3834 val = hdspm_sync_in_sync_check(hdspm); break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01003835 default: /* AES1 to AES8 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01003836 val = hdspm_aes_sync_check(hdspm,
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01003837 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003838 }
3839
3840 }
3841
3842 if (-1 == val)
3843 val = 3;
3844
3845 ucontrol->value.enumerated.item[0] = val;
3846 return 0;
3847}
3848
3849
3850
3851/**
3852 * TCO controls
3853 **/
3854static void hdspm_tco_write(struct hdspm *hdspm)
3855{
3856 unsigned int tc[4] = { 0, 0, 0, 0};
3857
3858 switch (hdspm->tco->input) {
3859 case 0:
3860 tc[2] |= HDSPM_TCO2_set_input_MSB;
3861 break;
3862 case 1:
3863 tc[2] |= HDSPM_TCO2_set_input_LSB;
3864 break;
3865 default:
3866 break;
3867 }
3868
3869 switch (hdspm->tco->framerate) {
3870 case 1:
3871 tc[1] |= HDSPM_TCO1_LTC_Format_LSB;
3872 break;
3873 case 2:
3874 tc[1] |= HDSPM_TCO1_LTC_Format_MSB;
3875 break;
3876 case 3:
3877 tc[1] |= HDSPM_TCO1_LTC_Format_MSB +
3878 HDSPM_TCO1_set_drop_frame_flag;
3879 break;
3880 case 4:
3881 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
3882 HDSPM_TCO1_LTC_Format_MSB;
3883 break;
3884 case 5:
3885 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
3886 HDSPM_TCO1_LTC_Format_MSB +
3887 HDSPM_TCO1_set_drop_frame_flag;
3888 break;
3889 default:
3890 break;
3891 }
3892
3893 switch (hdspm->tco->wordclock) {
3894 case 1:
3895 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_LSB;
3896 break;
3897 case 2:
3898 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_MSB;
3899 break;
3900 default:
3901 break;
3902 }
3903
3904 switch (hdspm->tco->samplerate) {
3905 case 1:
3906 tc[2] |= HDSPM_TCO2_set_freq;
3907 break;
3908 case 2:
3909 tc[2] |= HDSPM_TCO2_set_freq_from_app;
3910 break;
3911 default:
3912 break;
3913 }
3914
3915 switch (hdspm->tco->pull) {
3916 case 1:
3917 tc[2] |= HDSPM_TCO2_set_pull_up;
3918 break;
3919 case 2:
3920 tc[2] |= HDSPM_TCO2_set_pull_down;
3921 break;
3922 case 3:
3923 tc[2] |= HDSPM_TCO2_set_pull_up + HDSPM_TCO2_set_01_4;
3924 break;
3925 case 4:
3926 tc[2] |= HDSPM_TCO2_set_pull_down + HDSPM_TCO2_set_01_4;
3927 break;
3928 default:
3929 break;
3930 }
3931
3932 if (1 == hdspm->tco->term) {
3933 tc[2] |= HDSPM_TCO2_set_term_75R;
3934 }
3935
3936 hdspm_write(hdspm, HDSPM_WR_TCO, tc[0]);
3937 hdspm_write(hdspm, HDSPM_WR_TCO+4, tc[1]);
3938 hdspm_write(hdspm, HDSPM_WR_TCO+8, tc[2]);
3939 hdspm_write(hdspm, HDSPM_WR_TCO+12, tc[3]);
3940}
3941
3942
3943#define HDSPM_TCO_SAMPLE_RATE(xname, xindex) \
3944{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3945 .name = xname, \
3946 .index = xindex, \
3947 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
3948 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3949 .info = snd_hdspm_info_tco_sample_rate, \
3950 .get = snd_hdspm_get_tco_sample_rate, \
3951 .put = snd_hdspm_put_tco_sample_rate \
3952}
3953
3954static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol,
3955 struct snd_ctl_elem_info *uinfo)
3956{
3957 static char *texts[] = { "44.1 kHz", "48 kHz" };
3958 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3959 uinfo->count = 1;
3960 uinfo->value.enumerated.items = 2;
3961
3962 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3963 uinfo->value.enumerated.item =
3964 uinfo->value.enumerated.items - 1;
3965
3966 strcpy(uinfo->value.enumerated.name,
3967 texts[uinfo->value.enumerated.item]);
3968
3969 return 0;
3970}
3971
3972static int snd_hdspm_get_tco_sample_rate(struct snd_kcontrol *kcontrol,
3973 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003974{
Takashi Iwai98274f02005-11-17 14:52:34 +01003975 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003976
Adrian Knoth0dca1792011-01-26 19:32:14 +01003977 ucontrol->value.enumerated.item[0] = hdspm->tco->samplerate;
3978
Takashi Iwai763f3562005-06-03 11:25:34 +02003979 return 0;
3980}
3981
Adrian Knoth0dca1792011-01-26 19:32:14 +01003982static int snd_hdspm_put_tco_sample_rate(struct snd_kcontrol *kcontrol,
3983 struct snd_ctl_elem_value *ucontrol)
Remy Bruno3cee5a62006-10-16 12:46:32 +02003984{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003985 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3986
3987 if (hdspm->tco->samplerate != ucontrol->value.enumerated.item[0]) {
3988 hdspm->tco->samplerate = ucontrol->value.enumerated.item[0];
3989
3990 hdspm_tco_write(hdspm);
3991
3992 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003993 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01003994
Remy Bruno3cee5a62006-10-16 12:46:32 +02003995 return 0;
3996}
3997
Adrian Knoth0dca1792011-01-26 19:32:14 +01003998
3999#define HDSPM_TCO_PULL(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_pull, \
4006 .get = snd_hdspm_get_tco_pull, \
4007 .put = snd_hdspm_put_tco_pull \
4008}
4009
4010static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol,
4011 struct snd_ctl_elem_info *uinfo)
4012{
4013 static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" };
4014 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4015 uinfo->count = 1;
4016 uinfo->value.enumerated.items = 5;
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_pull(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->pull;
4034
4035 return 0;
4036}
4037
4038static int snd_hdspm_put_tco_pull(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->pull != ucontrol->value.enumerated.item[0]) {
4044 hdspm->tco->pull = ucontrol->value.enumerated.item[0];
4045
4046 hdspm_tco_write(hdspm);
4047
4048 return 1;
4049 }
4050
4051 return 0;
4052}
4053
4054#define HDSPM_TCO_WCK_CONVERSION(xname, xindex) \
4055{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4056 .name = xname, \
4057 .index = xindex, \
4058 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4059 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4060 .info = snd_hdspm_info_tco_wck_conversion, \
4061 .get = snd_hdspm_get_tco_wck_conversion, \
4062 .put = snd_hdspm_put_tco_wck_conversion \
4063}
4064
4065static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4066 struct snd_ctl_elem_info *uinfo)
4067{
4068 static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
4069 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4070 uinfo->count = 1;
4071 uinfo->value.enumerated.items = 3;
4072
4073 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4074 uinfo->value.enumerated.item =
4075 uinfo->value.enumerated.items - 1;
4076
4077 strcpy(uinfo->value.enumerated.name,
4078 texts[uinfo->value.enumerated.item]);
4079
4080 return 0;
4081}
4082
4083static int snd_hdspm_get_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4084 struct snd_ctl_elem_value *ucontrol)
4085{
4086 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4087
4088 ucontrol->value.enumerated.item[0] = hdspm->tco->wordclock;
4089
4090 return 0;
4091}
4092
4093static int snd_hdspm_put_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4094 struct snd_ctl_elem_value *ucontrol)
4095{
4096 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4097
4098 if (hdspm->tco->wordclock != ucontrol->value.enumerated.item[0]) {
4099 hdspm->tco->wordclock = ucontrol->value.enumerated.item[0];
4100
4101 hdspm_tco_write(hdspm);
4102
4103 return 1;
4104 }
4105
4106 return 0;
4107}
4108
4109
4110#define HDSPM_TCO_FRAME_RATE(xname, xindex) \
4111{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4112 .name = xname, \
4113 .index = xindex, \
4114 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4115 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4116 .info = snd_hdspm_info_tco_frame_rate, \
4117 .get = snd_hdspm_get_tco_frame_rate, \
4118 .put = snd_hdspm_put_tco_frame_rate \
4119}
4120
4121static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol,
4122 struct snd_ctl_elem_info *uinfo)
4123{
4124 static char *texts[] = { "24 fps", "25 fps", "29.97fps",
4125 "29.97 dfps", "30 fps", "30 dfps" };
4126 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4127 uinfo->count = 1;
4128 uinfo->value.enumerated.items = 6;
4129
4130 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4131 uinfo->value.enumerated.item =
4132 uinfo->value.enumerated.items - 1;
4133
4134 strcpy(uinfo->value.enumerated.name,
4135 texts[uinfo->value.enumerated.item]);
4136
4137 return 0;
4138}
4139
4140static int snd_hdspm_get_tco_frame_rate(struct snd_kcontrol *kcontrol,
Remy Bruno3cee5a62006-10-16 12:46:32 +02004141 struct snd_ctl_elem_value *ucontrol)
4142{
Remy Bruno3cee5a62006-10-16 12:46:32 +02004143 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4144
Adrian Knoth0dca1792011-01-26 19:32:14 +01004145 ucontrol->value.enumerated.item[0] = hdspm->tco->framerate;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004146
Remy Bruno3cee5a62006-10-16 12:46:32 +02004147 return 0;
4148}
Takashi Iwai763f3562005-06-03 11:25:34 +02004149
Adrian Knoth0dca1792011-01-26 19:32:14 +01004150static int snd_hdspm_put_tco_frame_rate(struct snd_kcontrol *kcontrol,
4151 struct snd_ctl_elem_value *ucontrol)
4152{
4153 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4154
4155 if (hdspm->tco->framerate != ucontrol->value.enumerated.item[0]) {
4156 hdspm->tco->framerate = ucontrol->value.enumerated.item[0];
4157
4158 hdspm_tco_write(hdspm);
4159
4160 return 1;
4161 }
4162
4163 return 0;
4164}
4165
4166
4167#define HDSPM_TCO_SYNC_SOURCE(xname, xindex) \
4168{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4169 .name = xname, \
4170 .index = xindex, \
4171 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4172 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4173 .info = snd_hdspm_info_tco_sync_source, \
4174 .get = snd_hdspm_get_tco_sync_source, \
4175 .put = snd_hdspm_put_tco_sync_source \
4176}
4177
4178static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol,
4179 struct snd_ctl_elem_info *uinfo)
4180{
4181 static char *texts[] = { "LTC", "Video", "WCK" };
4182 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4183 uinfo->count = 1;
4184 uinfo->value.enumerated.items = 3;
4185
4186 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4187 uinfo->value.enumerated.item =
4188 uinfo->value.enumerated.items - 1;
4189
4190 strcpy(uinfo->value.enumerated.name,
4191 texts[uinfo->value.enumerated.item]);
4192
4193 return 0;
4194}
4195
4196static int snd_hdspm_get_tco_sync_source(struct snd_kcontrol *kcontrol,
4197 struct snd_ctl_elem_value *ucontrol)
4198{
4199 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4200
4201 ucontrol->value.enumerated.item[0] = hdspm->tco->input;
4202
4203 return 0;
4204}
4205
4206static int snd_hdspm_put_tco_sync_source(struct snd_kcontrol *kcontrol,
4207 struct snd_ctl_elem_value *ucontrol)
4208{
4209 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4210
4211 if (hdspm->tco->input != ucontrol->value.enumerated.item[0]) {
4212 hdspm->tco->input = ucontrol->value.enumerated.item[0];
4213
4214 hdspm_tco_write(hdspm);
4215
4216 return 1;
4217 }
4218
4219 return 0;
4220}
4221
4222
4223#define HDSPM_TCO_WORD_TERM(xname, xindex) \
4224{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4225 .name = xname, \
4226 .index = xindex, \
4227 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4228 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4229 .info = snd_hdspm_info_tco_word_term, \
4230 .get = snd_hdspm_get_tco_word_term, \
4231 .put = snd_hdspm_put_tco_word_term \
4232}
4233
4234static int snd_hdspm_info_tco_word_term(struct snd_kcontrol *kcontrol,
4235 struct snd_ctl_elem_info *uinfo)
4236{
4237 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
4238 uinfo->count = 1;
4239 uinfo->value.integer.min = 0;
4240 uinfo->value.integer.max = 1;
4241
4242 return 0;
4243}
4244
4245
4246static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol,
4247 struct snd_ctl_elem_value *ucontrol)
4248{
4249 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4250
4251 ucontrol->value.enumerated.item[0] = hdspm->tco->term;
4252
4253 return 0;
4254}
4255
4256
4257static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol,
4258 struct snd_ctl_elem_value *ucontrol)
4259{
4260 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4261
4262 if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) {
4263 hdspm->tco->term = ucontrol->value.enumerated.item[0];
4264
4265 hdspm_tco_write(hdspm);
4266
4267 return 1;
4268 }
4269
4270 return 0;
4271}
4272
4273
4274
Takashi Iwai763f3562005-06-03 11:25:34 +02004275
Remy Bruno3cee5a62006-10-16 12:46:32 +02004276static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004277 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004278 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Takashi Iwai763f3562005-06-03 11:25:34 +02004279 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4280 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4281 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4282 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004283 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4284 HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
4285 HDSPM_SYNC_CHECK("TCO SyncCHeck", 2),
4286 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
Takashi Iwai763f3562005-06-03 11:25:34 +02004287 HDSPM_LINE_OUT("Line Out", 0),
4288 HDSPM_TX_64("TX 64 channels mode", 0),
4289 HDSPM_C_TMS("Clear Track Marker", 0),
4290 HDSPM_SAFE_MODE("Safe Mode", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004291 HDSPM_INPUT_SELECT("Input Select", 0)
4292};
4293
4294
4295static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
4296 HDSPM_MIXER("Mixer", 0),
4297 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4298 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4299 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4300 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4301 HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
4302 HDSPM_TX_64("TX 64 channels mode", 0),
4303 HDSPM_C_TMS("Clear Track Marker", 0),
Adrian Knothf6ea8052011-02-23 11:43:12 +01004304 HDSPM_SAFE_MODE("Safe Mode", 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004305};
4306
Adrian Knoth0dca1792011-01-26 19:32:14 +01004307static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004308 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004309 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004310 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4311 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4312 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4313 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004314 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004315 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4316 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4317 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4318 HDSPM_SYNC_CHECK("ADAT SyncCheck", 3),
4319 HDSPM_SYNC_CHECK("TCO SyncCheck", 4),
4320 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 5),
4321 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4322 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4323 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4324 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT Frequency", 3),
4325 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 4),
4326 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5)
4327
4328 /*
4329 HDSPM_INPUT_SELECT("Input Select", 0),
4330 HDSPM_SPDIF_OPTICAL("SPDIF Out Optical", 0),
4331 HDSPM_PROFESSIONAL("SPDIF Out Professional", 0);
4332 HDSPM_SPDIF_IN("SPDIF In", 0);
4333 HDSPM_BREAKOUT_CABLE("Breakout Cable", 0);
4334 HDSPM_INPUT_LEVEL("Input Level", 0);
4335 HDSPM_OUTPUT_LEVEL("Output Level", 0);
4336 HDSPM_PHONES("Phones", 0);
4337 */
4338};
4339
4340static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = {
4341 HDSPM_MIXER("Mixer", 0),
4342 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4343 HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0),
4344 HDSPM_PREF_SYNC_REF("Pref Sync Ref", 0),
4345 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4346 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4347 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4348 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4349 HDSPM_SYNC_CHECK("ADAT1 SyncCheck", 3),
4350 HDSPM_SYNC_CHECK("ADAT2 SyncCheck", 4),
4351 HDSPM_SYNC_CHECK("ADAT3 SyncCheck", 5),
4352 HDSPM_SYNC_CHECK("ADAT4 SyncCheck", 6),
4353 HDSPM_SYNC_CHECK("TCO SyncCheck", 7),
4354 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 8),
4355 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4356 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4357 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4358 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT1 Frequency", 3),
4359 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT2 Frequency", 4),
4360 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT3 Frequency", 5),
4361 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT4 Frequency", 6),
4362 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 7),
4363 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8)
4364};
4365
4366static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
4367 HDSPM_MIXER("Mixer", 0),
4368 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4369 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4370 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4371 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4372 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4373 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4374 HDSPM_SYNC_CHECK("WC Sync Check", 0),
4375 HDSPM_SYNC_CHECK("AES1 Sync Check", 1),
4376 HDSPM_SYNC_CHECK("AES2 Sync Check", 2),
4377 HDSPM_SYNC_CHECK("AES3 Sync Check", 3),
4378 HDSPM_SYNC_CHECK("AES4 Sync Check", 4),
4379 HDSPM_SYNC_CHECK("AES5 Sync Check", 5),
4380 HDSPM_SYNC_CHECK("AES6 Sync Check", 6),
4381 HDSPM_SYNC_CHECK("AES7 Sync Check", 7),
4382 HDSPM_SYNC_CHECK("AES8 Sync Check", 8),
4383 HDSPM_SYNC_CHECK("TCO Sync Check", 9),
4384 HDSPM_SYNC_CHECK("SYNC IN Sync Check", 10),
4385 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4386 HDSPM_AUTOSYNC_SAMPLE_RATE("AES1 Frequency", 1),
4387 HDSPM_AUTOSYNC_SAMPLE_RATE("AES2 Frequency", 2),
4388 HDSPM_AUTOSYNC_SAMPLE_RATE("AES3 Frequency", 3),
4389 HDSPM_AUTOSYNC_SAMPLE_RATE("AES4 Frequency", 4),
4390 HDSPM_AUTOSYNC_SAMPLE_RATE("AES5 Frequency", 5),
4391 HDSPM_AUTOSYNC_SAMPLE_RATE("AES6 Frequency", 6),
4392 HDSPM_AUTOSYNC_SAMPLE_RATE("AES7 Frequency", 7),
4393 HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8),
4394 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9),
4395 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004396 HDSPM_LINE_OUT("Line Out", 0),
4397 HDSPM_EMPHASIS("Emphasis", 0),
4398 HDSPM_DOLBY("Non Audio", 0),
4399 HDSPM_PROFESSIONAL("Professional", 0),
4400 HDSPM_C_TMS("Clear Track Marker", 0),
4401 HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
4402 HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
4403};
4404
Adrian Knoth0dca1792011-01-26 19:32:14 +01004405
4406
4407/* Control elements for the optional TCO module */
4408static struct snd_kcontrol_new snd_hdspm_controls_tco[] = {
4409 HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0),
4410 HDSPM_TCO_PULL("TCO Pull", 0),
4411 HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0),
4412 HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0),
4413 HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0),
4414 HDSPM_TCO_WORD_TERM("TCO Word Term", 0)
4415};
4416
4417
Takashi Iwai98274f02005-11-17 14:52:34 +01004418static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
Takashi Iwai763f3562005-06-03 11:25:34 +02004419
4420
Takashi Iwai98274f02005-11-17 14:52:34 +01004421static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004422{
4423 int i;
4424
Adrian Knoth0dca1792011-01-26 19:32:14 +01004425 for (i = hdspm->ds_out_channels; i < hdspm->ss_out_channels; ++i) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004426 if (hdspm->system_sample_rate > 48000) {
4427 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004428 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
4429 SNDRV_CTL_ELEM_ACCESS_READ |
4430 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004431 } else {
4432 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004433 SNDRV_CTL_ELEM_ACCESS_READWRITE |
4434 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004435 }
4436 snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
Adrian Knoth0dca1792011-01-26 19:32:14 +01004437 SNDRV_CTL_EVENT_MASK_INFO,
4438 &hdspm->playback_mixer_ctls[i]->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02004439 }
4440
4441 return 0;
4442}
4443
4444
Adrian Knoth0dca1792011-01-26 19:32:14 +01004445static int snd_hdspm_create_controls(struct snd_card *card,
4446 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004447{
4448 unsigned int idx, limit;
4449 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01004450 struct snd_kcontrol *kctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004451 struct snd_kcontrol_new *list = NULL;
Takashi Iwai763f3562005-06-03 11:25:34 +02004452
Adrian Knoth0dca1792011-01-26 19:32:14 +01004453 switch (hdspm->io_type) {
4454 case MADI:
4455 list = snd_hdspm_controls_madi;
4456 limit = ARRAY_SIZE(snd_hdspm_controls_madi);
4457 break;
4458 case MADIface:
4459 list = snd_hdspm_controls_madiface;
4460 limit = ARRAY_SIZE(snd_hdspm_controls_madiface);
4461 break;
4462 case AIO:
4463 list = snd_hdspm_controls_aio;
4464 limit = ARRAY_SIZE(snd_hdspm_controls_aio);
4465 break;
4466 case RayDAT:
4467 list = snd_hdspm_controls_raydat;
4468 limit = ARRAY_SIZE(snd_hdspm_controls_raydat);
4469 break;
4470 case AES32:
4471 list = snd_hdspm_controls_aes32;
4472 limit = ARRAY_SIZE(snd_hdspm_controls_aes32);
4473 break;
4474 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004475
Adrian Knoth0dca1792011-01-26 19:32:14 +01004476 if (NULL != list) {
4477 for (idx = 0; idx < limit; idx++) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004478 err = snd_ctl_add(card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004479 snd_ctl_new1(&list[idx], hdspm));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004480 if (err < 0)
4481 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004482 }
4483 }
4484
Takashi Iwai763f3562005-06-03 11:25:34 +02004485
Adrian Knoth0dca1792011-01-26 19:32:14 +01004486 /* create simple 1:1 playback mixer controls */
Takashi Iwai763f3562005-06-03 11:25:34 +02004487 snd_hdspm_playback_mixer.name = "Chn";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004488 if (hdspm->system_sample_rate >= 128000) {
4489 limit = hdspm->qs_out_channels;
4490 } else if (hdspm->system_sample_rate >= 64000) {
4491 limit = hdspm->ds_out_channels;
4492 } else {
4493 limit = hdspm->ss_out_channels;
4494 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004495 for (idx = 0; idx < limit; ++idx) {
4496 snd_hdspm_playback_mixer.index = idx + 1;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004497 kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm);
4498 err = snd_ctl_add(card, kctl);
4499 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004500 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004501 hdspm->playback_mixer_ctls[idx] = kctl;
4502 }
4503
Adrian Knoth0dca1792011-01-26 19:32:14 +01004504
4505 if (hdspm->tco) {
4506 /* add tco control elements */
4507 list = snd_hdspm_controls_tco;
4508 limit = ARRAY_SIZE(snd_hdspm_controls_tco);
4509 for (idx = 0; idx < limit; idx++) {
4510 err = snd_ctl_add(card,
4511 snd_ctl_new1(&list[idx], hdspm));
4512 if (err < 0)
4513 return err;
4514 }
4515 }
4516
Takashi Iwai763f3562005-06-03 11:25:34 +02004517 return 0;
4518}
4519
4520/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01004521 /proc interface
Takashi Iwai763f3562005-06-03 11:25:34 +02004522 ------------------------------------------------------------*/
4523
4524static void
Remy Bruno3cee5a62006-10-16 12:46:32 +02004525snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
4526 struct snd_info_buffer *buffer)
Takashi Iwai763f3562005-06-03 11:25:34 +02004527{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004528 struct hdspm *hdspm = entry->private_data;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004529 unsigned int status, status2, control, freq;
4530
Takashi Iwai763f3562005-06-03 11:25:34 +02004531 char *pref_sync_ref;
4532 char *autosync_ref;
4533 char *system_clock_mode;
Takashi Iwai763f3562005-06-03 11:25:34 +02004534 char *insel;
Takashi Iwai763f3562005-06-03 11:25:34 +02004535 int x, x2;
4536
Adrian Knoth0dca1792011-01-26 19:32:14 +01004537 /* TCO stuff */
4538 int a, ltc, frames, seconds, minutes, hours;
4539 unsigned int period;
4540 u64 freq_const = 0;
4541 u32 rate;
4542
Takashi Iwai763f3562005-06-03 11:25:34 +02004543 status = hdspm_read(hdspm, HDSPM_statusRegister);
4544 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004545 control = hdspm->control_register;
4546 freq = hdspm_read(hdspm, HDSPM_timecodeRegister);
Takashi Iwai763f3562005-06-03 11:25:34 +02004547
4548 snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004549 hdspm->card_name, hdspm->card->number + 1,
4550 hdspm->firmware_rev,
4551 (status2 & HDSPM_version0) |
4552 (status2 & HDSPM_version1) | (status2 &
4553 HDSPM_version2));
4554
4555 snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n",
4556 (hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF,
4557 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF);
Takashi Iwai763f3562005-06-03 11:25:34 +02004558
4559 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004560 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
Takashi Iwai763f3562005-06-03 11:25:34 +02004561
4562 snd_iprintf(buffer, "--- System ---\n");
4563
4564 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004565 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4566 status & HDSPM_audioIRQPending,
4567 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4568 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4569 hdspm->irq_count);
Takashi Iwai763f3562005-06-03 11:25:34 +02004570 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004571 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4572 "estimated= %ld (bytes)\n",
4573 ((status & HDSPM_BufferID) ? 1 : 0),
4574 (status & HDSPM_BufferPositionMask),
4575 (status & HDSPM_BufferPositionMask) %
4576 (2 * (int)hdspm->period_bytes),
4577 ((status & HDSPM_BufferPositionMask) - 64) %
4578 (2 * (int)hdspm->period_bytes),
4579 (long) hdspm_hw_pointer(hdspm) * 4);
Takashi Iwai763f3562005-06-03 11:25:34 +02004580
4581 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004582 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4583 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4584 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4585 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4586 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
Takashi Iwai763f3562005-06-03 11:25:34 +02004587 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004588 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4589 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4590 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4591 snd_iprintf(buffer,
4592 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4593 "status2=0x%x\n",
4594 hdspm->control_register, hdspm->control2_register,
4595 status, status2);
4596 if (status & HDSPM_tco_detect) {
4597 snd_iprintf(buffer, "TCO module detected.\n");
4598 a = hdspm_read(hdspm, HDSPM_RD_TCO+4);
4599 if (a & HDSPM_TCO1_LTC_Input_valid) {
4600 snd_iprintf(buffer, " LTC valid, ");
4601 switch (a & (HDSPM_TCO1_LTC_Format_LSB |
4602 HDSPM_TCO1_LTC_Format_MSB)) {
4603 case 0:
4604 snd_iprintf(buffer, "24 fps, ");
4605 break;
4606 case HDSPM_TCO1_LTC_Format_LSB:
4607 snd_iprintf(buffer, "25 fps, ");
4608 break;
4609 case HDSPM_TCO1_LTC_Format_MSB:
4610 snd_iprintf(buffer, "29.97 fps, ");
4611 break;
4612 default:
4613 snd_iprintf(buffer, "30 fps, ");
4614 break;
4615 }
4616 if (a & HDSPM_TCO1_set_drop_frame_flag) {
4617 snd_iprintf(buffer, "drop frame\n");
4618 } else {
4619 snd_iprintf(buffer, "full frame\n");
4620 }
4621 } else {
4622 snd_iprintf(buffer, " no LTC\n");
4623 }
4624 if (a & HDSPM_TCO1_Video_Input_Format_NTSC) {
4625 snd_iprintf(buffer, " Video: NTSC\n");
4626 } else if (a & HDSPM_TCO1_Video_Input_Format_PAL) {
4627 snd_iprintf(buffer, " Video: PAL\n");
4628 } else {
4629 snd_iprintf(buffer, " No video\n");
4630 }
4631 if (a & HDSPM_TCO1_TCO_lock) {
4632 snd_iprintf(buffer, " Sync: lock\n");
4633 } else {
4634 snd_iprintf(buffer, " Sync: no lock\n");
4635 }
4636
4637 switch (hdspm->io_type) {
4638 case MADI:
4639 case AES32:
4640 freq_const = 110069313433624ULL;
4641 break;
4642 case RayDAT:
4643 case AIO:
4644 freq_const = 104857600000000ULL;
4645 break;
4646 case MADIface:
4647 break; /* no TCO possible */
4648 }
4649
4650 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
4651 snd_iprintf(buffer, " period: %u\n", period);
4652
4653
4654 /* rate = freq_const/period; */
4655 rate = div_u64(freq_const, period);
4656
4657 if (control & HDSPM_QuadSpeed) {
4658 rate *= 4;
4659 } else if (control & HDSPM_DoubleSpeed) {
4660 rate *= 2;
4661 }
4662
4663 snd_iprintf(buffer, " Frequency: %u Hz\n",
4664 (unsigned int) rate);
4665
4666 ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
4667 frames = ltc & 0xF;
4668 ltc >>= 4;
4669 frames += (ltc & 0x3) * 10;
4670 ltc >>= 4;
4671 seconds = ltc & 0xF;
4672 ltc >>= 4;
4673 seconds += (ltc & 0x7) * 10;
4674 ltc >>= 4;
4675 minutes = ltc & 0xF;
4676 ltc >>= 4;
4677 minutes += (ltc & 0x7) * 10;
4678 ltc >>= 4;
4679 hours = ltc & 0xF;
4680 ltc >>= 4;
4681 hours += (ltc & 0x3) * 10;
4682 snd_iprintf(buffer,
4683 " LTC In: %02d:%02d:%02d:%02d\n",
4684 hours, minutes, seconds, frames);
4685
4686 } else {
4687 snd_iprintf(buffer, "No TCO module detected.\n");
4688 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004689
4690 snd_iprintf(buffer, "--- Settings ---\n");
4691
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004692 x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
Adrian Knoth0dca1792011-01-26 19:32:14 +01004693 HDSPM_LatencyMask));
Takashi Iwai763f3562005-06-03 11:25:34 +02004694
4695 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004696 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4697 x, (unsigned long) hdspm->period_bytes);
Takashi Iwai763f3562005-06-03 11:25:34 +02004698
Adrian Knoth0dca1792011-01-26 19:32:14 +01004699 snd_iprintf(buffer, "Line out: %s\n",
4700 (hdspm->control_register & HDSPM_LineOut) ? "on " : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004701
4702 switch (hdspm->control_register & HDSPM_InputMask) {
4703 case HDSPM_InputOptical:
4704 insel = "Optical";
4705 break;
4706 case HDSPM_InputCoaxial:
4707 insel = "Coaxial";
4708 break;
4709 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01004710 insel = "Unkown";
Takashi Iwai763f3562005-06-03 11:25:34 +02004711 }
4712
Takashi Iwai763f3562005-06-03 11:25:34 +02004713 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004714 "ClearTrackMarker = %s, Transmit in %s Channel Mode, "
4715 "Auto Input %s\n",
4716 (hdspm->control_register & HDSPM_clr_tms) ? "on" : "off",
4717 (hdspm->control_register & HDSPM_TX_64ch) ? "64" : "56",
4718 (hdspm->control_register & HDSPM_AutoInp) ? "on" : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004719
Adrian Knoth0dca1792011-01-26 19:32:14 +01004720
Remy Bruno3cee5a62006-10-16 12:46:32 +02004721 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
Adrian Knoth0dca1792011-01-26 19:32:14 +01004722 system_clock_mode = "AutoSync";
Remy Bruno3cee5a62006-10-16 12:46:32 +02004723 else
Takashi Iwai763f3562005-06-03 11:25:34 +02004724 system_clock_mode = "Master";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004725 snd_iprintf(buffer, "AutoSync Reference: %s\n", system_clock_mode);
Takashi Iwai763f3562005-06-03 11:25:34 +02004726
4727 switch (hdspm_pref_sync_ref(hdspm)) {
4728 case HDSPM_SYNC_FROM_WORD:
4729 pref_sync_ref = "Word Clock";
4730 break;
4731 case HDSPM_SYNC_FROM_MADI:
4732 pref_sync_ref = "MADI Sync";
4733 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004734 case HDSPM_SYNC_FROM_TCO:
4735 pref_sync_ref = "TCO";
4736 break;
4737 case HDSPM_SYNC_FROM_SYNC_IN:
4738 pref_sync_ref = "Sync In";
4739 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004740 default:
4741 pref_sync_ref = "XXXX Clock";
4742 break;
4743 }
4744 snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004745 pref_sync_ref);
Takashi Iwai763f3562005-06-03 11:25:34 +02004746
4747 snd_iprintf(buffer, "System Clock Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004748 hdspm->system_sample_rate);
Takashi Iwai763f3562005-06-03 11:25:34 +02004749
4750
4751 snd_iprintf(buffer, "--- Status:\n");
4752
4753 x = status & HDSPM_madiSync;
4754 x2 = status2 & HDSPM_wcSync;
4755
4756 snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004757 (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
4758 "NoLock",
4759 (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
4760 "NoLock");
Takashi Iwai763f3562005-06-03 11:25:34 +02004761
4762 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004763 case HDSPM_AUTOSYNC_FROM_SYNC_IN:
4764 autosync_ref = "Sync In";
4765 break;
4766 case HDSPM_AUTOSYNC_FROM_TCO:
4767 autosync_ref = "TCO";
4768 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004769 case HDSPM_AUTOSYNC_FROM_WORD:
4770 autosync_ref = "Word Clock";
4771 break;
4772 case HDSPM_AUTOSYNC_FROM_MADI:
4773 autosync_ref = "MADI Sync";
4774 break;
4775 case HDSPM_AUTOSYNC_FROM_NONE:
4776 autosync_ref = "Input not valid";
4777 break;
4778 default:
4779 autosync_ref = "---";
4780 break;
4781 }
4782 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004783 "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
4784 autosync_ref, hdspm_external_sample_rate(hdspm),
4785 (status & HDSPM_madiFreqMask) >> 22,
4786 (status2 & HDSPM_wcFreqMask) >> 5);
Takashi Iwai763f3562005-06-03 11:25:34 +02004787
4788 snd_iprintf(buffer, "Input: %s, Mode=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004789 (status & HDSPM_AB_int) ? "Coax" : "Optical",
4790 (status & HDSPM_RX_64ch) ? "64 channels" :
4791 "56 channels");
Takashi Iwai763f3562005-06-03 11:25:34 +02004792
4793 snd_iprintf(buffer, "\n");
4794}
4795
Remy Bruno3cee5a62006-10-16 12:46:32 +02004796static void
4797snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
4798 struct snd_info_buffer *buffer)
4799{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004800 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004801 unsigned int status;
4802 unsigned int status2;
4803 unsigned int timecode;
4804 int pref_syncref;
4805 char *autosync_ref;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004806 int x;
4807
4808 status = hdspm_read(hdspm, HDSPM_statusRegister);
4809 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
4810 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
4811
4812 snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
4813 hdspm->card_name, hdspm->card->number + 1,
4814 hdspm->firmware_rev);
4815
4816 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
4817 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
4818
4819 snd_iprintf(buffer, "--- System ---\n");
4820
4821 snd_iprintf(buffer,
4822 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4823 status & HDSPM_audioIRQPending,
4824 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4825 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4826 hdspm->irq_count);
4827 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004828 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4829 "estimated= %ld (bytes)\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004830 ((status & HDSPM_BufferID) ? 1 : 0),
4831 (status & HDSPM_BufferPositionMask),
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004832 (status & HDSPM_BufferPositionMask) %
4833 (2 * (int)hdspm->period_bytes),
4834 ((status & HDSPM_BufferPositionMask) - 64) %
4835 (2 * (int)hdspm->period_bytes),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004836 (long) hdspm_hw_pointer(hdspm) * 4);
4837
4838 snd_iprintf(buffer,
4839 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4840 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4841 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4842 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4843 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
4844 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004845 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4846 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4847 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4848 snd_iprintf(buffer,
4849 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4850 "status2=0x%x\n",
4851 hdspm->control_register, hdspm->control2_register,
4852 status, status2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02004853
4854 snd_iprintf(buffer, "--- Settings ---\n");
4855
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004856 x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
Adrian Knoth0dca1792011-01-26 19:32:14 +01004857 HDSPM_LatencyMask));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004858
4859 snd_iprintf(buffer,
4860 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4861 x, (unsigned long) hdspm->period_bytes);
4862
Adrian Knoth0dca1792011-01-26 19:32:14 +01004863 snd_iprintf(buffer, "Line out: %s\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004864 (hdspm->
Adrian Knoth0dca1792011-01-26 19:32:14 +01004865 control_register & HDSPM_LineOut) ? "on " : "off");
Remy Bruno3cee5a62006-10-16 12:46:32 +02004866
4867 snd_iprintf(buffer,
4868 "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
4869 (hdspm->
4870 control_register & HDSPM_clr_tms) ? "on" : "off",
4871 (hdspm->
4872 control_register & HDSPM_Emphasis) ? "on" : "off",
4873 (hdspm->
4874 control_register & HDSPM_Dolby) ? "on" : "off");
4875
Remy Bruno3cee5a62006-10-16 12:46:32 +02004876
4877 pref_syncref = hdspm_pref_sync_ref(hdspm);
4878 if (pref_syncref == 0)
4879 snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
4880 else
4881 snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
4882 pref_syncref);
4883
4884 snd_iprintf(buffer, "System Clock Frequency: %d\n",
4885 hdspm->system_sample_rate);
4886
4887 snd_iprintf(buffer, "Double speed: %s\n",
4888 hdspm->control_register & HDSPM_DS_DoubleWire?
4889 "Double wire" : "Single wire");
4890 snd_iprintf(buffer, "Quad speed: %s\n",
4891 hdspm->control_register & HDSPM_QS_DoubleWire?
4892 "Double wire" :
4893 hdspm->control_register & HDSPM_QS_QuadWire?
4894 "Quad wire" : "Single wire");
4895
4896 snd_iprintf(buffer, "--- Status:\n");
4897
4898 snd_iprintf(buffer, "Word: %s Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004899 (status & HDSPM_AES32_wcLock) ? "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004900 HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004901
4902 for (x = 0; x < 8; x++) {
4903 snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004904 x+1,
4905 (status2 & (HDSPM_LockAES >> x)) ?
Adrian Knoth0dca1792011-01-26 19:32:14 +01004906 "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004907 HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004908 }
4909
4910 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004911 case HDSPM_AES32_AUTOSYNC_FROM_NONE:
4912 autosync_ref = "None"; break;
4913 case HDSPM_AES32_AUTOSYNC_FROM_WORD:
4914 autosync_ref = "Word Clock"; break;
4915 case HDSPM_AES32_AUTOSYNC_FROM_AES1:
4916 autosync_ref = "AES1"; break;
4917 case HDSPM_AES32_AUTOSYNC_FROM_AES2:
4918 autosync_ref = "AES2"; break;
4919 case HDSPM_AES32_AUTOSYNC_FROM_AES3:
4920 autosync_ref = "AES3"; break;
4921 case HDSPM_AES32_AUTOSYNC_FROM_AES4:
4922 autosync_ref = "AES4"; break;
4923 case HDSPM_AES32_AUTOSYNC_FROM_AES5:
4924 autosync_ref = "AES5"; break;
4925 case HDSPM_AES32_AUTOSYNC_FROM_AES6:
4926 autosync_ref = "AES6"; break;
4927 case HDSPM_AES32_AUTOSYNC_FROM_AES7:
4928 autosync_ref = "AES7"; break;
4929 case HDSPM_AES32_AUTOSYNC_FROM_AES8:
4930 autosync_ref = "AES8"; break;
4931 default:
4932 autosync_ref = "---"; break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004933 }
4934 snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
4935
4936 snd_iprintf(buffer, "\n");
4937}
4938
Adrian Knoth0dca1792011-01-26 19:32:14 +01004939static void
4940snd_hdspm_proc_read_raydat(struct snd_info_entry *entry,
4941 struct snd_info_buffer *buffer)
4942{
4943 struct hdspm *hdspm = entry->private_data;
4944 unsigned int status1, status2, status3, control, i;
4945 unsigned int lock, sync;
4946
4947 status1 = hdspm_read(hdspm, HDSPM_RD_STATUS_1); /* s1 */
4948 status2 = hdspm_read(hdspm, HDSPM_RD_STATUS_2); /* freq */
4949 status3 = hdspm_read(hdspm, HDSPM_RD_STATUS_3); /* s2 */
4950
4951 control = hdspm->control_register;
4952
4953 snd_iprintf(buffer, "STATUS1: 0x%08x\n", status1);
4954 snd_iprintf(buffer, "STATUS2: 0x%08x\n", status2);
4955 snd_iprintf(buffer, "STATUS3: 0x%08x\n", status3);
4956
4957
4958 snd_iprintf(buffer, "\n*** CLOCK MODE\n\n");
4959
4960 snd_iprintf(buffer, "Clock mode : %s\n",
4961 (hdspm_system_clock_mode(hdspm) == 0) ? "master" : "slave");
4962 snd_iprintf(buffer, "System frequency: %d Hz\n",
4963 hdspm_get_system_sample_rate(hdspm));
4964
4965 snd_iprintf(buffer, "\n*** INPUT STATUS\n\n");
4966
4967 lock = 0x1;
4968 sync = 0x100;
4969
4970 for (i = 0; i < 8; i++) {
4971 snd_iprintf(buffer, "s1_input %d: Lock %d, Sync %d, Freq %s\n",
4972 i,
4973 (status1 & lock) ? 1 : 0,
4974 (status1 & sync) ? 1 : 0,
4975 texts_freq[(status2 >> (i * 4)) & 0xF]);
4976
4977 lock = lock<<1;
4978 sync = sync<<1;
4979 }
4980
4981 snd_iprintf(buffer, "WC input: Lock %d, Sync %d, Freq %s\n",
4982 (status1 & 0x1000000) ? 1 : 0,
4983 (status1 & 0x2000000) ? 1 : 0,
4984 texts_freq[(status1 >> 16) & 0xF]);
4985
4986 snd_iprintf(buffer, "TCO input: Lock %d, Sync %d, Freq %s\n",
4987 (status1 & 0x4000000) ? 1 : 0,
4988 (status1 & 0x8000000) ? 1 : 0,
4989 texts_freq[(status1 >> 20) & 0xF]);
4990
4991 snd_iprintf(buffer, "SYNC IN: Lock %d, Sync %d, Freq %s\n",
4992 (status3 & 0x400) ? 1 : 0,
4993 (status3 & 0x800) ? 1 : 0,
4994 texts_freq[(status2 >> 12) & 0xF]);
4995
4996}
4997
Remy Bruno3cee5a62006-10-16 12:46:32 +02004998#ifdef CONFIG_SND_DEBUG
4999static void
Adrian Knoth0dca1792011-01-26 19:32:14 +01005000snd_hdspm_proc_read_debug(struct snd_info_entry *entry,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005001 struct snd_info_buffer *buffer)
5002{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005003 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005004
5005 int j,i;
5006
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005007 for (i = 0; i < 256 /* 1024*64 */; i += j) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02005008 snd_iprintf(buffer, "0x%08X: ", i);
5009 for (j = 0; j < 16; j += 4)
5010 snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
5011 snd_iprintf(buffer, "\n");
5012 }
5013}
5014#endif
5015
5016
Adrian Knoth0dca1792011-01-26 19:32:14 +01005017static void snd_hdspm_proc_ports_in(struct snd_info_entry *entry,
5018 struct snd_info_buffer *buffer)
5019{
5020 struct hdspm *hdspm = entry->private_data;
5021 int i;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005022
Adrian Knoth0dca1792011-01-26 19:32:14 +01005023 snd_iprintf(buffer, "# generated by hdspm\n");
5024
5025 for (i = 0; i < hdspm->max_channels_in; i++) {
5026 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_in[i]);
5027 }
5028}
5029
5030static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry,
5031 struct snd_info_buffer *buffer)
5032{
5033 struct hdspm *hdspm = entry->private_data;
5034 int i;
5035
5036 snd_iprintf(buffer, "# generated by hdspm\n");
5037
5038 for (i = 0; i < hdspm->max_channels_out; i++) {
5039 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_out[i]);
5040 }
5041}
5042
5043
5044static void __devinit snd_hdspm_proc_init(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005045{
Takashi Iwai98274f02005-11-17 14:52:34 +01005046 struct snd_info_entry *entry;
Takashi Iwai763f3562005-06-03 11:25:34 +02005047
Adrian Knoth0dca1792011-01-26 19:32:14 +01005048 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) {
5049 switch (hdspm->io_type) {
5050 case AES32:
5051 snd_info_set_text_ops(entry, hdspm,
5052 snd_hdspm_proc_read_aes32);
5053 break;
5054 case MADI:
5055 snd_info_set_text_ops(entry, hdspm,
5056 snd_hdspm_proc_read_madi);
5057 break;
5058 case MADIface:
5059 /* snd_info_set_text_ops(entry, hdspm,
5060 snd_hdspm_proc_read_madiface); */
5061 break;
5062 case RayDAT:
5063 snd_info_set_text_ops(entry, hdspm,
5064 snd_hdspm_proc_read_raydat);
5065 break;
5066 case AIO:
5067 break;
5068 }
5069 }
5070
5071 if (!snd_card_proc_new(hdspm->card, "ports.in", &entry)) {
5072 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_in);
5073 }
5074
5075 if (!snd_card_proc_new(hdspm->card, "ports.out", &entry)) {
5076 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_out);
5077 }
5078
Remy Bruno3cee5a62006-10-16 12:46:32 +02005079#ifdef CONFIG_SND_DEBUG
5080 /* debug file to read all hdspm registers */
5081 if (!snd_card_proc_new(hdspm->card, "debug", &entry))
5082 snd_info_set_text_ops(entry, hdspm,
5083 snd_hdspm_proc_read_debug);
5084#endif
Takashi Iwai763f3562005-06-03 11:25:34 +02005085}
5086
5087/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005088 hdspm intitialize
Takashi Iwai763f3562005-06-03 11:25:34 +02005089 ------------------------------------------------------------*/
5090
Takashi Iwai98274f02005-11-17 14:52:34 +01005091static int snd_hdspm_set_defaults(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005092{
Takashi Iwai763f3562005-06-03 11:25:34 +02005093 /* ASSUMPTION: hdspm->lock is either held, or there is no need to
Joe Perches561de312007-12-18 13:13:47 +01005094 hold it (e.g. during module initialization).
Adrian Knoth0dca1792011-01-26 19:32:14 +01005095 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005096
5097 /* set defaults: */
5098
Adrian Knoth0dca1792011-01-26 19:32:14 +01005099 hdspm->settings_register = 0;
5100
5101 switch (hdspm->io_type) {
5102 case MADI:
5103 case MADIface:
5104 hdspm->control_register =
5105 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5106 break;
5107
5108 case RayDAT:
5109 case AIO:
5110 hdspm->settings_register = 0x1 + 0x1000;
5111 /* Magic values are: LAT_0, LAT_2, Master, freq1, tx64ch, inp_0,
5112 * line_out */
5113 hdspm->control_register =
5114 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5115 break;
5116
5117 case AES32:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005118 hdspm->control_register =
5119 HDSPM_ClockModeMaster | /* Master Cloack Mode on */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005120 hdspm_encode_latency(7) | /* latency max=8192samples */
Remy Bruno3cee5a62006-10-16 12:46:32 +02005121 HDSPM_SyncRef0 | /* AES1 is syncclock */
5122 HDSPM_LineOut | /* Analog output in */
5123 HDSPM_Professional; /* Professional mode */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005124 break;
5125 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005126
5127 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5128
Adrian Knoth0dca1792011-01-26 19:32:14 +01005129 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005130 /* No control2 register for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005131#ifdef SNDRV_BIG_ENDIAN
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005132 hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
Takashi Iwai763f3562005-06-03 11:25:34 +02005133#else
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005134 hdspm->control2_register = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005135#endif
5136
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005137 hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
5138 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005139 hdspm_compute_period_size(hdspm);
5140
5141 /* silence everything */
5142
5143 all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
5144
Adrian Knoth0dca1792011-01-26 19:32:14 +01005145 if (hdspm->io_type == AIO || hdspm->io_type == RayDAT) {
5146 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
Takashi Iwai763f3562005-06-03 11:25:34 +02005147 }
5148
5149 /* set a default rate so that the channel map is set up. */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005150 hdspm_set_rate(hdspm, 48000, 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02005151
5152 return 0;
5153}
5154
5155
5156/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005157 interrupt
Takashi Iwai763f3562005-06-03 11:25:34 +02005158 ------------------------------------------------------------*/
5159
David Howells7d12e782006-10-05 14:55:46 +01005160static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02005161{
Takashi Iwai98274f02005-11-17 14:52:34 +01005162 struct hdspm *hdspm = (struct hdspm *) dev_id;
Takashi Iwai763f3562005-06-03 11:25:34 +02005163 unsigned int status;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005164 int i, audio, midi, schedule = 0;
5165 /* cycles_t now; */
Takashi Iwai763f3562005-06-03 11:25:34 +02005166
5167 status = hdspm_read(hdspm, HDSPM_statusRegister);
5168
5169 audio = status & HDSPM_audioIRQPending;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005170 midi = status & (HDSPM_midi0IRQPending | HDSPM_midi1IRQPending |
5171 HDSPM_midi2IRQPending | HDSPM_midi3IRQPending);
Takashi Iwai763f3562005-06-03 11:25:34 +02005172
Adrian Knoth0dca1792011-01-26 19:32:14 +01005173 /* now = get_cycles(); */
5174 /**
5175 * LAT_2..LAT_0 period counter (win) counter (mac)
5176 * 6 4096 ~256053425 ~514672358
5177 * 5 2048 ~128024983 ~257373821
5178 * 4 1024 ~64023706 ~128718089
5179 * 3 512 ~32005945 ~64385999
5180 * 2 256 ~16003039 ~32260176
5181 * 1 128 ~7998738 ~16194507
5182 * 0 64 ~3998231 ~8191558
5183 **/
5184 /*
5185 snd_printk(KERN_INFO "snd_hdspm_interrupt %llu @ %llx\n",
5186 now-hdspm->last_interrupt, status & 0xFFC0);
5187 hdspm->last_interrupt = now;
5188 */
5189
5190 if (!audio && !midi)
Takashi Iwai763f3562005-06-03 11:25:34 +02005191 return IRQ_NONE;
5192
5193 hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
5194 hdspm->irq_count++;
5195
Takashi Iwai763f3562005-06-03 11:25:34 +02005196
5197 if (audio) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005198 if (hdspm->capture_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005199 snd_pcm_period_elapsed(hdspm->capture_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005200
5201 if (hdspm->playback_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005202 snd_pcm_period_elapsed(hdspm->playback_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005203 }
5204
Adrian Knoth0dca1792011-01-26 19:32:14 +01005205 if (midi) {
5206 i = 0;
5207 while (i < hdspm->midiPorts) {
5208 if ((hdspm_read(hdspm,
5209 hdspm->midi[i].statusIn) & 0xff) &&
5210 (status & hdspm->midi[i].irq)) {
5211 /* we disable interrupts for this input until
5212 * processing is done
5213 */
5214 hdspm->control_register &= ~hdspm->midi[i].ie;
5215 hdspm_write(hdspm, HDSPM_controlRegister,
5216 hdspm->control_register);
5217 hdspm->midi[i].pending = 1;
5218 schedule = 1;
5219 }
5220
5221 i++;
5222 }
5223
5224 if (schedule)
5225 tasklet_hi_schedule(&hdspm->midi_tasklet);
Takashi Iwai763f3562005-06-03 11:25:34 +02005226 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005227
Takashi Iwai763f3562005-06-03 11:25:34 +02005228 return IRQ_HANDLED;
5229}
5230
5231/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005232 pcm interface
Takashi Iwai763f3562005-06-03 11:25:34 +02005233 ------------------------------------------------------------*/
5234
5235
Adrian Knoth0dca1792011-01-26 19:32:14 +01005236static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream
5237 *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005238{
Takashi Iwai98274f02005-11-17 14:52:34 +01005239 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005240 return hdspm_hw_pointer(hdspm);
5241}
5242
Takashi Iwai763f3562005-06-03 11:25:34 +02005243
Takashi Iwai98274f02005-11-17 14:52:34 +01005244static int snd_hdspm_reset(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005245{
Takashi Iwai98274f02005-11-17 14:52:34 +01005246 struct snd_pcm_runtime *runtime = substream->runtime;
5247 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5248 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005249
5250 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5251 other = hdspm->capture_substream;
5252 else
5253 other = hdspm->playback_substream;
5254
5255 if (hdspm->running)
5256 runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
5257 else
5258 runtime->status->hw_ptr = 0;
5259 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005260 struct snd_pcm_substream *s;
5261 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01005262 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005263 if (s == other) {
5264 oruntime->status->hw_ptr =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005265 runtime->status->hw_ptr;
Takashi Iwai763f3562005-06-03 11:25:34 +02005266 break;
5267 }
5268 }
5269 }
5270 return 0;
5271}
5272
Takashi Iwai98274f02005-11-17 14:52:34 +01005273static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
5274 struct snd_pcm_hw_params *params)
Takashi Iwai763f3562005-06-03 11:25:34 +02005275{
Takashi Iwai98274f02005-11-17 14:52:34 +01005276 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005277 int err;
5278 int i;
5279 pid_t this_pid;
5280 pid_t other_pid;
Takashi Iwai763f3562005-06-03 11:25:34 +02005281
5282 spin_lock_irq(&hdspm->lock);
5283
5284 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5285 this_pid = hdspm->playback_pid;
5286 other_pid = hdspm->capture_pid;
5287 } else {
5288 this_pid = hdspm->capture_pid;
5289 other_pid = hdspm->playback_pid;
5290 }
5291
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005292 if (other_pid > 0 && this_pid != other_pid) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005293
5294 /* The other stream is open, and not by the same
5295 task as this one. Make sure that the parameters
5296 that matter are the same.
Adrian Knoth0dca1792011-01-26 19:32:14 +01005297 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005298
5299 if (params_rate(params) != hdspm->system_sample_rate) {
5300 spin_unlock_irq(&hdspm->lock);
5301 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005302 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005303 return -EBUSY;
5304 }
5305
5306 if (params_period_size(params) != hdspm->period_bytes / 4) {
5307 spin_unlock_irq(&hdspm->lock);
5308 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005309 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005310 return -EBUSY;
5311 }
5312
5313 }
5314 /* We're fine. */
5315 spin_unlock_irq(&hdspm->lock);
5316
5317 /* how to make sure that the rate matches an externally-set one ? */
5318
5319 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005320 err = hdspm_set_rate(hdspm, params_rate(params), 0);
5321 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005322 snd_printk(KERN_INFO "err on hdspm_set_rate: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005323 spin_unlock_irq(&hdspm->lock);
5324 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005325 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005326 return err;
5327 }
5328 spin_unlock_irq(&hdspm->lock);
5329
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005330 err = hdspm_set_interrupt_interval(hdspm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005331 params_period_size(params));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005332 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005333 snd_printk(KERN_INFO "err on hdspm_set_interrupt_interval: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005334 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005335 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005336 return err;
5337 }
5338
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005339 /* Memory allocation, takashi's method, dont know if we should
5340 * spinlock
5341 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005342 /* malloc all buffer even if not enabled to get sure */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005343 /* Update for MADI rev 204: we need to allocate for all channels,
5344 * otherwise it doesn't work at 96kHz */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005345
Takashi Iwai763f3562005-06-03 11:25:34 +02005346 err =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005347 snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
5348 if (err < 0) {
5349 snd_printk(KERN_INFO "err on snd_pcm_lib_malloc_pages: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005350 return err;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005351 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005352
Takashi Iwai763f3562005-06-03 11:25:34 +02005353 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5354
Takashi Iwai77a23f22008-08-21 13:00:13 +02005355 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferOut,
Takashi Iwai763f3562005-06-03 11:25:34 +02005356 params_channels(params));
5357
5358 for (i = 0; i < params_channels(params); ++i)
5359 snd_hdspm_enable_out(hdspm, i, 1);
5360
5361 hdspm->playback_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005362 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005363 snd_printdd("Allocated sample buffer for playback at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005364 hdspm->playback_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005365 } else {
Takashi Iwai77a23f22008-08-21 13:00:13 +02005366 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn,
Takashi Iwai763f3562005-06-03 11:25:34 +02005367 params_channels(params));
5368
5369 for (i = 0; i < params_channels(params); ++i)
5370 snd_hdspm_enable_in(hdspm, i, 1);
5371
5372 hdspm->capture_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005373 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005374 snd_printdd("Allocated sample buffer for capture at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005375 hdspm->capture_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005376 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005377
Remy Bruno3cee5a62006-10-16 12:46:32 +02005378 /*
5379 snd_printdd("Allocated sample buffer for %s at 0x%08X\n",
5380 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5381 "playback" : "capture",
Takashi Iwai77a23f22008-08-21 13:00:13 +02005382 snd_pcm_sgbuf_get_addr(substream, 0));
Adrian Knoth0dca1792011-01-26 19:32:14 +01005383 */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005384 /*
Adrian Knoth0dca1792011-01-26 19:32:14 +01005385 snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n",
5386 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5387 "playback" : "capture",
5388 params_rate(params), params_channels(params),
5389 params_buffer_size(params));
5390 */
5391
5392
5393 /* Switch to native float format if requested */
5394 if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) {
5395 if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT))
5396 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE float format.\n");
5397
5398 hdspm->control_register |= HDSPe_FLOAT_FORMAT;
5399 } else if (SNDRV_PCM_FORMAT_S32_LE == params_format(params)) {
5400 if (hdspm->control_register & HDSPe_FLOAT_FORMAT)
5401 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE integer format.\n");
5402
5403 hdspm->control_register &= ~HDSPe_FLOAT_FORMAT;
5404 }
5405 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5406
Takashi Iwai763f3562005-06-03 11:25:34 +02005407 return 0;
5408}
5409
Takashi Iwai98274f02005-11-17 14:52:34 +01005410static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005411{
5412 int i;
Takashi Iwai98274f02005-11-17 14:52:34 +01005413 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005414
5415 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5416
Adrian Knoth0dca1792011-01-26 19:32:14 +01005417 /* params_channels(params) should be enough,
Takashi Iwai763f3562005-06-03 11:25:34 +02005418 but to get sure in case of error */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005419 for (i = 0; i < hdspm->max_channels_out; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005420 snd_hdspm_enable_out(hdspm, i, 0);
5421
5422 hdspm->playback_buffer = NULL;
5423 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005424 for (i = 0; i < hdspm->max_channels_in; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005425 snd_hdspm_enable_in(hdspm, i, 0);
5426
5427 hdspm->capture_buffer = NULL;
5428
5429 }
5430
5431 snd_pcm_lib_free_pages(substream);
5432
5433 return 0;
5434}
5435
Adrian Knoth0dca1792011-01-26 19:32:14 +01005436
Takashi Iwai98274f02005-11-17 14:52:34 +01005437static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005438 struct snd_pcm_channel_info *info)
Takashi Iwai763f3562005-06-03 11:25:34 +02005439{
Takashi Iwai98274f02005-11-17 14:52:34 +01005440 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005441
Adrian Knoth0dca1792011-01-26 19:32:14 +01005442 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5443 if (snd_BUG_ON(info->channel >= hdspm->max_channels_out)) {
5444 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel out of range (%d)\n", info->channel);
5445 return -EINVAL;
5446 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005447
Adrian Knoth0dca1792011-01-26 19:32:14 +01005448 if (hdspm->channel_map_out[info->channel] < 0) {
5449 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel %d mapped out\n", info->channel);
5450 return -EINVAL;
5451 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005452
Adrian Knoth0dca1792011-01-26 19:32:14 +01005453 info->offset = hdspm->channel_map_out[info->channel] *
5454 HDSPM_CHANNEL_BUFFER_BYTES;
5455 } else {
5456 if (snd_BUG_ON(info->channel >= hdspm->max_channels_in)) {
5457 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel out of range (%d)\n", info->channel);
5458 return -EINVAL;
5459 }
5460
5461 if (hdspm->channel_map_in[info->channel] < 0) {
5462 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel %d mapped out\n", info->channel);
5463 return -EINVAL;
5464 }
5465
5466 info->offset = hdspm->channel_map_in[info->channel] *
5467 HDSPM_CHANNEL_BUFFER_BYTES;
5468 }
5469
Takashi Iwai763f3562005-06-03 11:25:34 +02005470 info->first = 0;
5471 info->step = 32;
5472 return 0;
5473}
5474
Adrian Knoth0dca1792011-01-26 19:32:14 +01005475
Takashi Iwai98274f02005-11-17 14:52:34 +01005476static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005477 unsigned int cmd, void *arg)
Takashi Iwai763f3562005-06-03 11:25:34 +02005478{
5479 switch (cmd) {
5480 case SNDRV_PCM_IOCTL1_RESET:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005481 return snd_hdspm_reset(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005482
5483 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Adrian Knoth0dca1792011-01-26 19:32:14 +01005484 {
5485 struct snd_pcm_channel_info *info = arg;
5486 return snd_hdspm_channel_info(substream, info);
5487 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005488 default:
5489 break;
5490 }
5491
5492 return snd_pcm_lib_ioctl(substream, cmd, arg);
5493}
5494
Takashi Iwai98274f02005-11-17 14:52:34 +01005495static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
Takashi Iwai763f3562005-06-03 11:25:34 +02005496{
Takashi Iwai98274f02005-11-17 14:52:34 +01005497 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5498 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005499 int running;
5500
5501 spin_lock(&hdspm->lock);
5502 running = hdspm->running;
5503 switch (cmd) {
5504 case SNDRV_PCM_TRIGGER_START:
5505 running |= 1 << substream->stream;
5506 break;
5507 case SNDRV_PCM_TRIGGER_STOP:
5508 running &= ~(1 << substream->stream);
5509 break;
5510 default:
5511 snd_BUG();
5512 spin_unlock(&hdspm->lock);
5513 return -EINVAL;
5514 }
5515 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5516 other = hdspm->capture_substream;
5517 else
5518 other = hdspm->playback_substream;
5519
5520 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005521 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01005522 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005523 if (s == other) {
5524 snd_pcm_trigger_done(s, substream);
5525 if (cmd == SNDRV_PCM_TRIGGER_START)
5526 running |= 1 << s->stream;
5527 else
5528 running &= ~(1 << s->stream);
5529 goto _ok;
5530 }
5531 }
5532 if (cmd == SNDRV_PCM_TRIGGER_START) {
5533 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005534 && substream->stream ==
5535 SNDRV_PCM_STREAM_CAPTURE)
Takashi Iwai763f3562005-06-03 11:25:34 +02005536 hdspm_silence_playback(hdspm);
5537 } else {
5538 if (running &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01005539 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Takashi Iwai763f3562005-06-03 11:25:34 +02005540 hdspm_silence_playback(hdspm);
5541 }
5542 } else {
5543 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
5544 hdspm_silence_playback(hdspm);
5545 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005546_ok:
Takashi Iwai763f3562005-06-03 11:25:34 +02005547 snd_pcm_trigger_done(substream, substream);
5548 if (!hdspm->running && running)
5549 hdspm_start_audio(hdspm);
5550 else if (hdspm->running && !running)
5551 hdspm_stop_audio(hdspm);
5552 hdspm->running = running;
5553 spin_unlock(&hdspm->lock);
5554
5555 return 0;
5556}
5557
Takashi Iwai98274f02005-11-17 14:52:34 +01005558static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005559{
5560 return 0;
5561}
5562
Adrian Knoth0dca1792011-01-26 19:32:14 +01005563static unsigned int period_sizes_old[] = {
5564 64, 128, 256, 512, 1024, 2048, 4096
5565};
5566
5567static unsigned int period_sizes_new[] = {
5568 32, 64, 128, 256, 512, 1024, 2048, 4096
5569};
5570
5571/* RayDAT and AIO always have a buffer of 16384 samples per channel */
5572static unsigned int raydat_aio_buffer_sizes[] = {
5573 16384
5574};
Takashi Iwai763f3562005-06-03 11:25:34 +02005575
Takashi Iwai98274f02005-11-17 14:52:34 +01005576static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005577 .info = (SNDRV_PCM_INFO_MMAP |
5578 SNDRV_PCM_INFO_MMAP_VALID |
5579 SNDRV_PCM_INFO_NONINTERLEAVED |
5580 SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
5581 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5582 .rates = (SNDRV_PCM_RATE_32000 |
5583 SNDRV_PCM_RATE_44100 |
5584 SNDRV_PCM_RATE_48000 |
5585 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005586 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5587 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ),
Takashi Iwai763f3562005-06-03 11:25:34 +02005588 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005589 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005590 .channels_min = 1,
5591 .channels_max = HDSPM_MAX_CHANNELS,
5592 .buffer_bytes_max =
5593 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
5594 .period_bytes_min = (64 * 4),
Adrian Knoth0dca1792011-01-26 19:32:14 +01005595 .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005596 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005597 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005598 .fifo_size = 0
5599};
5600
Takashi Iwai98274f02005-11-17 14:52:34 +01005601static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005602 .info = (SNDRV_PCM_INFO_MMAP |
5603 SNDRV_PCM_INFO_MMAP_VALID |
5604 SNDRV_PCM_INFO_NONINTERLEAVED |
5605 SNDRV_PCM_INFO_SYNC_START),
5606 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5607 .rates = (SNDRV_PCM_RATE_32000 |
5608 SNDRV_PCM_RATE_44100 |
5609 SNDRV_PCM_RATE_48000 |
5610 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005611 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5612 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
Takashi Iwai763f3562005-06-03 11:25:34 +02005613 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005614 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005615 .channels_min = 1,
5616 .channels_max = HDSPM_MAX_CHANNELS,
5617 .buffer_bytes_max =
5618 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
5619 .period_bytes_min = (64 * 4),
Adrian Knoth0dca1792011-01-26 19:32:14 +01005620 .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005621 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005622 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005623 .fifo_size = 0
5624};
5625
Adrian Knoth0dca1792011-01-26 19:32:14 +01005626static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_old = {
5627 .count = ARRAY_SIZE(period_sizes_old),
5628 .list = period_sizes_old,
Takashi Iwai763f3562005-06-03 11:25:34 +02005629 .mask = 0
5630};
5631
Adrian Knoth0dca1792011-01-26 19:32:14 +01005632static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_new = {
5633 .count = ARRAY_SIZE(period_sizes_new),
5634 .list = period_sizes_new,
5635 .mask = 0
5636};
Takashi Iwai763f3562005-06-03 11:25:34 +02005637
Adrian Knoth0dca1792011-01-26 19:32:14 +01005638static struct snd_pcm_hw_constraint_list hw_constraints_raydat_io_buffer = {
5639 .count = ARRAY_SIZE(raydat_aio_buffer_sizes),
5640 .list = raydat_aio_buffer_sizes,
5641 .mask = 0
5642};
5643
5644static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
5645 struct snd_pcm_hw_rule *rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005646{
Takashi Iwai98274f02005-11-17 14:52:34 +01005647 struct hdspm *hdspm = rule->private;
5648 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005649 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005650 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005651 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5652
Adrian Knoth0dca1792011-01-26 19:32:14 +01005653 if (r->min > 96000 && r->max <= 192000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005654 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005655 .min = hdspm->qs_in_channels,
5656 .max = hdspm->qs_in_channels,
5657 .integer = 1,
5658 };
5659 return snd_interval_refine(c, &t);
5660 } else if (r->min > 48000 && r->max <= 96000) {
5661 struct snd_interval t = {
5662 .min = hdspm->ds_in_channels,
5663 .max = hdspm->ds_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005664 .integer = 1,
5665 };
5666 return snd_interval_refine(c, &t);
5667 } else if (r->max < 64000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005668 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005669 .min = hdspm->ss_in_channels,
5670 .max = hdspm->ss_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005671 .integer = 1,
5672 };
5673 return snd_interval_refine(c, &t);
5674 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005675
Takashi Iwai763f3562005-06-03 11:25:34 +02005676 return 0;
5677}
5678
Adrian Knoth0dca1792011-01-26 19:32:14 +01005679static int snd_hdspm_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
Takashi Iwai98274f02005-11-17 14:52:34 +01005680 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005681{
Takashi Iwai98274f02005-11-17 14:52:34 +01005682 struct hdspm *hdspm = rule->private;
5683 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005684 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005685 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005686 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5687
Adrian Knoth0dca1792011-01-26 19:32:14 +01005688 if (r->min > 96000 && r->max <= 192000) {
5689 struct snd_interval t = {
5690 .min = hdspm->qs_out_channels,
5691 .max = hdspm->qs_out_channels,
5692 .integer = 1,
5693 };
5694 return snd_interval_refine(c, &t);
5695 } else if (r->min > 48000 && r->max <= 96000) {
5696 struct snd_interval t = {
5697 .min = hdspm->ds_out_channels,
5698 .max = hdspm->ds_out_channels,
5699 .integer = 1,
5700 };
5701 return snd_interval_refine(c, &t);
5702 } else if (r->max < 64000) {
5703 struct snd_interval t = {
5704 .min = hdspm->ss_out_channels,
5705 .max = hdspm->ss_out_channels,
5706 .integer = 1,
5707 };
5708 return snd_interval_refine(c, &t);
5709 } else {
5710 }
5711 return 0;
5712}
5713
5714static int snd_hdspm_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
5715 struct snd_pcm_hw_rule * rule)
5716{
5717 struct hdspm *hdspm = rule->private;
5718 struct snd_interval *c =
5719 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5720 struct snd_interval *r =
5721 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5722
5723 if (c->min >= hdspm->ss_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005724 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005725 .min = 32000,
5726 .max = 48000,
5727 .integer = 1,
5728 };
5729 return snd_interval_refine(r, &t);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005730 } else if (c->max <= hdspm->qs_in_channels) {
5731 struct snd_interval t = {
5732 .min = 128000,
5733 .max = 192000,
5734 .integer = 1,
5735 };
5736 return snd_interval_refine(r, &t);
5737 } else if (c->max <= hdspm->ds_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005738 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005739 .min = 64000,
5740 .max = 96000,
5741 .integer = 1,
5742 };
Takashi Iwai763f3562005-06-03 11:25:34 +02005743 return snd_interval_refine(r, &t);
5744 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005745
5746 return 0;
5747}
5748static int snd_hdspm_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
5749 struct snd_pcm_hw_rule *rule)
5750{
5751 struct hdspm *hdspm = rule->private;
5752 struct snd_interval *c =
5753 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5754 struct snd_interval *r =
5755 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5756
5757 if (c->min >= hdspm->ss_out_channels) {
5758 struct snd_interval t = {
5759 .min = 32000,
5760 .max = 48000,
5761 .integer = 1,
5762 };
5763 return snd_interval_refine(r, &t);
5764 } else if (c->max <= hdspm->qs_out_channels) {
5765 struct snd_interval t = {
5766 .min = 128000,
5767 .max = 192000,
5768 .integer = 1,
5769 };
5770 return snd_interval_refine(r, &t);
5771 } else if (c->max <= hdspm->ds_out_channels) {
5772 struct snd_interval t = {
5773 .min = 64000,
5774 .max = 96000,
5775 .integer = 1,
5776 };
5777 return snd_interval_refine(r, &t);
5778 }
5779
Takashi Iwai763f3562005-06-03 11:25:34 +02005780 return 0;
5781}
5782
Adrian Knoth0dca1792011-01-26 19:32:14 +01005783static int snd_hdspm_hw_rule_in_channels(struct snd_pcm_hw_params *params,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005784 struct snd_pcm_hw_rule *rule)
5785{
5786 unsigned int list[3];
5787 struct hdspm *hdspm = rule->private;
5788 struct snd_interval *c = hw_param_interval(params,
5789 SNDRV_PCM_HW_PARAM_CHANNELS);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005790
5791 list[0] = hdspm->qs_in_channels;
5792 list[1] = hdspm->ds_in_channels;
5793 list[2] = hdspm->ss_in_channels;
5794 return snd_interval_list(c, 3, list, 0);
5795}
5796
5797static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params,
5798 struct snd_pcm_hw_rule *rule)
5799{
5800 unsigned int list[3];
5801 struct hdspm *hdspm = rule->private;
5802 struct snd_interval *c = hw_param_interval(params,
5803 SNDRV_PCM_HW_PARAM_CHANNELS);
5804
5805 list[0] = hdspm->qs_out_channels;
5806 list[1] = hdspm->ds_out_channels;
5807 list[2] = hdspm->ss_out_channels;
5808 return snd_interval_list(c, 3, list, 0);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005809}
5810
5811
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005812static unsigned int hdspm_aes32_sample_rates[] = {
5813 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000
5814};
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005815
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005816static struct snd_pcm_hw_constraint_list
5817hdspm_hw_constraints_aes32_sample_rates = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005818 .count = ARRAY_SIZE(hdspm_aes32_sample_rates),
5819 .list = hdspm_aes32_sample_rates,
5820 .mask = 0
5821};
5822
Takashi Iwai98274f02005-11-17 14:52:34 +01005823static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005824{
Takashi Iwai98274f02005-11-17 14:52:34 +01005825 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5826 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02005827
Takashi Iwai763f3562005-06-03 11:25:34 +02005828 spin_lock_irq(&hdspm->lock);
5829
5830 snd_pcm_set_sync(substream);
5831
Adrian Knoth0dca1792011-01-26 19:32:14 +01005832
Takashi Iwai763f3562005-06-03 11:25:34 +02005833 runtime->hw = snd_hdspm_playback_subinfo;
5834
5835 if (hdspm->capture_substream == NULL)
5836 hdspm_stop_audio(hdspm);
5837
5838 hdspm->playback_pid = current->pid;
5839 hdspm->playback_substream = substream;
5840
5841 spin_unlock_irq(&hdspm->lock);
5842
5843 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
5844
Adrian Knoth0dca1792011-01-26 19:32:14 +01005845 switch (hdspm->io_type) {
5846 case AIO:
5847 case RayDAT:
5848 snd_pcm_hw_constraint_list(runtime, 0,
5849 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5850 &hw_constraints_period_sizes_new);
5851 snd_pcm_hw_constraint_list(runtime, 0,
5852 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
5853 &hw_constraints_raydat_io_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005854
Adrian Knoth0dca1792011-01-26 19:32:14 +01005855 break;
5856
5857 default:
5858 snd_pcm_hw_constraint_list(runtime, 0,
5859 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5860 &hw_constraints_period_sizes_old);
5861 }
5862
5863 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005864 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
5865 &hdspm_hw_constraints_aes32_sample_rates);
5866 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005867 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005868 snd_hdspm_hw_rule_rate_out_channels, hdspm,
5869 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005870 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01005871
5872 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5873 snd_hdspm_hw_rule_out_channels, hdspm,
5874 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
5875
5876 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5877 snd_hdspm_hw_rule_out_channels_rate, hdspm,
5878 SNDRV_PCM_HW_PARAM_RATE, -1);
5879
Takashi Iwai763f3562005-06-03 11:25:34 +02005880 return 0;
5881}
5882
Takashi Iwai98274f02005-11-17 14:52:34 +01005883static int snd_hdspm_playback_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005884{
Takashi Iwai98274f02005-11-17 14:52:34 +01005885 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005886
5887 spin_lock_irq(&hdspm->lock);
5888
5889 hdspm->playback_pid = -1;
5890 hdspm->playback_substream = NULL;
5891
5892 spin_unlock_irq(&hdspm->lock);
5893
5894 return 0;
5895}
5896
5897
Takashi Iwai98274f02005-11-17 14:52:34 +01005898static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005899{
Takashi Iwai98274f02005-11-17 14:52:34 +01005900 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5901 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02005902
5903 spin_lock_irq(&hdspm->lock);
5904 snd_pcm_set_sync(substream);
5905 runtime->hw = snd_hdspm_capture_subinfo;
5906
5907 if (hdspm->playback_substream == NULL)
5908 hdspm_stop_audio(hdspm);
5909
5910 hdspm->capture_pid = current->pid;
5911 hdspm->capture_substream = substream;
5912
5913 spin_unlock_irq(&hdspm->lock);
5914
5915 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005916 switch (hdspm->io_type) {
5917 case AIO:
5918 case RayDAT:
5919 snd_pcm_hw_constraint_list(runtime, 0,
5920 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5921 &hw_constraints_period_sizes_new);
5922 snd_pcm_hw_constraint_list(runtime, 0,
5923 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
5924 &hw_constraints_raydat_io_buffer);
5925 break;
5926
5927 default:
5928 snd_pcm_hw_constraint_list(runtime, 0,
5929 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5930 &hw_constraints_period_sizes_old);
5931 }
5932
5933 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005934 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
5935 &hdspm_hw_constraints_aes32_sample_rates);
5936 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005937 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth88fabbf2011-02-23 11:43:10 +01005938 snd_hdspm_hw_rule_rate_in_channels, hdspm,
5939 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005940 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01005941
5942 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5943 snd_hdspm_hw_rule_in_channels, hdspm,
5944 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
5945
5946 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5947 snd_hdspm_hw_rule_in_channels_rate, hdspm,
5948 SNDRV_PCM_HW_PARAM_RATE, -1);
5949
Takashi Iwai763f3562005-06-03 11:25:34 +02005950 return 0;
5951}
5952
Takashi Iwai98274f02005-11-17 14:52:34 +01005953static int snd_hdspm_capture_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005954{
Takashi Iwai98274f02005-11-17 14:52:34 +01005955 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005956
5957 spin_lock_irq(&hdspm->lock);
5958
5959 hdspm->capture_pid = -1;
5960 hdspm->capture_substream = NULL;
5961
5962 spin_unlock_irq(&hdspm->lock);
5963 return 0;
5964}
5965
Adrian Knoth0dca1792011-01-26 19:32:14 +01005966static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
Takashi Iwai763f3562005-06-03 11:25:34 +02005967{
Adrian Knoth0dca1792011-01-26 19:32:14 +01005968 /* we have nothing to initialize but the call is required */
5969 return 0;
5970}
5971
5972static inline int copy_u32_le(void __user *dest, void __iomem *src)
5973{
5974 u32 val = readl(src);
5975 return copy_to_user(dest, &val, 4);
5976}
5977
5978static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
5979 unsigned int cmd, unsigned long __user arg)
5980{
5981 void __user *argp = (void __user *)arg;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005982 struct hdspm *hdspm = hw->private_data;
Takashi Iwai98274f02005-11-17 14:52:34 +01005983 struct hdspm_mixer_ioctl mixer;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005984 struct hdspm_config info;
5985 struct hdspm_status status;
Takashi Iwai98274f02005-11-17 14:52:34 +01005986 struct hdspm_version hdspm_version;
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005987 struct hdspm_peak_rms *levels;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005988 struct hdspm_ltc ltc;
5989 unsigned int statusregister;
5990 long unsigned int s;
5991 int i = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005992
5993 switch (cmd) {
5994
Takashi Iwai763f3562005-06-03 11:25:34 +02005995 case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005996 levels = &hdspm->peak_rms;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005997 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005998 levels->input_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005999 readl(hdspm->iobase +
6000 HDSPM_MADI_INPUT_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006001 levels->playback_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006002 readl(hdspm->iobase +
6003 HDSPM_MADI_PLAYBACK_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006004 levels->output_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006005 readl(hdspm->iobase +
6006 HDSPM_MADI_OUTPUT_PEAK + i*4);
6007
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006008 levels->input_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006009 ((uint64_t) readl(hdspm->iobase +
6010 HDSPM_MADI_INPUT_RMS_H + i*4) << 32) |
6011 (uint64_t) readl(hdspm->iobase +
6012 HDSPM_MADI_INPUT_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006013 levels->playback_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006014 ((uint64_t)readl(hdspm->iobase +
6015 HDSPM_MADI_PLAYBACK_RMS_H+i*4) << 32) |
6016 (uint64_t)readl(hdspm->iobase +
6017 HDSPM_MADI_PLAYBACK_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006018 levels->output_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006019 ((uint64_t)readl(hdspm->iobase +
6020 HDSPM_MADI_OUTPUT_RMS_H + i*4) << 32) |
6021 (uint64_t)readl(hdspm->iobase +
6022 HDSPM_MADI_OUTPUT_RMS_L + i*4);
6023 }
6024
6025 if (hdspm->system_sample_rate > 96000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006026 levels->speed = qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006027 } else if (hdspm->system_sample_rate > 48000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006028 levels->speed = ds;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006029 } else {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006030 levels->speed = ss;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006031 }
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006032 levels->status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006033
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006034 s = copy_to_user(argp, levels, sizeof(struct hdspm_peak_rms));
Adrian Knoth0dca1792011-01-26 19:32:14 +01006035 if (0 != s) {
6036 /* snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu
6037 [Levels]\n", sizeof(struct hdspm_peak_rms), s);
6038 */
Takashi Iwai763f3562005-06-03 11:25:34 +02006039 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006040 }
6041 break;
6042
6043 case SNDRV_HDSPM_IOCTL_GET_LTC:
6044 ltc.ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
6045 i = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
6046 if (i & HDSPM_TCO1_LTC_Input_valid) {
6047 switch (i & (HDSPM_TCO1_LTC_Format_LSB |
6048 HDSPM_TCO1_LTC_Format_MSB)) {
6049 case 0:
6050 ltc.format = fps_24;
6051 break;
6052 case HDSPM_TCO1_LTC_Format_LSB:
6053 ltc.format = fps_25;
6054 break;
6055 case HDSPM_TCO1_LTC_Format_MSB:
6056 ltc.format = fps_2997;
6057 break;
6058 default:
6059 ltc.format = 30;
6060 break;
6061 }
6062 if (i & HDSPM_TCO1_set_drop_frame_flag) {
6063 ltc.frame = drop_frame;
6064 } else {
6065 ltc.frame = full_frame;
6066 }
6067 } else {
6068 ltc.format = format_invalid;
6069 ltc.frame = frame_invalid;
6070 }
6071 if (i & HDSPM_TCO1_Video_Input_Format_NTSC) {
6072 ltc.input_format = ntsc;
6073 } else if (i & HDSPM_TCO1_Video_Input_Format_PAL) {
6074 ltc.input_format = pal;
6075 } else {
6076 ltc.input_format = no_video;
6077 }
6078
6079 s = copy_to_user(argp, &ltc, sizeof(struct hdspm_ltc));
6080 if (0 != s) {
6081 /*
6082 snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */
Takashi Iwai763f3562005-06-03 11:25:34 +02006083 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006084 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006085
6086 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02006087
Adrian Knoth0dca1792011-01-26 19:32:14 +01006088 case SNDRV_HDSPM_IOCTL_GET_CONFIG:
Takashi Iwai763f3562005-06-03 11:25:34 +02006089
Adrian Knoth4ab69a22011-02-23 11:43:14 +01006090 memset(&info, 0, sizeof(info));
Takashi Iwai763f3562005-06-03 11:25:34 +02006091 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006092 info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
6093 info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006094
6095 info.system_sample_rate = hdspm->system_sample_rate;
6096 info.autosync_sample_rate =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006097 hdspm_external_sample_rate(hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006098 info.system_clock_mode = hdspm_system_clock_mode(hdspm);
6099 info.clock_source = hdspm_clock_source(hdspm);
6100 info.autosync_ref = hdspm_autosync_ref(hdspm);
6101 info.line_out = hdspm_line_out(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006102 info.passthru = 0;
6103 spin_unlock_irq(&hdspm->lock);
6104 if (copy_to_user((void __user *) arg, &info, sizeof(info)))
6105 return -EFAULT;
6106 break;
6107
Adrian Knoth0dca1792011-01-26 19:32:14 +01006108 case SNDRV_HDSPM_IOCTL_GET_STATUS:
6109 status.card_type = hdspm->io_type;
6110
6111 status.autosync_source = hdspm_autosync_ref(hdspm);
6112
6113 status.card_clock = 110069313433624ULL;
6114 status.master_period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
6115
6116 switch (hdspm->io_type) {
6117 case MADI:
6118 case MADIface:
6119 status.card_specific.madi.sync_wc =
6120 hdspm_wc_sync_check(hdspm);
6121 status.card_specific.madi.sync_madi =
6122 hdspm_madi_sync_check(hdspm);
6123 status.card_specific.madi.sync_tco =
6124 hdspm_tco_sync_check(hdspm);
6125 status.card_specific.madi.sync_in =
6126 hdspm_sync_in_sync_check(hdspm);
6127
6128 statusregister =
6129 hdspm_read(hdspm, HDSPM_statusRegister);
6130 status.card_specific.madi.madi_input =
6131 (statusregister & HDSPM_AB_int) ? 1 : 0;
6132 status.card_specific.madi.channel_format =
6133 (statusregister & HDSPM_TX_64ch) ? 1 : 0;
6134 /* TODO: Mac driver sets it when f_s>48kHz */
6135 status.card_specific.madi.frame_format = 0;
6136
6137 default:
6138 break;
6139 }
6140
6141 if (copy_to_user((void __user *) arg, &status, sizeof(status)))
6142 return -EFAULT;
6143
6144
6145 break;
6146
Takashi Iwai763f3562005-06-03 11:25:34 +02006147 case SNDRV_HDSPM_IOCTL_GET_VERSION:
Adrian Knoth0dca1792011-01-26 19:32:14 +01006148 hdspm_version.card_type = hdspm->io_type;
6149 strncpy(hdspm_version.cardname, hdspm->card_name,
6150 sizeof(hdspm_version.cardname));
6151 hdspm_version.serial = (hdspm_read(hdspm,
6152 HDSPM_midiStatusIn0)>>8) & 0xFFFFFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02006153 hdspm_version.firmware_rev = hdspm->firmware_rev;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006154 hdspm_version.addons = 0;
6155 if (hdspm->tco)
6156 hdspm_version.addons |= HDSPM_ADDON_TCO;
6157
Takashi Iwai763f3562005-06-03 11:25:34 +02006158 if (copy_to_user((void __user *) arg, &hdspm_version,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006159 sizeof(hdspm_version)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006160 return -EFAULT;
6161 break;
6162
6163 case SNDRV_HDSPM_IOCTL_GET_MIXER:
6164 if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer)))
6165 return -EFAULT;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006166 if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006167 sizeof(struct hdspm_mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006168 return -EFAULT;
6169 break;
6170
6171 default:
6172 return -EINVAL;
6173 }
6174 return 0;
6175}
6176
Takashi Iwai98274f02005-11-17 14:52:34 +01006177static struct snd_pcm_ops snd_hdspm_playback_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006178 .open = snd_hdspm_playback_open,
6179 .close = snd_hdspm_playback_release,
6180 .ioctl = snd_hdspm_ioctl,
6181 .hw_params = snd_hdspm_hw_params,
6182 .hw_free = snd_hdspm_hw_free,
6183 .prepare = snd_hdspm_prepare,
6184 .trigger = snd_hdspm_trigger,
6185 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006186 .page = snd_pcm_sgbuf_ops_page,
6187};
6188
Takashi Iwai98274f02005-11-17 14:52:34 +01006189static struct snd_pcm_ops snd_hdspm_capture_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006190 .open = snd_hdspm_capture_open,
6191 .close = snd_hdspm_capture_release,
6192 .ioctl = snd_hdspm_ioctl,
6193 .hw_params = snd_hdspm_hw_params,
6194 .hw_free = snd_hdspm_hw_free,
6195 .prepare = snd_hdspm_prepare,
6196 .trigger = snd_hdspm_trigger,
6197 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006198 .page = snd_pcm_sgbuf_ops_page,
6199};
6200
Takashi Iwai98274f02005-11-17 14:52:34 +01006201static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
6202 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006203{
Takashi Iwai98274f02005-11-17 14:52:34 +01006204 struct snd_hwdep *hw;
Takashi Iwai763f3562005-06-03 11:25:34 +02006205 int err;
6206
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006207 err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw);
6208 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006209 return err;
6210
6211 hdspm->hwdep = hw;
6212 hw->private_data = hdspm;
6213 strcpy(hw->name, "HDSPM hwdep interface");
6214
Adrian Knoth0dca1792011-01-26 19:32:14 +01006215 hw->ops.open = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006216 hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006217 hw->ops.release = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006218
6219 return 0;
6220}
6221
6222
6223/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01006224 memory interface
Takashi Iwai763f3562005-06-03 11:25:34 +02006225 ------------------------------------------------------------*/
Adrian Knoth0dca1792011-01-26 19:32:14 +01006226static int __devinit snd_hdspm_preallocate_memory(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006227{
6228 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01006229 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006230 size_t wanted;
6231
6232 pcm = hdspm->pcm;
6233
Remy Bruno3cee5a62006-10-16 12:46:32 +02006234 wanted = HDSPM_DMA_AREA_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02006235
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006236 err =
Takashi Iwai763f3562005-06-03 11:25:34 +02006237 snd_pcm_lib_preallocate_pages_for_all(pcm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006238 SNDRV_DMA_TYPE_DEV_SG,
Takashi Iwai763f3562005-06-03 11:25:34 +02006239 snd_dma_pci_data(hdspm->pci),
6240 wanted,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006241 wanted);
6242 if (err < 0) {
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006243 snd_printdd("Could not preallocate %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006244
6245 return err;
6246 } else
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006247 snd_printdd(" Preallocated %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006248
6249 return 0;
6250}
6251
Adrian Knoth0dca1792011-01-26 19:32:14 +01006252
6253static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +02006254 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02006255 unsigned int reg, int channels)
6256{
6257 int i;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006258
6259 /* continuous memory segment */
Takashi Iwai763f3562005-06-03 11:25:34 +02006260 for (i = 0; i < (channels * 16); i++)
6261 hdspm_write(hdspm, reg + 4 * i,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006262 snd_pcm_sgbuf_get_addr(substream, 4096 * i));
Takashi Iwai763f3562005-06-03 11:25:34 +02006263}
6264
Adrian Knoth0dca1792011-01-26 19:32:14 +01006265
Takashi Iwai763f3562005-06-03 11:25:34 +02006266/* ------------- ALSA Devices ---------------------------- */
Takashi Iwai98274f02005-11-17 14:52:34 +01006267static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006268 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006269{
Takashi Iwai98274f02005-11-17 14:52:34 +01006270 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006271 int err;
6272
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006273 err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm);
6274 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006275 return err;
6276
6277 hdspm->pcm = pcm;
6278 pcm->private_data = hdspm;
6279 strcpy(pcm->name, hdspm->card_name);
6280
6281 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
6282 &snd_hdspm_playback_ops);
6283 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
6284 &snd_hdspm_capture_ops);
6285
6286 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
6287
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006288 err = snd_hdspm_preallocate_memory(hdspm);
6289 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006290 return err;
6291
6292 return 0;
6293}
6294
Takashi Iwai98274f02005-11-17 14:52:34 +01006295static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006296{
Adrian Knoth7c7102b2011-02-28 15:14:50 +01006297 int i;
6298
6299 for (i = 0; i < hdspm->midiPorts; i++)
6300 snd_hdspm_flush_midi_input(hdspm, i);
Takashi Iwai763f3562005-06-03 11:25:34 +02006301}
6302
Takashi Iwai98274f02005-11-17 14:52:34 +01006303static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
6304 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006305{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006306 int err, i;
Takashi Iwai763f3562005-06-03 11:25:34 +02006307
6308 snd_printdd("Create card...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006309 err = snd_hdspm_create_pcm(card, hdspm);
6310 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006311 return err;
6312
Adrian Knoth0dca1792011-01-26 19:32:14 +01006313 i = 0;
6314 while (i < hdspm->midiPorts) {
6315 err = snd_hdspm_create_midi(card, hdspm, i);
6316 if (err < 0) {
6317 return err;
6318 }
6319 i++;
6320 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006321
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006322 err = snd_hdspm_create_controls(card, hdspm);
6323 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006324 return err;
6325
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006326 err = snd_hdspm_create_hwdep(card, hdspm);
6327 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006328 return err;
6329
6330 snd_printdd("proc init...\n");
6331 snd_hdspm_proc_init(hdspm);
6332
6333 hdspm->system_sample_rate = -1;
6334 hdspm->last_external_sample_rate = -1;
6335 hdspm->last_internal_sample_rate = -1;
6336 hdspm->playback_pid = -1;
6337 hdspm->capture_pid = -1;
6338 hdspm->capture_substream = NULL;
6339 hdspm->playback_substream = NULL;
6340
6341 snd_printdd("Set defaults...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006342 err = snd_hdspm_set_defaults(hdspm);
6343 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006344 return err;
6345
6346 snd_printdd("Update mixer controls...\n");
6347 hdspm_update_simple_mixer_controls(hdspm);
6348
6349 snd_printdd("Initializeing complete ???\n");
6350
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006351 err = snd_card_register(card);
6352 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006353 snd_printk(KERN_ERR "HDSPM: error registering card\n");
6354 return err;
6355 }
6356
6357 snd_printdd("... yes now\n");
6358
6359 return 0;
6360}
6361
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006362static int __devinit snd_hdspm_create(struct snd_card *card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006363 struct hdspm *hdspm) {
6364
Takashi Iwai763f3562005-06-03 11:25:34 +02006365 struct pci_dev *pci = hdspm->pci;
6366 int err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006367 unsigned long io_extent;
6368
6369 hdspm->irq = -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02006370 hdspm->card = card;
6371
6372 spin_lock_init(&hdspm->lock);
6373
Takashi Iwai763f3562005-06-03 11:25:34 +02006374 pci_read_config_word(hdspm->pci,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006375 PCI_CLASS_REVISION, &hdspm->firmware_rev);
Remy Bruno3cee5a62006-10-16 12:46:32 +02006376
Takashi Iwai763f3562005-06-03 11:25:34 +02006377 strcpy(card->mixername, "Xilinx FPGA");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006378 strcpy(card->driver, "HDSPM");
6379
6380 switch (hdspm->firmware_rev) {
6381 case HDSPM_MADI_REV:
6382 hdspm->io_type = MADI;
6383 hdspm->card_name = "RME MADI";
6384 hdspm->midiPorts = 3;
6385 break;
6386 case HDSPM_RAYDAT_REV:
6387 hdspm->io_type = RayDAT;
6388 hdspm->card_name = "RME RayDAT";
6389 hdspm->midiPorts = 2;
6390 break;
6391 case HDSPM_AIO_REV:
6392 hdspm->io_type = AIO;
6393 hdspm->card_name = "RME AIO";
6394 hdspm->midiPorts = 1;
6395 break;
6396 case HDSPM_MADIFACE_REV:
6397 hdspm->io_type = MADIface;
6398 hdspm->card_name = "RME MADIface";
6399 hdspm->midiPorts = 1;
6400 break;
6401 case HDSPM_AES_REV:
Adrian Knoth526ea862011-02-28 15:14:48 +01006402 case HDSPM_AES32_REV:
Adrian Knothbdd32552011-03-07 19:10:11 +01006403 case HDSPM_AES32_OLD_REV:
Adrian Knoth0dca1792011-01-26 19:32:14 +01006404 hdspm->io_type = AES32;
6405 hdspm->card_name = "RME AES32";
6406 hdspm->midiPorts = 2;
6407 break;
Adrian Knoth5027f342011-02-28 15:14:49 +01006408 default:
6409 snd_printk(KERN_ERR "HDSPM: unknown firmware revision %x\n",
6410 hdspm->firmware_rev);
6411 return -ENODEV;
Remy Bruno3cee5a62006-10-16 12:46:32 +02006412 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006413
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006414 err = pci_enable_device(pci);
6415 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006416 return err;
6417
6418 pci_set_master(hdspm->pci);
6419
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006420 err = pci_request_regions(pci, "hdspm");
6421 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006422 return err;
6423
6424 hdspm->port = pci_resource_start(pci, 0);
6425 io_extent = pci_resource_len(pci, 0);
6426
6427 snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006428 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006429
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006430 hdspm->iobase = ioremap_nocache(hdspm->port, io_extent);
6431 if (!hdspm->iobase) {
6432 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006433 "unable to remap region 0x%lx-0x%lx\n",
6434 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006435 return -EBUSY;
6436 }
6437 snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006438 (unsigned long)hdspm->iobase, hdspm->port,
6439 hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006440
6441 if (request_irq(pci->irq, snd_hdspm_interrupt,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006442 IRQF_SHARED, "hdspm", hdspm)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006443 snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
6444 return -EBUSY;
6445 }
6446
6447 snd_printdd("use IRQ %d\n", pci->irq);
6448
6449 hdspm->irq = pci->irq;
Takashi Iwai763f3562005-06-03 11:25:34 +02006450
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006451 snd_printdd("kmalloc Mixer memory of %zd Bytes\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006452 sizeof(struct hdspm_mixer));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006453 hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL);
6454 if (!hdspm->mixer) {
6455 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006456 "unable to kmalloc Mixer memory of %d Bytes\n",
6457 (int)sizeof(struct hdspm_mixer));
Takashi Iwai763f3562005-06-03 11:25:34 +02006458 return err;
6459 }
6460
Adrian Knoth0dca1792011-01-26 19:32:14 +01006461 hdspm->port_names_in = NULL;
6462 hdspm->port_names_out = NULL;
6463
6464 switch (hdspm->io_type) {
6465 case AES32:
Adrian Knothd2d10a22011-02-28 15:14:47 +01006466 hdspm->ss_in_channels = hdspm->ss_out_channels = AES32_CHANNELS;
6467 hdspm->ds_in_channels = hdspm->ds_out_channels = AES32_CHANNELS;
6468 hdspm->qs_in_channels = hdspm->qs_out_channels = AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006469
6470 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6471 channel_map_aes32;
6472 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6473 channel_map_aes32;
6474 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6475 channel_map_aes32;
6476 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6477 texts_ports_aes32;
6478 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6479 texts_ports_aes32;
6480 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6481 texts_ports_aes32;
6482
Adrian Knothd2d10a22011-02-28 15:14:47 +01006483 hdspm->max_channels_out = hdspm->max_channels_in =
6484 AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006485 hdspm->port_names_in = hdspm->port_names_out =
6486 texts_ports_aes32;
6487 hdspm->channel_map_in = hdspm->channel_map_out =
6488 channel_map_aes32;
6489
Adrian Knoth0dca1792011-01-26 19:32:14 +01006490 break;
6491
6492 case MADI:
6493 case MADIface:
6494 hdspm->ss_in_channels = hdspm->ss_out_channels =
6495 MADI_SS_CHANNELS;
6496 hdspm->ds_in_channels = hdspm->ds_out_channels =
6497 MADI_DS_CHANNELS;
6498 hdspm->qs_in_channels = hdspm->qs_out_channels =
6499 MADI_QS_CHANNELS;
6500
6501 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6502 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006503 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006504 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006505 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006506 channel_map_unity_ss;
6507
6508 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6509 texts_ports_madi;
6510 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6511 texts_ports_madi;
6512 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6513 texts_ports_madi;
6514 break;
6515
6516 case AIO:
6517 if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) {
6518 snd_printk(KERN_INFO "HDSPM: AEB input board found, but not supported\n");
6519 }
6520
6521 hdspm->ss_in_channels = AIO_IN_SS_CHANNELS;
6522 hdspm->ds_in_channels = AIO_IN_DS_CHANNELS;
6523 hdspm->qs_in_channels = AIO_IN_QS_CHANNELS;
6524 hdspm->ss_out_channels = AIO_OUT_SS_CHANNELS;
6525 hdspm->ds_out_channels = AIO_OUT_DS_CHANNELS;
6526 hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS;
6527
6528 hdspm->channel_map_out_ss = channel_map_aio_out_ss;
6529 hdspm->channel_map_out_ds = channel_map_aio_out_ds;
6530 hdspm->channel_map_out_qs = channel_map_aio_out_qs;
6531
6532 hdspm->channel_map_in_ss = channel_map_aio_in_ss;
6533 hdspm->channel_map_in_ds = channel_map_aio_in_ds;
6534 hdspm->channel_map_in_qs = channel_map_aio_in_qs;
6535
6536 hdspm->port_names_in_ss = texts_ports_aio_in_ss;
6537 hdspm->port_names_out_ss = texts_ports_aio_out_ss;
6538 hdspm->port_names_in_ds = texts_ports_aio_in_ds;
6539 hdspm->port_names_out_ds = texts_ports_aio_out_ds;
6540 hdspm->port_names_in_qs = texts_ports_aio_in_qs;
6541 hdspm->port_names_out_qs = texts_ports_aio_out_qs;
6542
6543 break;
6544
6545 case RayDAT:
6546 hdspm->ss_in_channels = hdspm->ss_out_channels =
6547 RAYDAT_SS_CHANNELS;
6548 hdspm->ds_in_channels = hdspm->ds_out_channels =
6549 RAYDAT_DS_CHANNELS;
6550 hdspm->qs_in_channels = hdspm->qs_out_channels =
6551 RAYDAT_QS_CHANNELS;
6552
6553 hdspm->max_channels_in = RAYDAT_SS_CHANNELS;
6554 hdspm->max_channels_out = RAYDAT_SS_CHANNELS;
6555
6556 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6557 channel_map_raydat_ss;
6558 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6559 channel_map_raydat_ds;
6560 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6561 channel_map_raydat_qs;
6562 hdspm->channel_map_in = hdspm->channel_map_out =
6563 channel_map_raydat_ss;
6564
6565 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6566 texts_ports_raydat_ss;
6567 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6568 texts_ports_raydat_ds;
6569 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6570 texts_ports_raydat_qs;
6571
6572
6573 break;
6574
6575 }
6576
6577 /* TCO detection */
6578 switch (hdspm->io_type) {
6579 case AIO:
6580 case RayDAT:
6581 if (hdspm_read(hdspm, HDSPM_statusRegister2) &
6582 HDSPM_s2_tco_detect) {
6583 hdspm->midiPorts++;
6584 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6585 GFP_KERNEL);
6586 if (NULL != hdspm->tco) {
6587 hdspm_tco_write(hdspm);
6588 }
6589 snd_printk(KERN_INFO "HDSPM: AIO/RayDAT TCO module found\n");
6590 } else {
6591 hdspm->tco = NULL;
6592 }
6593 break;
6594
6595 case MADI:
6596 if (hdspm_read(hdspm, HDSPM_statusRegister) & HDSPM_tco_detect) {
6597 hdspm->midiPorts++;
6598 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6599 GFP_KERNEL);
6600 if (NULL != hdspm->tco) {
6601 hdspm_tco_write(hdspm);
6602 }
6603 snd_printk(KERN_INFO "HDSPM: MADI TCO module found\n");
6604 } else {
6605 hdspm->tco = NULL;
6606 }
6607 break;
6608
6609 default:
6610 hdspm->tco = NULL;
6611 }
6612
6613 /* texts */
6614 switch (hdspm->io_type) {
6615 case AES32:
6616 if (hdspm->tco) {
6617 hdspm->texts_autosync = texts_autosync_aes_tco;
6618 hdspm->texts_autosync_items = 10;
6619 } else {
6620 hdspm->texts_autosync = texts_autosync_aes;
6621 hdspm->texts_autosync_items = 9;
6622 }
6623 break;
6624
6625 case MADI:
6626 if (hdspm->tco) {
6627 hdspm->texts_autosync = texts_autosync_madi_tco;
6628 hdspm->texts_autosync_items = 4;
6629 } else {
6630 hdspm->texts_autosync = texts_autosync_madi;
6631 hdspm->texts_autosync_items = 3;
6632 }
6633 break;
6634
6635 case MADIface:
6636
6637 break;
6638
6639 case RayDAT:
6640 if (hdspm->tco) {
6641 hdspm->texts_autosync = texts_autosync_raydat_tco;
6642 hdspm->texts_autosync_items = 9;
6643 } else {
6644 hdspm->texts_autosync = texts_autosync_raydat;
6645 hdspm->texts_autosync_items = 8;
6646 }
6647 break;
6648
6649 case AIO:
6650 if (hdspm->tco) {
6651 hdspm->texts_autosync = texts_autosync_aio_tco;
6652 hdspm->texts_autosync_items = 6;
6653 } else {
6654 hdspm->texts_autosync = texts_autosync_aio;
6655 hdspm->texts_autosync_items = 5;
6656 }
6657 break;
6658
6659 }
6660
6661 tasklet_init(&hdspm->midi_tasklet,
6662 hdspm_midi_tasklet, (unsigned long) hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006663
6664 snd_printdd("create alsa devices.\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006665 err = snd_hdspm_create_alsa_devices(card, hdspm);
6666 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006667 return err;
6668
6669 snd_hdspm_initialize_midi_flush(hdspm);
6670
6671 return 0;
6672}
6673
Adrian Knoth0dca1792011-01-26 19:32:14 +01006674
Takashi Iwai98274f02005-11-17 14:52:34 +01006675static int snd_hdspm_free(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006676{
6677
6678 if (hdspm->port) {
6679
6680 /* stop th audio, and cancel all interrupts */
6681 hdspm->control_register &=
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006682 ~(HDSPM_Start | HDSPM_AudioInterruptEnable |
Adrian Knoth0dca1792011-01-26 19:32:14 +01006683 HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable |
6684 HDSPM_Midi2InterruptEnable | HDSPM_Midi3InterruptEnable);
Takashi Iwai763f3562005-06-03 11:25:34 +02006685 hdspm_write(hdspm, HDSPM_controlRegister,
6686 hdspm->control_register);
6687 }
6688
6689 if (hdspm->irq >= 0)
6690 free_irq(hdspm->irq, (void *) hdspm);
6691
Jesper Juhlfc584222005-10-24 15:11:28 +02006692 kfree(hdspm->mixer);
Takashi Iwai763f3562005-06-03 11:25:34 +02006693
6694 if (hdspm->iobase)
6695 iounmap(hdspm->iobase);
6696
Takashi Iwai763f3562005-06-03 11:25:34 +02006697 if (hdspm->port)
6698 pci_release_regions(hdspm->pci);
6699
6700 pci_disable_device(hdspm->pci);
6701 return 0;
6702}
6703
Adrian Knoth0dca1792011-01-26 19:32:14 +01006704
Takashi Iwai98274f02005-11-17 14:52:34 +01006705static void snd_hdspm_card_free(struct snd_card *card)
Takashi Iwai763f3562005-06-03 11:25:34 +02006706{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006707 struct hdspm *hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006708
6709 if (hdspm)
6710 snd_hdspm_free(hdspm);
6711}
6712
Adrian Knoth0dca1792011-01-26 19:32:14 +01006713
Takashi Iwai763f3562005-06-03 11:25:34 +02006714static int __devinit snd_hdspm_probe(struct pci_dev *pci,
6715 const struct pci_device_id *pci_id)
6716{
6717 static int dev;
Takashi Iwai98274f02005-11-17 14:52:34 +01006718 struct hdspm *hdspm;
6719 struct snd_card *card;
Takashi Iwai763f3562005-06-03 11:25:34 +02006720 int err;
6721
6722 if (dev >= SNDRV_CARDS)
6723 return -ENODEV;
6724 if (!enable[dev]) {
6725 dev++;
6726 return -ENOENT;
6727 }
6728
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006729 err = snd_card_create(index[dev], id[dev],
Adrian Knoth0dca1792011-01-26 19:32:14 +01006730 THIS_MODULE, sizeof(struct hdspm), &card);
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006731 if (err < 0)
6732 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006733
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006734 hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006735 card->private_free = snd_hdspm_card_free;
6736 hdspm->dev = dev;
6737 hdspm->pci = pci;
6738
Takashi Iwaic187c042007-02-19 15:27:33 +01006739 snd_card_set_dev(card, &pci->dev);
6740
Adrian Knoth0dca1792011-01-26 19:32:14 +01006741 err = snd_hdspm_create(card, hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006742 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006743 snd_card_free(card);
6744 return err;
6745 }
6746
Adrian Knoth0dca1792011-01-26 19:32:14 +01006747 if (hdspm->io_type != MADIface) {
6748 sprintf(card->shortname, "%s_%x",
6749 hdspm->card_name,
6750 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF);
6751 sprintf(card->longname, "%s S/N 0x%x at 0x%lx, irq %d",
6752 hdspm->card_name,
6753 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF,
6754 hdspm->port, hdspm->irq);
6755 } else {
6756 sprintf(card->shortname, "%s", hdspm->card_name);
6757 sprintf(card->longname, "%s at 0x%lx, irq %d",
6758 hdspm->card_name, hdspm->port, hdspm->irq);
6759 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006760
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006761 err = snd_card_register(card);
6762 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006763 snd_card_free(card);
6764 return err;
6765 }
6766
6767 pci_set_drvdata(pci, card);
6768
6769 dev++;
6770 return 0;
6771}
6772
6773static void __devexit snd_hdspm_remove(struct pci_dev *pci)
6774{
6775 snd_card_free(pci_get_drvdata(pci));
6776 pci_set_drvdata(pci, NULL);
6777}
6778
6779static struct pci_driver driver = {
6780 .name = "RME Hammerfall DSP MADI",
Takashi Iwai763f3562005-06-03 11:25:34 +02006781 .id_table = snd_hdspm_ids,
6782 .probe = snd_hdspm_probe,
6783 .remove = __devexit_p(snd_hdspm_remove),
6784};
6785
6786
6787static int __init alsa_card_hdspm_init(void)
6788{
6789 return pci_register_driver(&driver);
6790}
6791
6792static void __exit alsa_card_hdspm_exit(void)
6793{
6794 pci_unregister_driver(&driver);
6795}
6796
6797module_init(alsa_card_hdspm_init)
6798module_exit(alsa_card_hdspm_exit)