blob: 0ed4b4e981d844bb939f5208915e636c93a3dcbe [file] [log] [blame]
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001/*
Takashi Iwai763f3562005-06-03 11:25:34 +02002 * ALSA driver for RME Hammerfall DSP MADI audio interface(s)
3 *
4 * Copyright (c) 2003 Winfried Ritsch (IEM)
5 * code based on hdsp.c Paul Davis
6 * Marcus Andersson
7 * Thomas Charbonnel
Remy Bruno3cee5a62006-10-16 12:46:32 +02008 * Modified 2006-06-01 for AES32 support by Remy Bruno
9 * <remy.bruno@trinnov.com>
Takashi Iwai763f3562005-06-03 11:25:34 +020010 *
Adrian Knoth0dca1792011-01-26 19:32:14 +010011 * Modified 2009-04-13 for proper metering by Florian Faber
12 * <faber@faberman.de>
13 *
14 * Modified 2009-04-14 for native float support by Florian Faber
15 * <faber@faberman.de>
16 *
17 * Modified 2009-04-26 fixed bug in rms metering by Florian Faber
18 * <faber@faberman.de>
19 *
20 * Modified 2009-04-30 added hw serial number support by Florian Faber
21 *
22 * Modified 2011-01-14 added S/PDIF input on RayDATs by Adrian Knoth
23 *
24 * Modified 2011-01-25 variable period sizes on RayDAT/AIO by Adrian Knoth
25 *
Takashi Iwai763f3562005-06-03 11:25:34 +020026 * This program is free software; you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License as published by
28 * the Free Software Foundation; either version 2 of the License, or
29 * (at your option) any later version.
30 *
31 * This program is distributed in the hope that it will be useful,
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 * GNU General Public License for more details.
35 *
36 * You should have received a copy of the GNU General Public License
37 * along with this program; if not, write to the Free Software
38 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 *
40 */
Takashi Iwai763f3562005-06-03 11:25:34 +020041#include <linux/init.h>
42#include <linux/delay.h>
43#include <linux/interrupt.h>
44#include <linux/moduleparam.h>
45#include <linux/slab.h>
46#include <linux/pci.h>
Takashi Iwai3f7440a2009-06-05 17:40:04 +020047#include <linux/math64.h>
Takashi Iwai763f3562005-06-03 11:25:34 +020048#include <asm/io.h>
49
50#include <sound/core.h>
51#include <sound/control.h>
52#include <sound/pcm.h>
Adrian Knoth0dca1792011-01-26 19:32:14 +010053#include <sound/pcm_params.h>
Takashi Iwai763f3562005-06-03 11:25:34 +020054#include <sound/info.h>
55#include <sound/asoundef.h>
56#include <sound/rawmidi.h>
57#include <sound/hwdep.h>
58#include <sound/initval.h>
59
60#include <sound/hdspm.h>
61
62static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
63static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
64static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
65
Takashi Iwai763f3562005-06-03 11:25:34 +020066module_param_array(index, int, NULL, 0444);
67MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");
68
69module_param_array(id, charp, NULL, 0444);
70MODULE_PARM_DESC(id, "ID string for RME HDSPM interface.");
71
72module_param_array(enable, bool, NULL, 0444);
73MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");
74
Takashi Iwai763f3562005-06-03 11:25:34 +020075
76MODULE_AUTHOR
Adrian Knoth0dca1792011-01-26 19:32:14 +010077(
78 "Winfried Ritsch <ritsch_AT_iem.at>, "
79 "Paul Davis <paul@linuxaudiosystems.com>, "
80 "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, "
81 "Remy Bruno <remy.bruno@trinnov.com>, "
82 "Florian Faber <faberman@linuxproaudio.org>, "
83 "Adrian Knoth <adi@drcomp.erfurt.thur.de>"
84);
Takashi Iwai763f3562005-06-03 11:25:34 +020085MODULE_DESCRIPTION("RME HDSPM");
86MODULE_LICENSE("GPL");
87MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
88
Adrian Knoth0dca1792011-01-26 19:32:14 +010089/* --- Write registers. ---
Takashi Iwai763f3562005-06-03 11:25:34 +020090 These are defined as byte-offsets from the iobase value. */
91
Adrian Knoth0dca1792011-01-26 19:32:14 +010092#define HDSPM_WR_SETTINGS 0
93#define HDSPM_outputBufferAddress 32
94#define HDSPM_inputBufferAddress 36
Takashi Iwai763f3562005-06-03 11:25:34 +020095#define HDSPM_controlRegister 64
96#define HDSPM_interruptConfirmation 96
97#define HDSPM_control2Reg 256 /* not in specs ???????? */
Remy Brunoffb2c3c2007-03-07 19:08:46 +010098#define HDSPM_freqReg 256 /* for AES32 */
Adrian Knoth0dca1792011-01-26 19:32:14 +010099#define HDSPM_midiDataOut0 352 /* just believe in old code */
100#define HDSPM_midiDataOut1 356
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100101#define HDSPM_eeprom_wr 384 /* for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200102
103/* DMA enable for 64 channels, only Bit 0 is relevant */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100104#define HDSPM_outputEnableBase 512 /* 512-767 input DMA */
Takashi Iwai763f3562005-06-03 11:25:34 +0200105#define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */
106
Adrian Knoth0dca1792011-01-26 19:32:14 +0100107/* 16 page addresses for each of the 64 channels DMA buffer in and out
Takashi Iwai763f3562005-06-03 11:25:34 +0200108 (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */
109#define HDSPM_pageAddressBufferOut 8192
110#define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4)
111
112#define HDSPM_MADI_mixerBase 32768 /* 32768-65535 for 2x64x64 Fader */
113
114#define HDSPM_MATRIX_MIXER_SIZE 8192 /* = 2*64*64 * 4 Byte => 32kB */
115
116/* --- Read registers. ---
117 These are defined as byte-offsets from the iobase value */
118#define HDSPM_statusRegister 0
Remy Bruno3cee5a62006-10-16 12:46:32 +0200119/*#define HDSPM_statusRegister2 96 */
120/* after RME Windows driver sources, status2 is 4-byte word # 48 = word at
121 * offset 192, for AES32 *and* MADI
122 * => need to check that offset 192 is working on MADI */
123#define HDSPM_statusRegister2 192
124#define HDSPM_timecodeRegister 128
Takashi Iwai763f3562005-06-03 11:25:34 +0200125
Adrian Knoth0dca1792011-01-26 19:32:14 +0100126/* AIO, RayDAT */
127#define HDSPM_RD_STATUS_0 0
128#define HDSPM_RD_STATUS_1 64
129#define HDSPM_RD_STATUS_2 128
130#define HDSPM_RD_STATUS_3 192
131
132#define HDSPM_RD_TCO 256
133#define HDSPM_RD_PLL_FREQ 512
134#define HDSPM_WR_TCO 128
135
136#define HDSPM_TCO1_TCO_lock 0x00000001
137#define HDSPM_TCO1_WCK_Input_Range_LSB 0x00000002
138#define HDSPM_TCO1_WCK_Input_Range_MSB 0x00000004
139#define HDSPM_TCO1_LTC_Input_valid 0x00000008
140#define HDSPM_TCO1_WCK_Input_valid 0x00000010
141#define HDSPM_TCO1_Video_Input_Format_NTSC 0x00000020
142#define HDSPM_TCO1_Video_Input_Format_PAL 0x00000040
143
144#define HDSPM_TCO1_set_TC 0x00000100
145#define HDSPM_TCO1_set_drop_frame_flag 0x00000200
146#define HDSPM_TCO1_LTC_Format_LSB 0x00000400
147#define HDSPM_TCO1_LTC_Format_MSB 0x00000800
148
149#define HDSPM_TCO2_TC_run 0x00010000
150#define HDSPM_TCO2_WCK_IO_ratio_LSB 0x00020000
151#define HDSPM_TCO2_WCK_IO_ratio_MSB 0x00040000
152#define HDSPM_TCO2_set_num_drop_frames_LSB 0x00080000
153#define HDSPM_TCO2_set_num_drop_frames_MSB 0x00100000
154#define HDSPM_TCO2_set_jam_sync 0x00200000
155#define HDSPM_TCO2_set_flywheel 0x00400000
156
157#define HDSPM_TCO2_set_01_4 0x01000000
158#define HDSPM_TCO2_set_pull_down 0x02000000
159#define HDSPM_TCO2_set_pull_up 0x04000000
160#define HDSPM_TCO2_set_freq 0x08000000
161#define HDSPM_TCO2_set_term_75R 0x10000000
162#define HDSPM_TCO2_set_input_LSB 0x20000000
163#define HDSPM_TCO2_set_input_MSB 0x40000000
164#define HDSPM_TCO2_set_freq_from_app 0x80000000
165
166
167#define HDSPM_midiDataOut0 352
168#define HDSPM_midiDataOut1 356
169#define HDSPM_midiDataOut2 368
170
Takashi Iwai763f3562005-06-03 11:25:34 +0200171#define HDSPM_midiDataIn0 360
172#define HDSPM_midiDataIn1 364
Adrian Knoth0dca1792011-01-26 19:32:14 +0100173#define HDSPM_midiDataIn2 372
174#define HDSPM_midiDataIn3 376
Takashi Iwai763f3562005-06-03 11:25:34 +0200175
176/* status is data bytes in MIDI-FIFO (0-128) */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100177#define HDSPM_midiStatusOut0 384
178#define HDSPM_midiStatusOut1 388
179#define HDSPM_midiStatusOut2 400
180
181#define HDSPM_midiStatusIn0 392
182#define HDSPM_midiStatusIn1 396
183#define HDSPM_midiStatusIn2 404
184#define HDSPM_midiStatusIn3 408
Takashi Iwai763f3562005-06-03 11:25:34 +0200185
186
187/* the meters are regular i/o-mapped registers, but offset
188 considerably from the rest. the peak registers are reset
Adrian Knoth0dca1792011-01-26 19:32:14 +0100189 when read; the least-significant 4 bits are full-scale counters;
Takashi Iwai763f3562005-06-03 11:25:34 +0200190 the actual peak value is in the most-significant 24 bits.
191*/
Adrian Knoth0dca1792011-01-26 19:32:14 +0100192
193#define HDSPM_MADI_INPUT_PEAK 4096
194#define HDSPM_MADI_PLAYBACK_PEAK 4352
195#define HDSPM_MADI_OUTPUT_PEAK 4608
196
197#define HDSPM_MADI_INPUT_RMS_L 6144
198#define HDSPM_MADI_PLAYBACK_RMS_L 6400
199#define HDSPM_MADI_OUTPUT_RMS_L 6656
200
201#define HDSPM_MADI_INPUT_RMS_H 7168
202#define HDSPM_MADI_PLAYBACK_RMS_H 7424
203#define HDSPM_MADI_OUTPUT_RMS_H 7680
Takashi Iwai763f3562005-06-03 11:25:34 +0200204
205/* --- Control Register bits --------- */
206#define HDSPM_Start (1<<0) /* start engine */
207
208#define HDSPM_Latency0 (1<<1) /* buffer size = 2^n */
209#define HDSPM_Latency1 (1<<2) /* where n is defined */
210#define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */
211
Adrian Knoth0dca1792011-01-26 19:32:14 +0100212#define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Autosync */
213#define HDSPM_c0Master 0x1 /* Master clock bit in settings
214 register [RayDAT, AIO] */
Takashi Iwai763f3562005-06-03 11:25:34 +0200215
216#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */
217
218#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */
219#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */
220#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200221#define HDSPM_QuadSpeed (1<<31) /* quad speed bit */
Takashi Iwai763f3562005-06-03 11:25:34 +0200222
Remy Bruno3cee5a62006-10-16 12:46:32 +0200223#define HDSPM_Professional (1<<9) /* Professional */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200224#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200225 56channelMODE=0 */ /* MADI ONLY*/
226#define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200227
Adrian Knoth0dca1792011-01-26 19:32:14 +0100228#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200229 0=off, 1=on */ /* MADI ONLY */
230#define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200231
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200232#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax
233 * -- MADI ONLY
234 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200235#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
236
Remy Bruno3cee5a62006-10-16 12:46:32 +0200237#define HDSPM_SyncRef2 (1<<13)
238#define HDSPM_SyncRef3 (1<<25)
Takashi Iwai763f3562005-06-03 11:25:34 +0200239
Remy Bruno3cee5a62006-10-16 12:46:32 +0200240#define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100241#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use
Takashi Iwai763f3562005-06-03 11:25:34 +0200242 AES additional bits in
243 lower 5 Audiodatabits ??? */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200244#define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */
245#define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200246
Adrian Knoth0dca1792011-01-26 19:32:14 +0100247#define HDSPM_Midi0InterruptEnable 0x0400000
248#define HDSPM_Midi1InterruptEnable 0x0800000
249#define HDSPM_Midi2InterruptEnable 0x0200000
250#define HDSPM_Midi3InterruptEnable 0x4000000
Takashi Iwai763f3562005-06-03 11:25:34 +0200251
252#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100253#define HDSPe_FLOAT_FORMAT 0x2000000
Takashi Iwai763f3562005-06-03 11:25:34 +0200254
Remy Bruno3cee5a62006-10-16 12:46:32 +0200255#define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */
256#define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */
257#define HDSPM_QS_QuadWire (1<<28) /* AES32 ONLY */
258
259#define HDSPM_wclk_sel (1<<30)
Takashi Iwai763f3562005-06-03 11:25:34 +0200260
261/* --- bit helper defines */
262#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200263#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|\
264 HDSPM_DoubleSpeed|HDSPM_QuadSpeed)
Takashi Iwai763f3562005-06-03 11:25:34 +0200265#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1)
266#define HDSPM_InputOptical 0
267#define HDSPM_InputCoaxial (HDSPM_InputSelect0)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200268#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\
269 HDSPM_SyncRef2|HDSPM_SyncRef3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200270
Adrian Knoth0dca1792011-01-26 19:32:14 +0100271#define HDSPM_c0_SyncRef0 0x2
272#define HDSPM_c0_SyncRef1 0x4
273#define HDSPM_c0_SyncRef2 0x8
274#define HDSPM_c0_SyncRef3 0x10
275#define HDSPM_c0_SyncRefMask (HDSPM_c0_SyncRef0 | HDSPM_c0_SyncRef1 |\
276 HDSPM_c0_SyncRef2 | HDSPM_c0_SyncRef3)
277
278#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */
279#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */
280#define HDSPM_SYNC_FROM_TCO 2
281#define HDSPM_SYNC_FROM_SYNC_IN 3
Takashi Iwai763f3562005-06-03 11:25:34 +0200282
283#define HDSPM_Frequency32KHz HDSPM_Frequency0
284#define HDSPM_Frequency44_1KHz HDSPM_Frequency1
285#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0)
286#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0)
287#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200288#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|\
289 HDSPM_Frequency0)
Remy Bruno3cee5a62006-10-16 12:46:32 +0200290#define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0)
291#define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200292#define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\
293 HDSPM_Frequency0)
Takashi Iwai763f3562005-06-03 11:25:34 +0200294
Takashi Iwai763f3562005-06-03 11:25:34 +0200295
296/* Synccheck Status */
297#define HDSPM_SYNC_CHECK_NO_LOCK 0
298#define HDSPM_SYNC_CHECK_LOCK 1
299#define HDSPM_SYNC_CHECK_SYNC 2
300
301/* AutoSync References - used by "autosync_ref" control switch */
302#define HDSPM_AUTOSYNC_FROM_WORD 0
303#define HDSPM_AUTOSYNC_FROM_MADI 1
Adrian Knoth0dca1792011-01-26 19:32:14 +0100304#define HDSPM_AUTOSYNC_FROM_TCO 2
305#define HDSPM_AUTOSYNC_FROM_SYNC_IN 3
306#define HDSPM_AUTOSYNC_FROM_NONE 4
Takashi Iwai763f3562005-06-03 11:25:34 +0200307
308/* Possible sources of MADI input */
309#define HDSPM_OPTICAL 0 /* optical */
310#define HDSPM_COAXIAL 1 /* BNC */
311
312#define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask)
Adrian Knoth0dca1792011-01-26 19:32:14 +0100313#define hdspm_decode_latency(x) ((((x) & HDSPM_LatencyMask)>>1))
Takashi Iwai763f3562005-06-03 11:25:34 +0200314
315#define hdspm_encode_in(x) (((x)&0x3)<<14)
316#define hdspm_decode_in(x) (((x)>>14)&0x3)
317
318/* --- control2 register bits --- */
319#define HDSPM_TMS (1<<0)
320#define HDSPM_TCK (1<<1)
321#define HDSPM_TDI (1<<2)
322#define HDSPM_JTAG (1<<3)
323#define HDSPM_PWDN (1<<4)
324#define HDSPM_PROGRAM (1<<5)
325#define HDSPM_CONFIG_MODE_0 (1<<6)
326#define HDSPM_CONFIG_MODE_1 (1<<7)
327/*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/
328#define HDSPM_BIGENDIAN_MODE (1<<9)
329#define HDSPM_RD_MULTIPLE (1<<10)
330
Remy Bruno3cee5a62006-10-16 12:46:32 +0200331/* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200332 that do not conflict with specific bits for AES32 seem to be valid also
333 for the AES32
334 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200335#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200336#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn MODE=0 */
337#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1
338 * (like inp0)
339 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100340
Takashi Iwai763f3562005-06-03 11:25:34 +0200341#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100342#define HDSPM_madiSync (1<<18) /* MADI is in sync */
343
344#define HDSPM_tcoLock 0x00000020 /* Optional TCO locked status FOR HDSPe MADI! */
345#define HDSPM_tcoSync 0x10000000 /* Optional TCO sync status */
346
347#define HDSPM_syncInLock 0x00010000 /* Sync In lock status FOR HDSPe MADI! */
348#define HDSPM_syncInSync 0x00020000 /* Sync In sync status FOR HDSPe MADI! */
Takashi Iwai763f3562005-06-03 11:25:34 +0200349
350#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100351 /* since 64byte accurate, last 6 bits are not used */
Takashi Iwai763f3562005-06-03 11:25:34 +0200352
Adrian Knoth0dca1792011-01-26 19:32:14 +0100353
354
Takashi Iwai763f3562005-06-03 11:25:34 +0200355#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */
356
357#define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */
358#define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */
359#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */
360#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */
361
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200362#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with
363 * Interrupt
364 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100365#define HDSPM_tco_detect 0x08000000
366#define HDSPM_tco_lock 0x20000000
367
368#define HDSPM_s2_tco_detect 0x00000040
369#define HDSPM_s2_AEBO_D 0x00000080
370#define HDSPM_s2_AEBI_D 0x00000100
371
372
373#define HDSPM_midi0IRQPending 0x40000000
374#define HDSPM_midi1IRQPending 0x80000000
375#define HDSPM_midi2IRQPending 0x20000000
376#define HDSPM_midi2IRQPendingAES 0x00000020
377#define HDSPM_midi3IRQPending 0x00200000
Takashi Iwai763f3562005-06-03 11:25:34 +0200378
379/* --- status bit helpers */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200380#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\
381 HDSPM_madiFreq2|HDSPM_madiFreq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200382#define HDSPM_madiFreq32 (HDSPM_madiFreq0)
383#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1)
384#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1)
385#define HDSPM_madiFreq64 (HDSPM_madiFreq2)
386#define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2)
387#define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2)
388#define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2)
389#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
390#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0)
391
Remy Bruno3cee5a62006-10-16 12:46:32 +0200392/* Status2 Register bits */ /* MADI ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200393
394#define HDSPM_version0 (1<<0) /* not realy defined but I guess */
395#define HDSPM_version1 (1<<1) /* in former cards it was ??? */
396#define HDSPM_version2 (1<<2)
397
398#define HDSPM_wcLock (1<<3) /* Wordclock is detected and locked */
399#define HDSPM_wcSync (1<<4) /* Wordclock is in sync with systemclock */
400
401#define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */
402#define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */
403#define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, */
404/* missing Bit for 111=128, 1000=176.4, 1001=192 */
405
Adrian Knoth0dca1792011-01-26 19:32:14 +0100406#define HDSPM_SyncRef0 0x10000 /* Sync Reference */
407#define HDSPM_SyncRef1 0x20000
408
409#define HDSPM_SelSyncRef0 (1<<8) /* AutoSync Source */
Takashi Iwai763f3562005-06-03 11:25:34 +0200410#define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */
411#define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */
412
413#define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync)
414
415#define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2)
416#define HDSPM_wcFreq32 (HDSPM_wc_freq0)
417#define HDSPM_wcFreq44_1 (HDSPM_wc_freq1)
418#define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1)
419#define HDSPM_wcFreq64 (HDSPM_wc_freq2)
420#define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2)
421#define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2)
422
Adrian Knoth0dca1792011-01-26 19:32:14 +0100423#define HDSPM_status1_F_0 0x0400000
424#define HDSPM_status1_F_1 0x0800000
425#define HDSPM_status1_F_2 0x1000000
426#define HDSPM_status1_F_3 0x2000000
427#define HDSPM_status1_freqMask (HDSPM_status1_F_0|HDSPM_status1_F_1|HDSPM_status1_F_2|HDSPM_status1_F_3)
428
Takashi Iwai763f3562005-06-03 11:25:34 +0200429
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200430#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
431 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200432#define HDSPM_SelSyncRef_WORD 0
433#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0)
Adrian Knoth0dca1792011-01-26 19:32:14 +0100434#define HDSPM_SelSyncRef_TCO (HDSPM_SelSyncRef1)
435#define HDSPM_SelSyncRef_SyncIn (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200436#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
437 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200438
Remy Bruno3cee5a62006-10-16 12:46:32 +0200439/*
440 For AES32, bits for status, status2 and timecode are different
441*/
442/* status */
443#define HDSPM_AES32_wcLock 0x0200000
444#define HDSPM_AES32_wcFreq_bit 22
Adrian Knoth0dca1792011-01-26 19:32:14 +0100445/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function
Remy Bruno3cee5a62006-10-16 12:46:32 +0200446 HDSPM_bit2freq */
447#define HDSPM_AES32_syncref_bit 16
448/* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */
449
450#define HDSPM_AES32_AUTOSYNC_FROM_WORD 0
451#define HDSPM_AES32_AUTOSYNC_FROM_AES1 1
452#define HDSPM_AES32_AUTOSYNC_FROM_AES2 2
453#define HDSPM_AES32_AUTOSYNC_FROM_AES3 3
454#define HDSPM_AES32_AUTOSYNC_FROM_AES4 4
455#define HDSPM_AES32_AUTOSYNC_FROM_AES5 5
456#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6
457#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7
458#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8
Remy Bruno65345992007-08-31 12:21:08 +0200459#define HDSPM_AES32_AUTOSYNC_FROM_NONE 9
Remy Bruno3cee5a62006-10-16 12:46:32 +0200460
461/* status2 */
462/* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */
463#define HDSPM_LockAES 0x80
464#define HDSPM_LockAES1 0x80
465#define HDSPM_LockAES2 0x40
466#define HDSPM_LockAES3 0x20
467#define HDSPM_LockAES4 0x10
468#define HDSPM_LockAES5 0x8
469#define HDSPM_LockAES6 0x4
470#define HDSPM_LockAES7 0x2
471#define HDSPM_LockAES8 0x1
472/*
473 Timecode
474 After windows driver sources, bits 4*i to 4*i+3 give the input frequency on
475 AES i+1
476 bits 3210
477 0001 32kHz
478 0010 44.1kHz
479 0011 48kHz
480 0100 64kHz
481 0101 88.2kHz
482 0110 96kHz
483 0111 128kHz
484 1000 176.4kHz
485 1001 192kHz
486 NB: Timecode register doesn't seem to work on AES32 card revision 230
487*/
488
Takashi Iwai763f3562005-06-03 11:25:34 +0200489/* Mixer Values */
490#define UNITY_GAIN 32768 /* = 65536/2 */
491#define MINUS_INFINITY_GAIN 0
492
Takashi Iwai763f3562005-06-03 11:25:34 +0200493/* Number of channels for different Speed Modes */
494#define MADI_SS_CHANNELS 64
495#define MADI_DS_CHANNELS 32
496#define MADI_QS_CHANNELS 16
497
Adrian Knoth0dca1792011-01-26 19:32:14 +0100498#define RAYDAT_SS_CHANNELS 36
499#define RAYDAT_DS_CHANNELS 20
500#define RAYDAT_QS_CHANNELS 12
501
502#define AIO_IN_SS_CHANNELS 14
503#define AIO_IN_DS_CHANNELS 10
504#define AIO_IN_QS_CHANNELS 8
505#define AIO_OUT_SS_CHANNELS 16
506#define AIO_OUT_DS_CHANNELS 12
507#define AIO_OUT_QS_CHANNELS 10
508
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
Remy Bruno3cee5a62006-10-16 12:46:32 +0200530
Remy Bruno65345992007-08-31 12:21:08 +0200531/* speed factor modes */
532#define HDSPM_SPEED_SINGLE 0
533#define HDSPM_SPEED_DOUBLE 1
534#define HDSPM_SPEED_QUAD 2
Adrian Knoth0dca1792011-01-26 19:32:14 +0100535
Remy Bruno65345992007-08-31 12:21:08 +0200536/* names for speed modes */
537static char *hdspm_speed_names[] = { "single", "double", "quad" };
538
Adrian Knoth0dca1792011-01-26 19:32:14 +0100539static char *texts_autosync_aes_tco[] = { "Word Clock",
540 "AES1", "AES2", "AES3", "AES4",
541 "AES5", "AES6", "AES7", "AES8",
542 "TCO" };
543static char *texts_autosync_aes[] = { "Word Clock",
544 "AES1", "AES2", "AES3", "AES4",
545 "AES5", "AES6", "AES7", "AES8" };
546static char *texts_autosync_madi_tco[] = { "Word Clock",
547 "MADI", "TCO", "Sync In" };
548static char *texts_autosync_madi[] = { "Word Clock",
549 "MADI", "Sync In" };
550
551static char *texts_autosync_raydat_tco[] = {
552 "Word Clock",
553 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
554 "AES", "SPDIF", "TCO", "Sync In"
555};
556static char *texts_autosync_raydat[] = {
557 "Word Clock",
558 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
559 "AES", "SPDIF", "Sync In"
560};
561static char *texts_autosync_aio_tco[] = {
562 "Word Clock",
563 "ADAT", "AES", "SPDIF", "TCO", "Sync In"
564};
565static char *texts_autosync_aio[] = { "Word Clock",
566 "ADAT", "AES", "SPDIF", "Sync In" };
567
568static char *texts_freq[] = {
569 "No Lock",
570 "32 kHz",
571 "44.1 kHz",
572 "48 kHz",
573 "64 kHz",
574 "88.2 kHz",
575 "96 kHz",
576 "128 kHz",
577 "176.4 kHz",
578 "192 kHz"
579};
580
Adrian Knoth0dca1792011-01-26 19:32:14 +0100581static char *texts_ports_madi[] = {
582 "MADI.1", "MADI.2", "MADI.3", "MADI.4", "MADI.5", "MADI.6",
583 "MADI.7", "MADI.8", "MADI.9", "MADI.10", "MADI.11", "MADI.12",
584 "MADI.13", "MADI.14", "MADI.15", "MADI.16", "MADI.17", "MADI.18",
585 "MADI.19", "MADI.20", "MADI.21", "MADI.22", "MADI.23", "MADI.24",
586 "MADI.25", "MADI.26", "MADI.27", "MADI.28", "MADI.29", "MADI.30",
587 "MADI.31", "MADI.32", "MADI.33", "MADI.34", "MADI.35", "MADI.36",
588 "MADI.37", "MADI.38", "MADI.39", "MADI.40", "MADI.41", "MADI.42",
589 "MADI.43", "MADI.44", "MADI.45", "MADI.46", "MADI.47", "MADI.48",
590 "MADI.49", "MADI.50", "MADI.51", "MADI.52", "MADI.53", "MADI.54",
591 "MADI.55", "MADI.56", "MADI.57", "MADI.58", "MADI.59", "MADI.60",
592 "MADI.61", "MADI.62", "MADI.63", "MADI.64",
593};
594
595
596static char *texts_ports_raydat_ss[] = {
597 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT1.5", "ADAT1.6",
598 "ADAT1.7", "ADAT1.8", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
599 "ADAT2.5", "ADAT2.6", "ADAT2.7", "ADAT2.8", "ADAT3.1", "ADAT3.2",
600 "ADAT3.3", "ADAT3.4", "ADAT3.5", "ADAT3.6", "ADAT3.7", "ADAT3.8",
601 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4", "ADAT4.5", "ADAT4.6",
602 "ADAT4.7", "ADAT4.8",
603 "AES.L", "AES.R",
604 "SPDIF.L", "SPDIF.R"
605};
606
607static char *texts_ports_raydat_ds[] = {
608 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4",
609 "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
610 "ADAT3.1", "ADAT3.2", "ADAT3.3", "ADAT3.4",
611 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4",
612 "AES.L", "AES.R",
613 "SPDIF.L", "SPDIF.R"
614};
615
616static char *texts_ports_raydat_qs[] = {
617 "ADAT1.1", "ADAT1.2",
618 "ADAT2.1", "ADAT2.2",
619 "ADAT3.1", "ADAT3.2",
620 "ADAT4.1", "ADAT4.2",
621 "AES.L", "AES.R",
622 "SPDIF.L", "SPDIF.R"
623};
624
625
626static char *texts_ports_aio_in_ss[] = {
627 "Analogue.L", "Analogue.R",
628 "AES.L", "AES.R",
629 "SPDIF.L", "SPDIF.R",
630 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
631 "ADAT.7", "ADAT.8"
632};
633
634static char *texts_ports_aio_out_ss[] = {
635 "Analogue.L", "Analogue.R",
636 "AES.L", "AES.R",
637 "SPDIF.L", "SPDIF.R",
638 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
639 "ADAT.7", "ADAT.8",
640 "Phone.L", "Phone.R"
641};
642
643static char *texts_ports_aio_in_ds[] = {
644 "Analogue.L", "Analogue.R",
645 "AES.L", "AES.R",
646 "SPDIF.L", "SPDIF.R",
647 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
648};
649
650static char *texts_ports_aio_out_ds[] = {
651 "Analogue.L", "Analogue.R",
652 "AES.L", "AES.R",
653 "SPDIF.L", "SPDIF.R",
654 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
655 "Phone.L", "Phone.R"
656};
657
658static char *texts_ports_aio_in_qs[] = {
659 "Analogue.L", "Analogue.R",
660 "AES.L", "AES.R",
661 "SPDIF.L", "SPDIF.R",
662 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
663};
664
665static char *texts_ports_aio_out_qs[] = {
666 "Analogue.L", "Analogue.R",
667 "AES.L", "AES.R",
668 "SPDIF.L", "SPDIF.R",
669 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
670 "Phone.L", "Phone.R"
671};
672
Adrian Knoth432d2502011-02-23 11:43:08 +0100673static char *texts_ports_aes32[] = {
674 "AES.1", "AES.2", "AES.3", "AES.4", "AES.5", "AES.6", "AES.7",
675 "AES.8", "AES.9.", "AES.10", "AES.11", "AES.12", "AES.13", "AES.14",
676 "AES.15", "AES.16"
677};
678
Adrian Knoth55a57602011-01-27 11:23:15 +0100679/* These tables map the ALSA channels 1..N to the channels that we
680 need to use in order to find the relevant channel buffer. RME
681 refers to this kind of mapping as between "the ADAT channel and
682 the DMA channel." We index it using the logical audio channel,
683 and the value is the DMA channel (i.e. channel buffer number)
684 where the data for that channel can be read/written from/to.
685*/
686
687static char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = {
688 0, 1, 2, 3, 4, 5, 6, 7,
689 8, 9, 10, 11, 12, 13, 14, 15,
690 16, 17, 18, 19, 20, 21, 22, 23,
691 24, 25, 26, 27, 28, 29, 30, 31,
692 32, 33, 34, 35, 36, 37, 38, 39,
693 40, 41, 42, 43, 44, 45, 46, 47,
694 48, 49, 50, 51, 52, 53, 54, 55,
695 56, 57, 58, 59, 60, 61, 62, 63
696};
697
Adrian Knoth55a57602011-01-27 11:23:15 +0100698static char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = {
699 4, 5, 6, 7, 8, 9, 10, 11, /* ADAT 1 */
700 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT 2 */
701 20, 21, 22, 23, 24, 25, 26, 27, /* ADAT 3 */
702 28, 29, 30, 31, 32, 33, 34, 35, /* ADAT 4 */
703 0, 1, /* AES */
704 2, 3, /* SPDIF */
705 -1, -1, -1, -1,
706 -1, -1, -1, -1, -1, -1, -1, -1,
707 -1, -1, -1, -1, -1, -1, -1, -1,
708 -1, -1, -1, -1, -1, -1, -1, -1,
709};
710
711static char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = {
712 4, 5, 6, 7, /* ADAT 1 */
713 8, 9, 10, 11, /* ADAT 2 */
714 12, 13, 14, 15, /* ADAT 3 */
715 16, 17, 18, 19, /* ADAT 4 */
716 0, 1, /* AES */
717 2, 3, /* SPDIF */
718 -1, -1, -1, -1,
719 -1, -1, -1, -1, -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};
725
726static char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = {
727 4, 5, /* ADAT 1 */
728 6, 7, /* ADAT 2 */
729 8, 9, /* ADAT 3 */
730 10, 11, /* ADAT 4 */
731 0, 1, /* AES */
732 2, 3, /* SPDIF */
733 -1, -1, -1, -1,
734 -1, -1, -1, -1, -1, -1, -1, -1,
735 -1, -1, -1, -1, -1, -1, -1, -1,
736 -1, -1, -1, -1, -1, -1, -1, -1,
737 -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};
741
742static char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = {
743 0, 1, /* line in */
744 8, 9, /* aes in, */
745 10, 11, /* spdif in */
746 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT in */
747 -1, -1,
748 -1, -1, -1, -1, -1, -1, -1, -1,
749 -1, -1, -1, -1, -1, -1, -1, -1,
750 -1, -1, -1, -1, -1, -1, -1, -1,
751 -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};
755
756static char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = {
757 0, 1, /* line out */
758 8, 9, /* aes out */
759 10, 11, /* spdif out */
760 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT out */
761 6, 7, /* phone out */
762 -1, -1, -1, -1, -1, -1, -1, -1,
763 -1, -1, -1, -1, -1, -1, -1, -1,
764 -1, -1, -1, -1, -1, -1, -1, -1,
765 -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};
769
770static char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = {
771 0, 1, /* line in */
772 8, 9, /* aes in */
773 10, 11, /* spdif in */
774 12, 14, 16, 18, /* adat in */
775 -1, -1, -1, -1, -1, -1,
776 -1, -1, -1, -1, -1, -1, -1, -1,
777 -1, -1, -1, -1, -1, -1, -1, -1,
778 -1, -1, -1, -1, -1, -1, -1, -1,
779 -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};
783
784static char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = {
785 0, 1, /* line out */
786 8, 9, /* aes out */
787 10, 11, /* spdif out */
788 12, 14, 16, 18, /* adat out */
789 6, 7, /* phone out */
790 -1, -1, -1, -1,
791 -1, -1, -1, -1, -1, -1, -1, -1,
792 -1, -1, -1, -1, -1, -1, -1, -1,
793 -1, -1, -1, -1, -1, -1, -1, -1,
794 -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};
798
799static char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = {
800 0, 1, /* line in */
801 8, 9, /* aes in */
802 10, 11, /* spdif in */
803 12, 16, /* adat in */
804 -1, -1, -1, -1, -1, -1, -1, -1,
805 -1, -1, -1, -1, -1, -1, -1, -1,
806 -1, -1, -1, -1, -1, -1, -1, -1,
807 -1, -1, -1, -1, -1, -1, -1, -1,
808 -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};
812
813static char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = {
814 0, 1, /* line out */
815 8, 9, /* aes out */
816 10, 11, /* spdif out */
817 12, 16, /* adat out */
818 6, 7, /* phone out */
819 -1, -1, -1, -1, -1, -1,
820 -1, -1, -1, -1, -1, -1, -1, -1,
821 -1, -1, -1, -1, -1, -1, -1, -1,
822 -1, -1, -1, -1, -1, -1, -1, -1,
823 -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};
827
Adrian Knoth432d2502011-02-23 11:43:08 +0100828static char channel_map_aes32[HDSPM_MAX_CHANNELS] = {
829 0, 1, 2, 3, 4, 5, 6, 7,
830 8, 9, 10, 11, 12, 13, 14, 15,
831 -1, -1, -1, -1, -1, -1, -1, -1,
832 -1, -1, -1, -1, -1, -1, -1, -1,
833 -1, -1, -1, -1, -1, -1, -1, -1,
834 -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};
838
Takashi Iwai98274f02005-11-17 14:52:34 +0100839struct hdspm_midi {
840 struct hdspm *hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +0200841 int id;
Takashi Iwai98274f02005-11-17 14:52:34 +0100842 struct snd_rawmidi *rmidi;
843 struct snd_rawmidi_substream *input;
844 struct snd_rawmidi_substream *output;
Takashi Iwai763f3562005-06-03 11:25:34 +0200845 char istimer; /* timer in use */
846 struct timer_list timer;
847 spinlock_t lock;
848 int pending;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100849 int dataIn;
850 int statusIn;
851 int dataOut;
852 int statusOut;
853 int ie;
854 int irq;
855};
856
857struct hdspm_tco {
858 int input;
859 int framerate;
860 int wordclock;
861 int samplerate;
862 int pull;
863 int term; /* 0 = off, 1 = on */
Takashi Iwai763f3562005-06-03 11:25:34 +0200864};
865
Takashi Iwai98274f02005-11-17 14:52:34 +0100866struct hdspm {
Takashi Iwai763f3562005-06-03 11:25:34 +0200867 spinlock_t lock;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200868 /* only one playback and/or capture stream */
869 struct snd_pcm_substream *capture_substream;
870 struct snd_pcm_substream *playback_substream;
Takashi Iwai763f3562005-06-03 11:25:34 +0200871
872 char *card_name; /* for procinfo */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200873 unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
874
Adrian Knoth0dca1792011-01-26 19:32:14 +0100875 uint8_t io_type;
Takashi Iwai763f3562005-06-03 11:25:34 +0200876
Takashi Iwai763f3562005-06-03 11:25:34 +0200877 int monitor_outs; /* set up monitoring outs init flag */
878
879 u32 control_register; /* cached value */
880 u32 control2_register; /* cached value */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100881 u32 settings_register;
Takashi Iwai763f3562005-06-03 11:25:34 +0200882
Adrian Knoth0dca1792011-01-26 19:32:14 +0100883 struct hdspm_midi midi[4];
Takashi Iwai763f3562005-06-03 11:25:34 +0200884 struct tasklet_struct midi_tasklet;
885
886 size_t period_bytes;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100887 unsigned char ss_in_channels;
888 unsigned char ds_in_channels;
889 unsigned char qs_in_channels;
890 unsigned char ss_out_channels;
891 unsigned char ds_out_channels;
892 unsigned char qs_out_channels;
893
894 unsigned char max_channels_in;
895 unsigned char max_channels_out;
896
897 char *channel_map_in;
898 char *channel_map_out;
899
900 char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs;
901 char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs;
902
903 char **port_names_in;
904 char **port_names_out;
905
906 char **port_names_in_ss, **port_names_in_ds, **port_names_in_qs;
907 char **port_names_out_ss, **port_names_out_ds, **port_names_out_qs;
Takashi Iwai763f3562005-06-03 11:25:34 +0200908
909 unsigned char *playback_buffer; /* suitably aligned address */
910 unsigned char *capture_buffer; /* suitably aligned address */
911
912 pid_t capture_pid; /* process id which uses capture */
913 pid_t playback_pid; /* process id which uses capture */
914 int running; /* running status */
915
916 int last_external_sample_rate; /* samplerate mystic ... */
917 int last_internal_sample_rate;
918 int system_sample_rate;
919
Takashi Iwai763f3562005-06-03 11:25:34 +0200920 int dev; /* Hardware vars... */
921 int irq;
922 unsigned long port;
923 void __iomem *iobase;
924
925 int irq_count; /* for debug */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100926 int midiPorts;
Takashi Iwai763f3562005-06-03 11:25:34 +0200927
Takashi Iwai98274f02005-11-17 14:52:34 +0100928 struct snd_card *card; /* one card */
929 struct snd_pcm *pcm; /* has one pcm */
930 struct snd_hwdep *hwdep; /* and a hwdep for additional ioctl */
Takashi Iwai763f3562005-06-03 11:25:34 +0200931 struct pci_dev *pci; /* and an pci info */
932
933 /* Mixer vars */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200934 /* fast alsa mixer */
935 struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS];
936 /* but input to much, so not used */
937 struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS];
Adrian Knoth0dca1792011-01-26 19:32:14 +0100938 /* full mixer accessable over mixer ioctl or hwdep-device */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200939 struct hdspm_mixer *mixer;
Takashi Iwai763f3562005-06-03 11:25:34 +0200940
Adrian Knoth0dca1792011-01-26 19:32:14 +0100941 struct hdspm_tco *tco; /* NULL if no TCO detected */
Takashi Iwai763f3562005-06-03 11:25:34 +0200942
Adrian Knoth0dca1792011-01-26 19:32:14 +0100943 char **texts_autosync;
944 int texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +0200945
Adrian Knoth0dca1792011-01-26 19:32:14 +0100946 cycles_t last_interrupt;
Jaroslav Kysela730a5862011-01-27 13:03:15 +0100947
948 struct hdspm_peak_rms peak_rms;
Takashi Iwai763f3562005-06-03 11:25:34 +0200949};
950
Takashi Iwai763f3562005-06-03 11:25:34 +0200951
Alexey Dobriyancebe41d2010-02-06 00:21:03 +0200952static DEFINE_PCI_DEVICE_TABLE(snd_hdspm_ids) = {
Takashi Iwai763f3562005-06-03 11:25:34 +0200953 {
954 .vendor = PCI_VENDOR_ID_XILINX,
955 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
956 .subvendor = PCI_ANY_ID,
957 .subdevice = PCI_ANY_ID,
958 .class = 0,
959 .class_mask = 0,
960 .driver_data = 0},
961 {0,}
962};
963
964MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
965
966/* prototypes */
Takashi Iwai98274f02005-11-17 14:52:34 +0100967static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
968 struct hdspm * hdspm);
969static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
970 struct hdspm * hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +0200971
Adrian Knoth0dca1792011-01-26 19:32:14 +0100972static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
973static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
974static int hdspm_autosync_ref(struct hdspm *hdspm);
975static int snd_hdspm_set_defaults(struct hdspm *hdspm);
976static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +0200977 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +0200978 unsigned int reg, int channels);
979
Remy Bruno3cee5a62006-10-16 12:46:32 +0200980static inline int HDSPM_bit2freq(int n)
981{
Denys Vlasenko62cef822008-04-14 13:04:18 +0200982 static const int bit2freq_tab[] = {
983 0, 32000, 44100, 48000, 64000, 88200,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200984 96000, 128000, 176400, 192000 };
985 if (n < 1 || n > 9)
986 return 0;
987 return bit2freq_tab[n];
988}
989
Adrian Knoth0dca1792011-01-26 19:32:14 +0100990/* Write/read to/from HDSPM with Adresses in Bytes
Takashi Iwai763f3562005-06-03 11:25:34 +0200991 not words but only 32Bit writes are allowed */
992
Takashi Iwai98274f02005-11-17 14:52:34 +0100993static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
Takashi Iwai763f3562005-06-03 11:25:34 +0200994 unsigned int val)
995{
996 writel(val, hdspm->iobase + reg);
997}
998
Takashi Iwai98274f02005-11-17 14:52:34 +0100999static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
Takashi Iwai763f3562005-06-03 11:25:34 +02001000{
1001 return readl(hdspm->iobase + reg);
1002}
1003
Adrian Knoth0dca1792011-01-26 19:32:14 +01001004/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
1005 mixer is write only on hardware so we have to cache him for read
Takashi Iwai763f3562005-06-03 11:25:34 +02001006 each fader is a u32, but uses only the first 16 bit */
1007
Takashi Iwai98274f02005-11-17 14:52:34 +01001008static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001009 unsigned int in)
1010{
Adrian Bunk5bab2482006-03-13 14:15:04 +01001011 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001012 return 0;
1013
1014 return hdspm->mixer->ch[chan].in[in];
1015}
1016
Takashi Iwai98274f02005-11-17 14:52:34 +01001017static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001018 unsigned int pb)
1019{
Adrian Bunk5bab2482006-03-13 14:15:04 +01001020 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001021 return 0;
1022 return hdspm->mixer->ch[chan].pb[pb];
1023}
1024
Denys Vlasenko62cef822008-04-14 13:04:18 +02001025static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001026 unsigned int in, unsigned short data)
1027{
1028 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
1029 return -1;
1030
1031 hdspm_write(hdspm,
1032 HDSPM_MADI_mixerBase +
1033 ((in + 128 * chan) * sizeof(u32)),
1034 (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
1035 return 0;
1036}
1037
Denys Vlasenko62cef822008-04-14 13:04:18 +02001038static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001039 unsigned int pb, unsigned short data)
1040{
1041 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
1042 return -1;
1043
1044 hdspm_write(hdspm,
1045 HDSPM_MADI_mixerBase +
1046 ((64 + pb + 128 * chan) * sizeof(u32)),
1047 (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
1048 return 0;
1049}
1050
1051
1052/* enable DMA for specific channels, now available for DSP-MADI */
Takashi Iwai98274f02005-11-17 14:52:34 +01001053static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001054{
1055 hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
1056}
1057
Takashi Iwai98274f02005-11-17 14:52:34 +01001058static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001059{
1060 hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
1061}
1062
1063/* check if same process is writing and reading */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001064static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001065{
1066 unsigned long flags;
1067 int ret = 1;
1068
1069 spin_lock_irqsave(&hdspm->lock, flags);
1070 if ((hdspm->playback_pid != hdspm->capture_pid) &&
1071 (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
1072 ret = 0;
1073 }
1074 spin_unlock_irqrestore(&hdspm->lock, flags);
1075 return ret;
1076}
1077
1078/* check for external sample rate */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001079static int hdspm_external_sample_rate(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001080{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001081 unsigned int status, status2, timecode;
1082 int syncref, rate = 0, rate_bits;
Takashi Iwai763f3562005-06-03 11:25:34 +02001083
Adrian Knoth0dca1792011-01-26 19:32:14 +01001084 switch (hdspm->io_type) {
1085 case AES32:
1086 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1087 status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01001088 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001089
1090 syncref = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001091
Remy Bruno3cee5a62006-10-16 12:46:32 +02001092 if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD &&
1093 status & HDSPM_AES32_wcLock)
Adrian Knoth0dca1792011-01-26 19:32:14 +01001094 return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF);
1095
Remy Bruno3cee5a62006-10-16 12:46:32 +02001096 if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001097 syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
1098 status2 & (HDSPM_LockAES >>
1099 (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1)))
1100 return HDSPM_bit2freq((timecode >> (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF);
Remy Bruno3cee5a62006-10-16 12:46:32 +02001101 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001102 break;
1103
1104 case MADIface:
1105 status = hdspm_read(hdspm, HDSPM_statusRegister);
1106
1107 if (!(status & HDSPM_madiLock)) {
1108 rate = 0; /* no lock */
1109 } else {
1110 switch (status & (HDSPM_status1_freqMask)) {
1111 case HDSPM_status1_F_0*1:
1112 rate = 32000; break;
1113 case HDSPM_status1_F_0*2:
1114 rate = 44100; break;
1115 case HDSPM_status1_F_0*3:
1116 rate = 48000; break;
1117 case HDSPM_status1_F_0*4:
1118 rate = 64000; break;
1119 case HDSPM_status1_F_0*5:
1120 rate = 88200; break;
1121 case HDSPM_status1_F_0*6:
1122 rate = 96000; break;
1123 case HDSPM_status1_F_0*7:
1124 rate = 128000; break;
1125 case HDSPM_status1_F_0*8:
1126 rate = 176400; break;
1127 case HDSPM_status1_F_0*9:
1128 rate = 192000; break;
1129 default:
1130 rate = 0; break;
1131 }
1132 }
1133
1134 break;
1135
1136 case MADI:
1137 case AIO:
1138 case RayDAT:
1139 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1140 status = hdspm_read(hdspm, HDSPM_statusRegister);
1141 rate = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02001142
Remy Bruno3cee5a62006-10-16 12:46:32 +02001143 /* if wordclock has synced freq and wordclock is valid */
1144 if ((status2 & HDSPM_wcLock) != 0 &&
1145 (status & HDSPM_SelSyncRef0) == 0) {
1146
1147 rate_bits = status2 & HDSPM_wcFreqMask;
1148
Adrian Knoth0dca1792011-01-26 19:32:14 +01001149
Remy Bruno3cee5a62006-10-16 12:46:32 +02001150 switch (rate_bits) {
1151 case HDSPM_wcFreq32:
1152 rate = 32000;
1153 break;
1154 case HDSPM_wcFreq44_1:
1155 rate = 44100;
1156 break;
1157 case HDSPM_wcFreq48:
1158 rate = 48000;
1159 break;
1160 case HDSPM_wcFreq64:
1161 rate = 64000;
1162 break;
1163 case HDSPM_wcFreq88_2:
1164 rate = 88200;
1165 break;
1166 case HDSPM_wcFreq96:
1167 rate = 96000;
1168 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001169 default:
1170 rate = 0;
1171 break;
1172 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001173 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001174
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001175 /* if rate detected and Syncref is Word than have it,
1176 * word has priority to MADI
1177 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001178 if (rate != 0 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001179 (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
Remy Bruno3cee5a62006-10-16 12:46:32 +02001180 return rate;
1181
Adrian Knoth0dca1792011-01-26 19:32:14 +01001182 /* maybe a madi input (which is taken if sel sync is madi) */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001183 if (status & HDSPM_madiLock) {
1184 rate_bits = status & HDSPM_madiFreqMask;
1185
1186 switch (rate_bits) {
1187 case HDSPM_madiFreq32:
1188 rate = 32000;
1189 break;
1190 case HDSPM_madiFreq44_1:
1191 rate = 44100;
1192 break;
1193 case HDSPM_madiFreq48:
1194 rate = 48000;
1195 break;
1196 case HDSPM_madiFreq64:
1197 rate = 64000;
1198 break;
1199 case HDSPM_madiFreq88_2:
1200 rate = 88200;
1201 break;
1202 case HDSPM_madiFreq96:
1203 rate = 96000;
1204 break;
1205 case HDSPM_madiFreq128:
1206 rate = 128000;
1207 break;
1208 case HDSPM_madiFreq176_4:
1209 rate = 176400;
1210 break;
1211 case HDSPM_madiFreq192:
1212 rate = 192000;
1213 break;
1214 default:
1215 rate = 0;
1216 break;
1217 }
1218 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001219 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001220 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001221
1222 return rate;
Takashi Iwai763f3562005-06-03 11:25:34 +02001223}
1224
1225/* Latency function */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001226static inline void hdspm_compute_period_size(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001227{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001228 hdspm->period_bytes = 1 << ((hdspm_decode_latency(hdspm->control_register) + 8));
Takashi Iwai763f3562005-06-03 11:25:34 +02001229}
1230
Adrian Knoth0dca1792011-01-26 19:32:14 +01001231
1232static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001233{
1234 int position;
1235
1236 position = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth483cee72011-02-23 11:43:09 +01001237
1238 switch (hdspm->io_type) {
1239 case RayDAT:
1240 case AIO:
1241 position &= HDSPM_BufferPositionMask;
1242 position /= 4; /* Bytes per sample */
1243 break;
1244 default:
1245 position = (position & HDSPM_BufferID) ?
1246 (hdspm->period_bytes / 4) : 0;
1247 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001248
1249 return position;
1250}
1251
1252
Takashi Iwai98274f02005-11-17 14:52:34 +01001253static inline void hdspm_start_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001254{
1255 s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
1256 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1257}
1258
Takashi Iwai98274f02005-11-17 14:52:34 +01001259static inline void hdspm_stop_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001260{
1261 s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
1262 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1263}
1264
1265/* should I silence all or only opened ones ? doit all for first even is 4MB*/
Denys Vlasenko62cef822008-04-14 13:04:18 +02001266static void hdspm_silence_playback(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001267{
1268 int i;
1269 int n = hdspm->period_bytes;
1270 void *buf = hdspm->playback_buffer;
1271
Remy Bruno3cee5a62006-10-16 12:46:32 +02001272 if (buf == NULL)
1273 return;
Takashi Iwai763f3562005-06-03 11:25:34 +02001274
1275 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
1276 memset(buf, 0, n);
1277 buf += HDSPM_CHANNEL_BUFFER_BYTES;
1278 }
1279}
1280
Adrian Knoth0dca1792011-01-26 19:32:14 +01001281static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames)
Takashi Iwai763f3562005-06-03 11:25:34 +02001282{
1283 int n;
1284
1285 spin_lock_irq(&s->lock);
1286
1287 frames >>= 7;
1288 n = 0;
1289 while (frames) {
1290 n++;
1291 frames >>= 1;
1292 }
1293 s->control_register &= ~HDSPM_LatencyMask;
1294 s->control_register |= hdspm_encode_latency(n);
1295
1296 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1297
1298 hdspm_compute_period_size(s);
1299
1300 spin_unlock_irq(&s->lock);
1301
1302 return 0;
1303}
1304
Adrian Knoth0dca1792011-01-26 19:32:14 +01001305static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period)
1306{
1307 u64 freq_const;
1308
1309 if (period == 0)
1310 return 0;
1311
1312 switch (hdspm->io_type) {
1313 case MADI:
1314 case AES32:
1315 freq_const = 110069313433624ULL;
1316 break;
1317 case RayDAT:
1318 case AIO:
1319 freq_const = 104857600000000ULL;
1320 break;
1321 case MADIface:
1322 freq_const = 131072000000000ULL;
1323 }
1324
1325 return div_u64(freq_const, period);
1326}
1327
1328
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001329static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
1330{
1331 u64 n;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001332
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001333 if (rate >= 112000)
1334 rate /= 4;
1335 else if (rate >= 56000)
1336 rate /= 2;
1337
Adrian Knoth0dca1792011-01-26 19:32:14 +01001338 switch (hdspm->io_type) {
1339 case MADIface:
1340 n = 131072000000000ULL; /* 125 MHz */
1341 break;
1342 case MADI:
1343 case AES32:
1344 n = 110069313433624ULL; /* 105 MHz */
1345 break;
1346 case RayDAT:
1347 case AIO:
1348 n = 104857600000000ULL; /* 100 MHz */
1349 break;
1350 }
1351
Takashi Iwai3f7440a2009-06-05 17:40:04 +02001352 n = div_u64(n, rate);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001353 /* n should be less than 2^32 for being written to FREQ register */
Takashi Iwaida3cec32008-08-08 17:12:14 +02001354 snd_BUG_ON(n >> 32);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001355 hdspm_write(hdspm, HDSPM_freqReg, (u32)n);
1356}
Takashi Iwai763f3562005-06-03 11:25:34 +02001357
1358/* dummy set rate lets see what happens */
Takashi Iwai98274f02005-11-17 14:52:34 +01001359static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
Takashi Iwai763f3562005-06-03 11:25:34 +02001360{
Takashi Iwai763f3562005-06-03 11:25:34 +02001361 int current_rate;
1362 int rate_bits;
1363 int not_set = 0;
Remy Bruno65345992007-08-31 12:21:08 +02001364 int current_speed, target_speed;
Takashi Iwai763f3562005-06-03 11:25:34 +02001365
1366 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
1367 it (e.g. during module initialization).
1368 */
1369
1370 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
1371
Adrian Knoth0dca1792011-01-26 19:32:14 +01001372 /* SLAVE --- */
Takashi Iwai763f3562005-06-03 11:25:34 +02001373 if (called_internally) {
1374
Adrian Knoth0dca1792011-01-26 19:32:14 +01001375 /* request from ctl or card initialization
1376 just make a warning an remember setting
1377 for future master mode switching */
1378
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001379 snd_printk(KERN_WARNING "HDSPM: "
1380 "Warning: device is not running "
1381 "as a clock master.\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001382 not_set = 1;
1383 } else {
1384
1385 /* hw_param request while in AutoSync mode */
1386 int external_freq =
1387 hdspm_external_sample_rate(hdspm);
1388
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001389 if (hdspm_autosync_ref(hdspm) ==
1390 HDSPM_AUTOSYNC_FROM_NONE) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001391
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001392 snd_printk(KERN_WARNING "HDSPM: "
1393 "Detected no Externel Sync \n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001394 not_set = 1;
1395
1396 } else if (rate != external_freq) {
1397
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001398 snd_printk(KERN_WARNING "HDSPM: "
1399 "Warning: No AutoSync source for "
1400 "requested rate\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001401 not_set = 1;
1402 }
1403 }
1404 }
1405
1406 current_rate = hdspm->system_sample_rate;
1407
1408 /* Changing between Singe, Double and Quad speed is not
1409 allowed if any substreams are open. This is because such a change
1410 causes a shift in the location of the DMA buffers and a reduction
1411 in the number of available buffers.
1412
1413 Note that a similar but essentially insoluble problem exists for
1414 externally-driven rate changes. All we can do is to flag rate
Adrian Knoth0dca1792011-01-26 19:32:14 +01001415 changes in the read/write routines.
Takashi Iwai763f3562005-06-03 11:25:34 +02001416 */
1417
Remy Bruno65345992007-08-31 12:21:08 +02001418 if (current_rate <= 48000)
1419 current_speed = HDSPM_SPEED_SINGLE;
1420 else if (current_rate <= 96000)
1421 current_speed = HDSPM_SPEED_DOUBLE;
1422 else
1423 current_speed = HDSPM_SPEED_QUAD;
1424
1425 if (rate <= 48000)
1426 target_speed = HDSPM_SPEED_SINGLE;
1427 else if (rate <= 96000)
1428 target_speed = HDSPM_SPEED_DOUBLE;
1429 else
1430 target_speed = HDSPM_SPEED_QUAD;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001431
Takashi Iwai763f3562005-06-03 11:25:34 +02001432 switch (rate) {
1433 case 32000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001434 rate_bits = HDSPM_Frequency32KHz;
1435 break;
1436 case 44100:
Takashi Iwai763f3562005-06-03 11:25:34 +02001437 rate_bits = HDSPM_Frequency44_1KHz;
1438 break;
1439 case 48000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001440 rate_bits = HDSPM_Frequency48KHz;
1441 break;
1442 case 64000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001443 rate_bits = HDSPM_Frequency64KHz;
1444 break;
1445 case 88200:
Takashi Iwai763f3562005-06-03 11:25:34 +02001446 rate_bits = HDSPM_Frequency88_2KHz;
1447 break;
1448 case 96000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001449 rate_bits = HDSPM_Frequency96KHz;
1450 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001451 case 128000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001452 rate_bits = HDSPM_Frequency128KHz;
1453 break;
1454 case 176400:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001455 rate_bits = HDSPM_Frequency176_4KHz;
1456 break;
1457 case 192000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001458 rate_bits = HDSPM_Frequency192KHz;
1459 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001460 default:
1461 return -EINVAL;
1462 }
1463
Remy Bruno65345992007-08-31 12:21:08 +02001464 if (current_speed != target_speed
Takashi Iwai763f3562005-06-03 11:25:34 +02001465 && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
1466 snd_printk
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001467 (KERN_ERR "HDSPM: "
Remy Bruno65345992007-08-31 12:21:08 +02001468 "cannot change from %s speed to %s speed mode "
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001469 "(capture PID = %d, playback PID = %d)\n",
Remy Bruno65345992007-08-31 12:21:08 +02001470 hdspm_speed_names[current_speed],
1471 hdspm_speed_names[target_speed],
Takashi Iwai763f3562005-06-03 11:25:34 +02001472 hdspm->capture_pid, hdspm->playback_pid);
1473 return -EBUSY;
1474 }
1475
1476 hdspm->control_register &= ~HDSPM_FrequencyMask;
1477 hdspm->control_register |= rate_bits;
1478 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1479
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001480 /* For AES32, need to set DDS value in FREQ register
1481 For MADI, also apparently */
1482 hdspm_set_dds_value(hdspm, rate);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001483
1484 if (AES32 == hdspm->io_type && rate != current_rate)
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001485 hdspm_write(hdspm, HDSPM_eeprom_wr, 0);
Takashi Iwai763f3562005-06-03 11:25:34 +02001486
1487 hdspm->system_sample_rate = rate;
1488
Adrian Knoth0dca1792011-01-26 19:32:14 +01001489 if (rate <= 48000) {
1490 hdspm->channel_map_in = hdspm->channel_map_in_ss;
1491 hdspm->channel_map_out = hdspm->channel_map_out_ss;
1492 hdspm->max_channels_in = hdspm->ss_in_channels;
1493 hdspm->max_channels_out = hdspm->ss_out_channels;
1494 hdspm->port_names_in = hdspm->port_names_in_ss;
1495 hdspm->port_names_out = hdspm->port_names_out_ss;
1496 } else if (rate <= 96000) {
1497 hdspm->channel_map_in = hdspm->channel_map_in_ds;
1498 hdspm->channel_map_out = hdspm->channel_map_out_ds;
1499 hdspm->max_channels_in = hdspm->ds_in_channels;
1500 hdspm->max_channels_out = hdspm->ds_out_channels;
1501 hdspm->port_names_in = hdspm->port_names_in_ds;
1502 hdspm->port_names_out = hdspm->port_names_out_ds;
1503 } else {
1504 hdspm->channel_map_in = hdspm->channel_map_in_qs;
1505 hdspm->channel_map_out = hdspm->channel_map_out_qs;
1506 hdspm->max_channels_in = hdspm->qs_in_channels;
1507 hdspm->max_channels_out = hdspm->qs_out_channels;
1508 hdspm->port_names_in = hdspm->port_names_in_qs;
1509 hdspm->port_names_out = hdspm->port_names_out_qs;
1510 }
1511
Takashi Iwai763f3562005-06-03 11:25:34 +02001512 if (not_set != 0)
1513 return -1;
1514
1515 return 0;
1516}
1517
1518/* mainly for init to 0 on load */
Takashi Iwai98274f02005-11-17 14:52:34 +01001519static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
Takashi Iwai763f3562005-06-03 11:25:34 +02001520{
1521 int i, j;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001522 unsigned int gain;
1523
1524 if (sgain > UNITY_GAIN)
1525 gain = UNITY_GAIN;
1526 else if (sgain < 0)
1527 gain = 0;
1528 else
1529 gain = sgain;
Takashi Iwai763f3562005-06-03 11:25:34 +02001530
1531 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
1532 for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
1533 hdspm_write_in_gain(hdspm, i, j, gain);
1534 hdspm_write_pb_gain(hdspm, i, j, gain);
1535 }
1536}
1537
1538/*----------------------------------------------------------------------------
1539 MIDI
1540 ----------------------------------------------------------------------------*/
1541
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001542static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm,
1543 int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001544{
1545 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001546 return hdspm_read(hdspm, hdspm->midi[id].dataIn);
Takashi Iwai763f3562005-06-03 11:25:34 +02001547}
1548
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001549static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
1550 int val)
Takashi Iwai763f3562005-06-03 11:25:34 +02001551{
1552 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001553 return hdspm_write(hdspm, hdspm->midi[id].dataOut, val);
Takashi Iwai763f3562005-06-03 11:25:34 +02001554}
1555
Takashi Iwai98274f02005-11-17 14:52:34 +01001556static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001557{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001558 return hdspm_read(hdspm, hdspm->midi[id].statusIn) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001559}
1560
Takashi Iwai98274f02005-11-17 14:52:34 +01001561static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001562{
1563 int fifo_bytes_used;
1564
Adrian Knoth0dca1792011-01-26 19:32:14 +01001565 fifo_bytes_used = hdspm_read(hdspm, hdspm->midi[id].statusOut) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001566
1567 if (fifo_bytes_used < 128)
1568 return 128 - fifo_bytes_used;
1569 else
1570 return 0;
1571}
1572
Denys Vlasenko62cef822008-04-14 13:04:18 +02001573static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001574{
1575 while (snd_hdspm_midi_input_available (hdspm, id))
1576 snd_hdspm_midi_read_byte (hdspm, id);
1577}
1578
Takashi Iwai98274f02005-11-17 14:52:34 +01001579static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001580{
1581 unsigned long flags;
1582 int n_pending;
1583 int to_write;
1584 int i;
1585 unsigned char buf[128];
1586
1587 /* Output is not interrupt driven */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001588
Takashi Iwai763f3562005-06-03 11:25:34 +02001589 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001590 if (hmidi->output &&
1591 !snd_rawmidi_transmit_empty (hmidi->output)) {
1592 n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm,
1593 hmidi->id);
1594 if (n_pending > 0) {
1595 if (n_pending > (int)sizeof (buf))
1596 n_pending = sizeof (buf);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001597
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001598 to_write = snd_rawmidi_transmit (hmidi->output, buf,
1599 n_pending);
1600 if (to_write > 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001601 for (i = 0; i < to_write; ++i)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001602 snd_hdspm_midi_write_byte (hmidi->hdspm,
1603 hmidi->id,
1604 buf[i]);
Takashi Iwai763f3562005-06-03 11:25:34 +02001605 }
1606 }
1607 }
1608 spin_unlock_irqrestore (&hmidi->lock, flags);
1609 return 0;
1610}
1611
Takashi Iwai98274f02005-11-17 14:52:34 +01001612static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001613{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001614 unsigned char buf[128]; /* this buffer is designed to match the MIDI
1615 * input FIFO size
1616 */
Takashi Iwai763f3562005-06-03 11:25:34 +02001617 unsigned long flags;
1618 int n_pending;
1619 int i;
1620
1621 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001622 n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id);
1623 if (n_pending > 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001624 if (hmidi->input) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001625 if (n_pending > (int)sizeof (buf))
Takashi Iwai763f3562005-06-03 11:25:34 +02001626 n_pending = sizeof (buf);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001627 for (i = 0; i < n_pending; ++i)
1628 buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm,
1629 hmidi->id);
1630 if (n_pending)
1631 snd_rawmidi_receive (hmidi->input, buf,
1632 n_pending);
Takashi Iwai763f3562005-06-03 11:25:34 +02001633 } else {
1634 /* flush the MIDI input FIFO */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001635 while (n_pending--)
1636 snd_hdspm_midi_read_byte (hmidi->hdspm,
1637 hmidi->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02001638 }
1639 }
1640 hmidi->pending = 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001641
1642 hmidi->hdspm->control_register |= hmidi->ie;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001643 hdspm_write(hmidi->hdspm, HDSPM_controlRegister,
1644 hmidi->hdspm->control_register);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001645
Takashi Iwai763f3562005-06-03 11:25:34 +02001646 spin_unlock_irqrestore (&hmidi->lock, flags);
1647 return snd_hdspm_midi_output_write (hmidi);
1648}
1649
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001650static void
1651snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001652{
Takashi Iwai98274f02005-11-17 14:52:34 +01001653 struct hdspm *hdspm;
1654 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001655 unsigned long flags;
Takashi Iwai763f3562005-06-03 11:25:34 +02001656
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001657 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001658 hdspm = hmidi->hdspm;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001659
Takashi Iwai763f3562005-06-03 11:25:34 +02001660 spin_lock_irqsave (&hdspm->lock, flags);
1661 if (up) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001662 if (!(hdspm->control_register & hmidi->ie)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001663 snd_hdspm_flush_midi_input (hdspm, hmidi->id);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001664 hdspm->control_register |= hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001665 }
1666 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001667 hdspm->control_register &= ~hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001668 }
1669
1670 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1671 spin_unlock_irqrestore (&hdspm->lock, flags);
1672}
1673
1674static void snd_hdspm_midi_output_timer(unsigned long data)
1675{
Takashi Iwai98274f02005-11-17 14:52:34 +01001676 struct hdspm_midi *hmidi = (struct hdspm_midi *) data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001677 unsigned long flags;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001678
Takashi Iwai763f3562005-06-03 11:25:34 +02001679 snd_hdspm_midi_output_write(hmidi);
1680 spin_lock_irqsave (&hmidi->lock, flags);
1681
1682 /* this does not bump hmidi->istimer, because the
1683 kernel automatically removed the timer when it
1684 expired, and we are now adding it back, thus
Adrian Knoth0dca1792011-01-26 19:32:14 +01001685 leaving istimer wherever it was set before.
Takashi Iwai763f3562005-06-03 11:25:34 +02001686 */
1687
1688 if (hmidi->istimer) {
1689 hmidi->timer.expires = 1 + jiffies;
1690 add_timer(&hmidi->timer);
1691 }
1692
1693 spin_unlock_irqrestore (&hmidi->lock, flags);
1694}
1695
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001696static void
1697snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001698{
Takashi Iwai98274f02005-11-17 14:52:34 +01001699 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001700 unsigned long flags;
1701
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001702 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001703 spin_lock_irqsave (&hmidi->lock, flags);
1704 if (up) {
1705 if (!hmidi->istimer) {
1706 init_timer(&hmidi->timer);
1707 hmidi->timer.function = snd_hdspm_midi_output_timer;
1708 hmidi->timer.data = (unsigned long) hmidi;
1709 hmidi->timer.expires = 1 + jiffies;
1710 add_timer(&hmidi->timer);
1711 hmidi->istimer++;
1712 }
1713 } else {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001714 if (hmidi->istimer && --hmidi->istimer <= 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02001715 del_timer (&hmidi->timer);
Takashi Iwai763f3562005-06-03 11:25:34 +02001716 }
1717 spin_unlock_irqrestore (&hmidi->lock, flags);
1718 if (up)
1719 snd_hdspm_midi_output_write(hmidi);
1720}
1721
Takashi Iwai98274f02005-11-17 14:52:34 +01001722static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001723{
Takashi Iwai98274f02005-11-17 14:52:34 +01001724 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001725
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001726 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001727 spin_lock_irq (&hmidi->lock);
1728 snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
1729 hmidi->input = substream;
1730 spin_unlock_irq (&hmidi->lock);
1731
1732 return 0;
1733}
1734
Takashi Iwai98274f02005-11-17 14:52:34 +01001735static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001736{
Takashi Iwai98274f02005-11-17 14:52:34 +01001737 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001738
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001739 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001740 spin_lock_irq (&hmidi->lock);
1741 hmidi->output = substream;
1742 spin_unlock_irq (&hmidi->lock);
1743
1744 return 0;
1745}
1746
Takashi Iwai98274f02005-11-17 14:52:34 +01001747static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001748{
Takashi Iwai98274f02005-11-17 14:52:34 +01001749 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001750
1751 snd_hdspm_midi_input_trigger (substream, 0);
1752
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001753 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001754 spin_lock_irq (&hmidi->lock);
1755 hmidi->input = NULL;
1756 spin_unlock_irq (&hmidi->lock);
1757
1758 return 0;
1759}
1760
Takashi Iwai98274f02005-11-17 14:52:34 +01001761static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001762{
Takashi Iwai98274f02005-11-17 14:52:34 +01001763 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001764
1765 snd_hdspm_midi_output_trigger (substream, 0);
1766
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001767 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001768 spin_lock_irq (&hmidi->lock);
1769 hmidi->output = NULL;
1770 spin_unlock_irq (&hmidi->lock);
1771
1772 return 0;
1773}
1774
Takashi Iwai98274f02005-11-17 14:52:34 +01001775static struct snd_rawmidi_ops snd_hdspm_midi_output =
Takashi Iwai763f3562005-06-03 11:25:34 +02001776{
1777 .open = snd_hdspm_midi_output_open,
1778 .close = snd_hdspm_midi_output_close,
1779 .trigger = snd_hdspm_midi_output_trigger,
1780};
1781
Takashi Iwai98274f02005-11-17 14:52:34 +01001782static struct snd_rawmidi_ops snd_hdspm_midi_input =
Takashi Iwai763f3562005-06-03 11:25:34 +02001783{
1784 .open = snd_hdspm_midi_input_open,
1785 .close = snd_hdspm_midi_input_close,
1786 .trigger = snd_hdspm_midi_input_trigger,
1787};
1788
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001789static int __devinit snd_hdspm_create_midi (struct snd_card *card,
1790 struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001791{
1792 int err;
1793 char buf[32];
1794
1795 hdspm->midi[id].id = id;
Takashi Iwai763f3562005-06-03 11:25:34 +02001796 hdspm->midi[id].hdspm = hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +02001797 spin_lock_init (&hdspm->midi[id].lock);
1798
Adrian Knoth0dca1792011-01-26 19:32:14 +01001799 if (0 == id) {
1800 if (MADIface == hdspm->io_type) {
1801 /* MIDI-over-MADI on HDSPe MADIface */
1802 hdspm->midi[0].dataIn = HDSPM_midiDataIn2;
1803 hdspm->midi[0].statusIn = HDSPM_midiStatusIn2;
1804 hdspm->midi[0].dataOut = HDSPM_midiDataOut2;
1805 hdspm->midi[0].statusOut = HDSPM_midiStatusOut2;
1806 hdspm->midi[0].ie = HDSPM_Midi2InterruptEnable;
1807 hdspm->midi[0].irq = HDSPM_midi2IRQPending;
1808 } else {
1809 hdspm->midi[0].dataIn = HDSPM_midiDataIn0;
1810 hdspm->midi[0].statusIn = HDSPM_midiStatusIn0;
1811 hdspm->midi[0].dataOut = HDSPM_midiDataOut0;
1812 hdspm->midi[0].statusOut = HDSPM_midiStatusOut0;
1813 hdspm->midi[0].ie = HDSPM_Midi0InterruptEnable;
1814 hdspm->midi[0].irq = HDSPM_midi0IRQPending;
1815 }
1816 } else if (1 == id) {
1817 hdspm->midi[1].dataIn = HDSPM_midiDataIn1;
1818 hdspm->midi[1].statusIn = HDSPM_midiStatusIn1;
1819 hdspm->midi[1].dataOut = HDSPM_midiDataOut1;
1820 hdspm->midi[1].statusOut = HDSPM_midiStatusOut1;
1821 hdspm->midi[1].ie = HDSPM_Midi1InterruptEnable;
1822 hdspm->midi[1].irq = HDSPM_midi1IRQPending;
1823 } else if ((2 == id) && (MADI == hdspm->io_type)) {
1824 /* MIDI-over-MADI on HDSPe MADI */
1825 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1826 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1827 hdspm->midi[2].dataOut = HDSPM_midiDataOut2;
1828 hdspm->midi[2].statusOut = HDSPM_midiStatusOut2;
1829 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1830 hdspm->midi[2].irq = HDSPM_midi2IRQPending;
1831 } else if (2 == id) {
1832 /* TCO MTC, read only */
1833 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1834 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1835 hdspm->midi[2].dataOut = -1;
1836 hdspm->midi[2].statusOut = -1;
1837 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1838 hdspm->midi[2].irq = HDSPM_midi2IRQPendingAES;
1839 } else if (3 == id) {
1840 /* TCO MTC on HDSPe MADI */
1841 hdspm->midi[3].dataIn = HDSPM_midiDataIn3;
1842 hdspm->midi[3].statusIn = HDSPM_midiStatusIn3;
1843 hdspm->midi[3].dataOut = -1;
1844 hdspm->midi[3].statusOut = -1;
1845 hdspm->midi[3].ie = HDSPM_Midi3InterruptEnable;
1846 hdspm->midi[3].irq = HDSPM_midi3IRQPending;
1847 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001848
Adrian Knoth0dca1792011-01-26 19:32:14 +01001849 if ((id < 2) || ((2 == id) && ((MADI == hdspm->io_type) ||
1850 (MADIface == hdspm->io_type)))) {
1851 if ((id == 0) && (MADIface == hdspm->io_type)) {
1852 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1853 } else if ((id == 2) && (MADI == hdspm->io_type)) {
1854 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1855 } else {
1856 sprintf(buf, "%s MIDI %d", card->shortname, id+1);
1857 }
1858 err = snd_rawmidi_new(card, buf, id, 1, 1,
1859 &hdspm->midi[id].rmidi);
1860 if (err < 0)
1861 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02001862
Adrian Knoth0dca1792011-01-26 19:32:14 +01001863 sprintf(hdspm->midi[id].rmidi->name, "%s MIDI %d",
1864 card->id, id+1);
1865 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
Takashi Iwai763f3562005-06-03 11:25:34 +02001866
Adrian Knoth0dca1792011-01-26 19:32:14 +01001867 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1868 SNDRV_RAWMIDI_STREAM_OUTPUT,
1869 &snd_hdspm_midi_output);
1870 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1871 SNDRV_RAWMIDI_STREAM_INPUT,
1872 &snd_hdspm_midi_input);
1873
1874 hdspm->midi[id].rmidi->info_flags |=
1875 SNDRV_RAWMIDI_INFO_OUTPUT |
1876 SNDRV_RAWMIDI_INFO_INPUT |
1877 SNDRV_RAWMIDI_INFO_DUPLEX;
1878 } else {
1879 /* TCO MTC, read only */
1880 sprintf(buf, "%s MTC %d", card->shortname, id+1);
1881 err = snd_rawmidi_new(card, buf, id, 1, 1,
1882 &hdspm->midi[id].rmidi);
1883 if (err < 0)
1884 return err;
1885
1886 sprintf(hdspm->midi[id].rmidi->name,
1887 "%s MTC %d", card->id, id+1);
1888 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
1889
1890 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1891 SNDRV_RAWMIDI_STREAM_INPUT,
1892 &snd_hdspm_midi_input);
1893
1894 hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
1895 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001896
1897 return 0;
1898}
1899
1900
1901static void hdspm_midi_tasklet(unsigned long arg)
1902{
Takashi Iwai98274f02005-11-17 14:52:34 +01001903 struct hdspm *hdspm = (struct hdspm *)arg;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001904 int i = 0;
1905
1906 while (i < hdspm->midiPorts) {
1907 if (hdspm->midi[i].pending)
1908 snd_hdspm_midi_input_read(&hdspm->midi[i]);
1909
1910 i++;
1911 }
1912}
Takashi Iwai763f3562005-06-03 11:25:34 +02001913
1914
1915/*-----------------------------------------------------------------------------
1916 Status Interface
1917 ----------------------------------------------------------------------------*/
1918
1919/* get the system sample rate which is set */
1920
Adrian Knoth0dca1792011-01-26 19:32:14 +01001921
1922/**
1923 * Calculate the real sample rate from the
1924 * current DDS value.
1925 **/
1926static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
1927{
1928 unsigned int period, rate;
1929
1930 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
1931 rate = hdspm_calc_dds_value(hdspm, period);
1932
1933 return rate;
1934}
1935
1936
Takashi Iwai763f3562005-06-03 11:25:34 +02001937#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001938{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001939 .name = xname, \
1940 .index = xindex, \
1941 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1942 .info = snd_hdspm_info_system_sample_rate, \
1943 .get = snd_hdspm_get_system_sample_rate \
1944}
1945
Takashi Iwai98274f02005-11-17 14:52:34 +01001946static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
1947 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001948{
1949 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1950 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001951 uinfo->value.integer.min = 27000;
1952 uinfo->value.integer.max = 207000;
1953 uinfo->value.integer.step = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02001954 return 0;
1955}
1956
Adrian Knoth0dca1792011-01-26 19:32:14 +01001957
Takashi Iwai98274f02005-11-17 14:52:34 +01001958static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
1959 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02001960 ucontrol)
1961{
Takashi Iwai98274f02005-11-17 14:52:34 +01001962 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001963
Adrian Knoth0dca1792011-01-26 19:32:14 +01001964 ucontrol->value.integer.value[0] = hdspm_get_system_sample_rate(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001965 return 0;
1966}
1967
Adrian Knoth0dca1792011-01-26 19:32:14 +01001968
1969/**
1970 * Returns the WordClock sample rate class for the given card.
1971 **/
1972static int hdspm_get_wc_sample_rate(struct hdspm *hdspm)
1973{
1974 int status;
1975
1976 switch (hdspm->io_type) {
1977 case RayDAT:
1978 case AIO:
1979 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
1980 return (status >> 16) & 0xF;
1981 break;
1982 default:
1983 break;
1984 }
1985
1986
1987 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02001988}
1989
Adrian Knoth0dca1792011-01-26 19:32:14 +01001990
1991/**
1992 * Returns the TCO sample rate class for the given card.
1993 **/
1994static int hdspm_get_tco_sample_rate(struct hdspm *hdspm)
1995{
1996 int status;
1997
1998 if (hdspm->tco) {
1999 switch (hdspm->io_type) {
2000 case RayDAT:
2001 case AIO:
2002 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2003 return (status >> 20) & 0xF;
2004 break;
2005 default:
2006 break;
2007 }
2008 }
2009
2010 return 0;
2011}
2012
2013
2014/**
2015 * Returns the SYNC_IN sample rate class for the given card.
2016 **/
2017static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm)
2018{
2019 int status;
2020
2021 if (hdspm->tco) {
2022 switch (hdspm->io_type) {
2023 case RayDAT:
2024 case AIO:
2025 status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2026 return (status >> 12) & 0xF;
2027 break;
2028 default:
2029 break;
2030 }
2031 }
2032
2033 return 0;
2034}
2035
2036
2037/**
2038 * Returns the sample rate class for input source <idx> for
2039 * 'new style' cards like the AIO and RayDAT.
2040 **/
2041static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
2042{
2043 int status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2044
2045 return (status >> (idx*4)) & 0xF;
2046}
2047
2048
2049
2050#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
2051{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2052 .name = xname, \
2053 .private_value = xindex, \
2054 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2055 .info = snd_hdspm_info_autosync_sample_rate, \
2056 .get = snd_hdspm_get_autosync_sample_rate \
2057}
2058
2059
Takashi Iwai98274f02005-11-17 14:52:34 +01002060static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2061 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002062{
Takashi Iwai763f3562005-06-03 11:25:34 +02002063 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2064 uinfo->count = 1;
2065 uinfo->value.enumerated.items = 10;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002066
Takashi Iwai763f3562005-06-03 11:25:34 +02002067 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
Adrian Knoth0dca1792011-01-26 19:32:14 +01002068 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002069 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002070 texts_freq[uinfo->value.enumerated.item]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002071 return 0;
2072}
2073
Adrian Knoth0dca1792011-01-26 19:32:14 +01002074
Takashi Iwai98274f02005-11-17 14:52:34 +01002075static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2076 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002077 ucontrol)
2078{
Takashi Iwai98274f02005-11-17 14:52:34 +01002079 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002080
Adrian Knoth0dca1792011-01-26 19:32:14 +01002081 switch (hdspm->io_type) {
2082 case RayDAT:
2083 switch (kcontrol->private_value) {
2084 case 0:
2085 ucontrol->value.enumerated.item[0] =
2086 hdspm_get_wc_sample_rate(hdspm);
2087 break;
2088 case 7:
2089 ucontrol->value.enumerated.item[0] =
2090 hdspm_get_tco_sample_rate(hdspm);
2091 break;
2092 case 8:
2093 ucontrol->value.enumerated.item[0] =
2094 hdspm_get_sync_in_sample_rate(hdspm);
2095 break;
2096 default:
2097 ucontrol->value.enumerated.item[0] =
2098 hdspm_get_s1_sample_rate(hdspm,
2099 kcontrol->private_value-1);
2100 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002101
Adrian Knoth0dca1792011-01-26 19:32:14 +01002102 case AIO:
2103 switch (kcontrol->private_value) {
2104 case 0: /* WC */
2105 ucontrol->value.enumerated.item[0] =
2106 hdspm_get_wc_sample_rate(hdspm);
2107 break;
2108 case 4: /* TCO */
2109 ucontrol->value.enumerated.item[0] =
2110 hdspm_get_tco_sample_rate(hdspm);
2111 break;
2112 case 5: /* SYNC_IN */
2113 ucontrol->value.enumerated.item[0] =
2114 hdspm_get_sync_in_sample_rate(hdspm);
2115 break;
2116 default:
2117 ucontrol->value.enumerated.item[0] =
2118 hdspm_get_s1_sample_rate(hdspm,
2119 ucontrol->id.index-1);
2120 }
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002121
2122 case AES32:
2123
2124 switch (kcontrol->private_value) {
2125 case 0: /* WC */
2126 ucontrol->value.enumerated.item[0] =
2127 hdspm_get_wc_sample_rate(hdspm);
2128 break;
2129 case 9: /* TCO */
2130 ucontrol->value.enumerated.item[0] =
2131 hdspm_get_tco_sample_rate(hdspm);
2132 break;
2133 case 10: /* SYNC_IN */
2134 ucontrol->value.enumerated.item[0] =
2135 hdspm_get_sync_in_sample_rate(hdspm);
2136 break;
2137 default: /* AES1 to AES8 */
2138 ucontrol->value.enumerated.item[0] =
2139 hdspm_get_s1_sample_rate(hdspm,
2140 kcontrol->private_value-1);
2141 break;
2142
2143 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002144 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002145 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002146 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002147
Takashi Iwai763f3562005-06-03 11:25:34 +02002148 return 0;
2149}
2150
Adrian Knoth0dca1792011-01-26 19:32:14 +01002151
Takashi Iwai763f3562005-06-03 11:25:34 +02002152#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002153{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2154 .name = xname, \
2155 .index = xindex, \
2156 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2157 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2158 .info = snd_hdspm_info_system_clock_mode, \
2159 .get = snd_hdspm_get_system_clock_mode, \
2160 .put = snd_hdspm_put_system_clock_mode, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002161}
2162
2163
Adrian Knoth0dca1792011-01-26 19:32:14 +01002164/**
2165 * Returns the system clock mode for the given card.
2166 * @returns 0 - master, 1 - slave
2167 **/
2168static int hdspm_system_clock_mode(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002169{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002170 switch (hdspm->io_type) {
2171 case AIO:
2172 case RayDAT:
2173 if (hdspm->settings_register & HDSPM_c0Master)
2174 return 0;
2175 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002176
Adrian Knoth0dca1792011-01-26 19:32:14 +01002177 default:
2178 if (hdspm->control_register & HDSPM_ClockModeMaster)
2179 return 0;
2180 }
2181
Takashi Iwai763f3562005-06-03 11:25:34 +02002182 return 1;
2183}
2184
Adrian Knoth0dca1792011-01-26 19:32:14 +01002185
2186/**
2187 * Sets the system clock mode.
2188 * @param mode 0 - master, 1 - slave
2189 **/
2190static void hdspm_set_system_clock_mode(struct hdspm *hdspm, int mode)
2191{
2192 switch (hdspm->io_type) {
2193 case AIO:
2194 case RayDAT:
2195 if (0 == mode)
2196 hdspm->settings_register |= HDSPM_c0Master;
2197 else
2198 hdspm->settings_register &= ~HDSPM_c0Master;
2199
2200 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2201 break;
2202
2203 default:
2204 if (0 == mode)
2205 hdspm->control_register |= HDSPM_ClockModeMaster;
2206 else
2207 hdspm->control_register &= ~HDSPM_ClockModeMaster;
2208
2209 hdspm_write(hdspm, HDSPM_controlRegister,
2210 hdspm->control_register);
2211 }
2212}
2213
2214
Takashi Iwai98274f02005-11-17 14:52:34 +01002215static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
2216 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002217{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002218 static char *texts[] = { "Master", "AutoSync" };
Takashi Iwai763f3562005-06-03 11:25:34 +02002219
2220 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2221 uinfo->count = 1;
2222 uinfo->value.enumerated.items = 2;
2223 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2224 uinfo->value.enumerated.item =
2225 uinfo->value.enumerated.items - 1;
2226 strcpy(uinfo->value.enumerated.name,
2227 texts[uinfo->value.enumerated.item]);
2228 return 0;
2229}
2230
Takashi Iwai98274f02005-11-17 14:52:34 +01002231static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
2232 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002233{
Takashi Iwai98274f02005-11-17 14:52:34 +01002234 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002235
Adrian Knoth0dca1792011-01-26 19:32:14 +01002236 ucontrol->value.enumerated.item[0] = hdspm_system_clock_mode(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002237 return 0;
2238}
2239
Adrian Knoth0dca1792011-01-26 19:32:14 +01002240static int snd_hdspm_put_system_clock_mode(struct snd_kcontrol *kcontrol,
2241 struct snd_ctl_elem_value *ucontrol)
2242{
2243 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2244 int val;
2245
2246 if (!snd_hdspm_use_is_exclusive(hdspm))
2247 return -EBUSY;
2248
2249 val = ucontrol->value.enumerated.item[0];
2250 if (val < 0)
2251 val = 0;
2252 else if (val > 1)
2253 val = 1;
2254
2255 hdspm_set_system_clock_mode(hdspm, val);
2256
2257 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002258}
2259
Adrian Knoth0dca1792011-01-26 19:32:14 +01002260
2261#define HDSPM_INTERNAL_CLOCK(xname, xindex) \
2262{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2263 .name = xname, \
2264 .index = xindex, \
2265 .info = snd_hdspm_info_clock_source, \
2266 .get = snd_hdspm_get_clock_source, \
2267 .put = snd_hdspm_put_clock_source \
2268}
2269
2270
Takashi Iwai98274f02005-11-17 14:52:34 +01002271static int hdspm_clock_source(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002272{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002273 switch (hdspm->system_sample_rate) {
2274 case 32000: return 0;
2275 case 44100: return 1;
2276 case 48000: return 2;
2277 case 64000: return 3;
2278 case 88200: return 4;
2279 case 96000: return 5;
2280 case 128000: return 6;
2281 case 176400: return 7;
2282 case 192000: return 8;
Takashi Iwai763f3562005-06-03 11:25:34 +02002283 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002284
2285 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002286}
2287
Takashi Iwai98274f02005-11-17 14:52:34 +01002288static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
Takashi Iwai763f3562005-06-03 11:25:34 +02002289{
2290 int rate;
2291 switch (mode) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002292 case 0:
2293 rate = 32000; break;
2294 case 1:
2295 rate = 44100; break;
2296 case 2:
2297 rate = 48000; break;
2298 case 3:
2299 rate = 64000; break;
2300 case 4:
2301 rate = 88200; break;
2302 case 5:
2303 rate = 96000; break;
2304 case 6:
2305 rate = 128000; break;
2306 case 7:
2307 rate = 176400; break;
2308 case 8:
2309 rate = 192000; break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002310 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002311 rate = 48000;
Takashi Iwai763f3562005-06-03 11:25:34 +02002312 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002313 hdspm_set_rate(hdspm, rate, 1);
2314 return 0;
2315}
2316
Takashi Iwai98274f02005-11-17 14:52:34 +01002317static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
2318 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002319{
Takashi Iwai763f3562005-06-03 11:25:34 +02002320 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2321 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002322 uinfo->value.enumerated.items = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002323
2324 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2325 uinfo->value.enumerated.item =
2326 uinfo->value.enumerated.items - 1;
2327
2328 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002329 texts_freq[uinfo->value.enumerated.item+1]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002330
2331 return 0;
2332}
2333
Takashi Iwai98274f02005-11-17 14:52:34 +01002334static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
2335 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002336{
Takashi Iwai98274f02005-11-17 14:52:34 +01002337 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002338
2339 ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
2340 return 0;
2341}
2342
Takashi Iwai98274f02005-11-17 14:52:34 +01002343static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
2344 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002345{
Takashi Iwai98274f02005-11-17 14:52:34 +01002346 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002347 int change;
2348 int val;
2349
2350 if (!snd_hdspm_use_is_exclusive(hdspm))
2351 return -EBUSY;
2352 val = ucontrol->value.enumerated.item[0];
2353 if (val < 0)
2354 val = 0;
Remy Bruno65345992007-08-31 12:21:08 +02002355 if (val > 9)
2356 val = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002357 spin_lock_irq(&hdspm->lock);
2358 if (val != hdspm_clock_source(hdspm))
2359 change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
2360 else
2361 change = 0;
2362 spin_unlock_irq(&hdspm->lock);
2363 return change;
2364}
2365
Adrian Knoth0dca1792011-01-26 19:32:14 +01002366
Takashi Iwai763f3562005-06-03 11:25:34 +02002367#define HDSPM_PREF_SYNC_REF(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002368{.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2369 .name = xname, \
2370 .index = xindex, \
2371 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2372 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2373 .info = snd_hdspm_info_pref_sync_ref, \
2374 .get = snd_hdspm_get_pref_sync_ref, \
2375 .put = snd_hdspm_put_pref_sync_ref \
Takashi Iwai763f3562005-06-03 11:25:34 +02002376}
2377
Adrian Knoth0dca1792011-01-26 19:32:14 +01002378
2379/**
2380 * Returns the current preferred sync reference setting.
2381 * The semantics of the return value are depending on the
2382 * card, please see the comments for clarification.
2383 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002384static int hdspm_pref_sync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002385{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002386 switch (hdspm->io_type) {
2387 case AES32:
Remy Bruno3cee5a62006-10-16 12:46:32 +02002388 switch (hdspm->control_register & HDSPM_SyncRefMask) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002389 case 0: return 0; /* WC */
2390 case HDSPM_SyncRef0: return 1; /* AES 1 */
2391 case HDSPM_SyncRef1: return 2; /* AES 2 */
2392 case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; /* AES 3 */
2393 case HDSPM_SyncRef2: return 4; /* AES 4 */
2394 case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; /* AES 5 */
2395 case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; /* AES 6 */
2396 case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0:
2397 return 7; /* AES 7 */
2398 case HDSPM_SyncRef3: return 8; /* AES 8 */
2399 case HDSPM_SyncRef3+HDSPM_SyncRef0: return 9; /* TCO */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002400 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002401 break;
2402
2403 case MADI:
2404 case MADIface:
2405 if (hdspm->tco) {
2406 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2407 case 0: return 0; /* WC */
2408 case HDSPM_SyncRef0: return 1; /* MADI */
2409 case HDSPM_SyncRef1: return 2; /* TCO */
2410 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2411 return 3; /* SYNC_IN */
2412 }
2413 } else {
2414 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2415 case 0: return 0; /* WC */
2416 case HDSPM_SyncRef0: return 1; /* MADI */
2417 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2418 return 2; /* SYNC_IN */
2419 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02002420 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002421 break;
2422
2423 case RayDAT:
2424 if (hdspm->tco) {
2425 switch ((hdspm->settings_register &
2426 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2427 case 0: return 0; /* WC */
2428 case 3: return 1; /* ADAT 1 */
2429 case 4: return 2; /* ADAT 2 */
2430 case 5: return 3; /* ADAT 3 */
2431 case 6: return 4; /* ADAT 4 */
2432 case 1: return 5; /* AES */
2433 case 2: return 6; /* SPDIF */
2434 case 9: return 7; /* TCO */
2435 case 10: return 8; /* SYNC_IN */
2436 }
2437 } else {
2438 switch ((hdspm->settings_register &
2439 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2440 case 0: return 0; /* WC */
2441 case 3: return 1; /* ADAT 1 */
2442 case 4: return 2; /* ADAT 2 */
2443 case 5: return 3; /* ADAT 3 */
2444 case 6: return 4; /* ADAT 4 */
2445 case 1: return 5; /* AES */
2446 case 2: return 6; /* SPDIF */
2447 case 10: return 7; /* SYNC_IN */
2448 }
2449 }
2450
2451 break;
2452
2453 case AIO:
2454 if (hdspm->tco) {
2455 switch ((hdspm->settings_register &
2456 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2457 case 0: return 0; /* WC */
2458 case 3: return 1; /* ADAT */
2459 case 1: return 2; /* AES */
2460 case 2: return 3; /* SPDIF */
2461 case 9: return 4; /* TCO */
2462 case 10: return 5; /* SYNC_IN */
2463 }
2464 } else {
2465 switch ((hdspm->settings_register &
2466 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2467 case 0: return 0; /* WC */
2468 case 3: return 1; /* ADAT */
2469 case 1: return 2; /* AES */
2470 case 2: return 3; /* SPDIF */
2471 case 10: return 4; /* SYNC_IN */
2472 }
2473 }
2474
2475 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002476 }
2477
Adrian Knoth0dca1792011-01-26 19:32:14 +01002478 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002479}
2480
Adrian Knoth0dca1792011-01-26 19:32:14 +01002481
2482/**
2483 * Set the preferred sync reference to <pref>. The semantics
2484 * of <pref> are depending on the card type, see the comments
2485 * for clarification.
2486 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002487static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
Takashi Iwai763f3562005-06-03 11:25:34 +02002488{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002489 int p = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002490
Adrian Knoth0dca1792011-01-26 19:32:14 +01002491 switch (hdspm->io_type) {
2492 case AES32:
2493 hdspm->control_register &= ~HDSPM_SyncRefMask;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002494 switch (pref) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002495 case 0: /* WC */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002496 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002497 case 1: /* AES 1 */
2498 hdspm->control_register |= HDSPM_SyncRef0;
2499 break;
2500 case 2: /* AES 2 */
2501 hdspm->control_register |= HDSPM_SyncRef1;
2502 break;
2503 case 3: /* AES 3 */
2504 hdspm->control_register |=
2505 HDSPM_SyncRef1+HDSPM_SyncRef0;
2506 break;
2507 case 4: /* AES 4 */
2508 hdspm->control_register |= HDSPM_SyncRef2;
2509 break;
2510 case 5: /* AES 5 */
2511 hdspm->control_register |=
2512 HDSPM_SyncRef2+HDSPM_SyncRef0;
2513 break;
2514 case 6: /* AES 6 */
2515 hdspm->control_register |=
2516 HDSPM_SyncRef2+HDSPM_SyncRef1;
2517 break;
2518 case 7: /* AES 7 */
2519 hdspm->control_register |=
2520 HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
2521 break;
2522 case 8: /* AES 8 */
2523 hdspm->control_register |= HDSPM_SyncRef3;
2524 break;
2525 case 9: /* TCO */
2526 hdspm->control_register |=
2527 HDSPM_SyncRef3+HDSPM_SyncRef0;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002528 break;
2529 default:
2530 return -1;
2531 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002532
2533 break;
2534
2535 case MADI:
2536 case MADIface:
2537 hdspm->control_register &= ~HDSPM_SyncRefMask;
2538 if (hdspm->tco) {
2539 switch (pref) {
2540 case 0: /* WC */
2541 break;
2542 case 1: /* MADI */
2543 hdspm->control_register |= HDSPM_SyncRef0;
2544 break;
2545 case 2: /* TCO */
2546 hdspm->control_register |= HDSPM_SyncRef1;
2547 break;
2548 case 3: /* SYNC_IN */
2549 hdspm->control_register |=
2550 HDSPM_SyncRef0+HDSPM_SyncRef1;
2551 break;
2552 default:
2553 return -1;
2554 }
2555 } else {
2556 switch (pref) {
2557 case 0: /* WC */
2558 break;
2559 case 1: /* MADI */
2560 hdspm->control_register |= HDSPM_SyncRef0;
2561 break;
2562 case 2: /* SYNC_IN */
2563 hdspm->control_register |=
2564 HDSPM_SyncRef0+HDSPM_SyncRef1;
2565 break;
2566 default:
2567 return -1;
2568 }
2569 }
2570
2571 break;
2572
2573 case RayDAT:
2574 if (hdspm->tco) {
2575 switch (pref) {
2576 case 0: p = 0; break; /* WC */
2577 case 1: p = 3; break; /* ADAT 1 */
2578 case 2: p = 4; break; /* ADAT 2 */
2579 case 3: p = 5; break; /* ADAT 3 */
2580 case 4: p = 6; break; /* ADAT 4 */
2581 case 5: p = 1; break; /* AES */
2582 case 6: p = 2; break; /* SPDIF */
2583 case 7: p = 9; break; /* TCO */
2584 case 8: p = 10; break; /* SYNC_IN */
2585 default: return -1;
2586 }
2587 } else {
2588 switch (pref) {
2589 case 0: p = 0; break; /* WC */
2590 case 1: p = 3; break; /* ADAT 1 */
2591 case 2: p = 4; break; /* ADAT 2 */
2592 case 3: p = 5; break; /* ADAT 3 */
2593 case 4: p = 6; break; /* ADAT 4 */
2594 case 5: p = 1; break; /* AES */
2595 case 6: p = 2; break; /* SPDIF */
2596 case 7: p = 10; break; /* SYNC_IN */
2597 default: return -1;
2598 }
2599 }
2600 break;
2601
2602 case AIO:
2603 if (hdspm->tco) {
2604 switch (pref) {
2605 case 0: p = 0; break; /* WC */
2606 case 1: p = 3; break; /* ADAT */
2607 case 2: p = 1; break; /* AES */
2608 case 3: p = 2; break; /* SPDIF */
2609 case 4: p = 9; break; /* TCO */
2610 case 5: p = 10; break; /* SYNC_IN */
2611 default: return -1;
2612 }
2613 } else {
2614 switch (pref) {
2615 case 0: p = 0; break; /* WC */
2616 case 1: p = 3; break; /* ADAT */
2617 case 2: p = 1; break; /* AES */
2618 case 3: p = 2; break; /* SPDIF */
2619 case 4: p = 10; break; /* SYNC_IN */
2620 default: return -1;
2621 }
2622 }
2623 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002624 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002625
2626 switch (hdspm->io_type) {
2627 case RayDAT:
2628 case AIO:
2629 hdspm->settings_register &= ~HDSPM_c0_SyncRefMask;
2630 hdspm->settings_register |= HDSPM_c0_SyncRef0 * p;
2631 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2632 break;
2633
2634 case MADI:
2635 case MADIface:
2636 case AES32:
2637 hdspm_write(hdspm, HDSPM_controlRegister,
2638 hdspm->control_register);
2639 }
2640
Takashi Iwai763f3562005-06-03 11:25:34 +02002641 return 0;
2642}
2643
Adrian Knoth0dca1792011-01-26 19:32:14 +01002644
Takashi Iwai98274f02005-11-17 14:52:34 +01002645static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
2646 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002647{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002648 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002649
Adrian Knoth0dca1792011-01-26 19:32:14 +01002650 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2651 uinfo->count = 1;
2652 uinfo->value.enumerated.items = hdspm->texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +02002653
Adrian Knoth0dca1792011-01-26 19:32:14 +01002654 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2655 uinfo->value.enumerated.item =
2656 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002657
Adrian Knoth0dca1792011-01-26 19:32:14 +01002658 strcpy(uinfo->value.enumerated.name,
2659 hdspm->texts_autosync[uinfo->value.enumerated.item]);
Remy Bruno3cee5a62006-10-16 12:46:32 +02002660
Takashi Iwai763f3562005-06-03 11:25:34 +02002661 return 0;
2662}
2663
Takashi Iwai98274f02005-11-17 14:52:34 +01002664static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
2665 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002666{
Takashi Iwai98274f02005-11-17 14:52:34 +01002667 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002668 int psf = hdspm_pref_sync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002669
Adrian Knoth0dca1792011-01-26 19:32:14 +01002670 if (psf >= 0) {
2671 ucontrol->value.enumerated.item[0] = psf;
2672 return 0;
2673 }
2674
2675 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002676}
2677
Takashi Iwai98274f02005-11-17 14:52:34 +01002678static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
2679 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002680{
Takashi Iwai98274f02005-11-17 14:52:34 +01002681 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002682 int val, change = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002683
2684 if (!snd_hdspm_use_is_exclusive(hdspm))
2685 return -EBUSY;
2686
Adrian Knoth0dca1792011-01-26 19:32:14 +01002687 val = ucontrol->value.enumerated.item[0];
2688
2689 if (val < 0)
2690 val = 0;
2691 else if (val >= hdspm->texts_autosync_items)
2692 val = hdspm->texts_autosync_items-1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002693
2694 spin_lock_irq(&hdspm->lock);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002695 if (val != hdspm_pref_sync_ref(hdspm))
2696 change = (0 == hdspm_set_pref_sync_ref(hdspm, val)) ? 1 : 0;
2697
Takashi Iwai763f3562005-06-03 11:25:34 +02002698 spin_unlock_irq(&hdspm->lock);
2699 return change;
2700}
2701
Adrian Knoth0dca1792011-01-26 19:32:14 +01002702
Takashi Iwai763f3562005-06-03 11:25:34 +02002703#define HDSPM_AUTOSYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002704{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002705 .name = xname, \
2706 .index = xindex, \
2707 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2708 .info = snd_hdspm_info_autosync_ref, \
2709 .get = snd_hdspm_get_autosync_ref, \
2710}
2711
Adrian Knoth0dca1792011-01-26 19:32:14 +01002712static int hdspm_autosync_ref(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002713{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002714 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002715 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002716 unsigned int syncref =
2717 (status >> HDSPM_AES32_syncref_bit) & 0xF;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002718 if (syncref == 0)
2719 return HDSPM_AES32_AUTOSYNC_FROM_WORD;
2720 if (syncref <= 8)
2721 return syncref;
2722 return HDSPM_AES32_AUTOSYNC_FROM_NONE;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002723 } else if (MADI == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002724 /* This looks at the autosync selected sync reference */
2725 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Takashi Iwai763f3562005-06-03 11:25:34 +02002726
Remy Bruno3cee5a62006-10-16 12:46:32 +02002727 switch (status2 & HDSPM_SelSyncRefMask) {
2728 case HDSPM_SelSyncRef_WORD:
2729 return HDSPM_AUTOSYNC_FROM_WORD;
2730 case HDSPM_SelSyncRef_MADI:
2731 return HDSPM_AUTOSYNC_FROM_MADI;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002732 case HDSPM_SelSyncRef_TCO:
2733 return HDSPM_AUTOSYNC_FROM_TCO;
2734 case HDSPM_SelSyncRef_SyncIn:
2735 return HDSPM_AUTOSYNC_FROM_SYNC_IN;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002736 case HDSPM_SelSyncRef_NVALID:
2737 return HDSPM_AUTOSYNC_FROM_NONE;
2738 default:
2739 return 0;
2740 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002741
Takashi Iwai763f3562005-06-03 11:25:34 +02002742 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002743 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002744}
2745
Adrian Knoth0dca1792011-01-26 19:32:14 +01002746
Takashi Iwai98274f02005-11-17 14:52:34 +01002747static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
2748 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002749{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002750 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002751
Adrian Knoth0dca1792011-01-26 19:32:14 +01002752 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002753 static char *texts[] = { "WordClock", "AES1", "AES2", "AES3",
2754 "AES4", "AES5", "AES6", "AES7", "AES8", "None"};
2755
2756 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2757 uinfo->count = 1;
2758 uinfo->value.enumerated.items = 10;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002759 if (uinfo->value.enumerated.item >=
2760 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002761 uinfo->value.enumerated.item =
2762 uinfo->value.enumerated.items - 1;
2763 strcpy(uinfo->value.enumerated.name,
2764 texts[uinfo->value.enumerated.item]);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002765 } else if (MADI == hdspm->io_type) {
2766 static char *texts[] = {"Word Clock", "MADI", "TCO",
2767 "Sync In", "None" };
Remy Bruno3cee5a62006-10-16 12:46:32 +02002768
2769 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2770 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002771 uinfo->value.enumerated.items = 5;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002772 if (uinfo->value.enumerated.item >=
Adrian Knoth0dca1792011-01-26 19:32:14 +01002773 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002774 uinfo->value.enumerated.item =
2775 uinfo->value.enumerated.items - 1;
2776 strcpy(uinfo->value.enumerated.name,
2777 texts[uinfo->value.enumerated.item]);
2778 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002779 return 0;
2780}
2781
Takashi Iwai98274f02005-11-17 14:52:34 +01002782static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
2783 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002784{
Takashi Iwai98274f02005-11-17 14:52:34 +01002785 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002786
Remy Bruno65345992007-08-31 12:21:08 +02002787 ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002788 return 0;
2789}
2790
Adrian Knoth0dca1792011-01-26 19:32:14 +01002791
Takashi Iwai763f3562005-06-03 11:25:34 +02002792#define HDSPM_LINE_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002793{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002794 .name = xname, \
2795 .index = xindex, \
2796 .info = snd_hdspm_info_line_out, \
2797 .get = snd_hdspm_get_line_out, \
2798 .put = snd_hdspm_put_line_out \
2799}
2800
Takashi Iwai98274f02005-11-17 14:52:34 +01002801static int hdspm_line_out(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002802{
2803 return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0;
2804}
2805
2806
Takashi Iwai98274f02005-11-17 14:52:34 +01002807static int hdspm_set_line_output(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002808{
2809 if (out)
2810 hdspm->control_register |= HDSPM_LineOut;
2811 else
2812 hdspm->control_register &= ~HDSPM_LineOut;
2813 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2814
2815 return 0;
2816}
2817
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002818#define snd_hdspm_info_line_out snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002819
Takashi Iwai98274f02005-11-17 14:52:34 +01002820static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol,
2821 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002822{
Takashi Iwai98274f02005-11-17 14:52:34 +01002823 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002824
2825 spin_lock_irq(&hdspm->lock);
2826 ucontrol->value.integer.value[0] = hdspm_line_out(hdspm);
2827 spin_unlock_irq(&hdspm->lock);
2828 return 0;
2829}
2830
Takashi Iwai98274f02005-11-17 14:52:34 +01002831static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
2832 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002833{
Takashi Iwai98274f02005-11-17 14:52:34 +01002834 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002835 int change;
2836 unsigned int val;
2837
2838 if (!snd_hdspm_use_is_exclusive(hdspm))
2839 return -EBUSY;
2840 val = ucontrol->value.integer.value[0] & 1;
2841 spin_lock_irq(&hdspm->lock);
2842 change = (int) val != hdspm_line_out(hdspm);
2843 hdspm_set_line_output(hdspm, val);
2844 spin_unlock_irq(&hdspm->lock);
2845 return change;
2846}
2847
Adrian Knoth0dca1792011-01-26 19:32:14 +01002848
Takashi Iwai763f3562005-06-03 11:25:34 +02002849#define HDSPM_TX_64(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002850{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002851 .name = xname, \
2852 .index = xindex, \
2853 .info = snd_hdspm_info_tx_64, \
2854 .get = snd_hdspm_get_tx_64, \
2855 .put = snd_hdspm_put_tx_64 \
2856}
2857
Takashi Iwai98274f02005-11-17 14:52:34 +01002858static int hdspm_tx_64(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002859{
2860 return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0;
2861}
2862
Takashi Iwai98274f02005-11-17 14:52:34 +01002863static int hdspm_set_tx_64(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002864{
2865 if (out)
2866 hdspm->control_register |= HDSPM_TX_64ch;
2867 else
2868 hdspm->control_register &= ~HDSPM_TX_64ch;
2869 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2870
2871 return 0;
2872}
2873
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002874#define snd_hdspm_info_tx_64 snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002875
Takashi Iwai98274f02005-11-17 14:52:34 +01002876static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol,
2877 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002878{
Takashi Iwai98274f02005-11-17 14:52:34 +01002879 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002880
2881 spin_lock_irq(&hdspm->lock);
2882 ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm);
2883 spin_unlock_irq(&hdspm->lock);
2884 return 0;
2885}
2886
Takashi Iwai98274f02005-11-17 14:52:34 +01002887static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
2888 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002889{
Takashi Iwai98274f02005-11-17 14:52:34 +01002890 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002891 int change;
2892 unsigned int val;
2893
2894 if (!snd_hdspm_use_is_exclusive(hdspm))
2895 return -EBUSY;
2896 val = ucontrol->value.integer.value[0] & 1;
2897 spin_lock_irq(&hdspm->lock);
2898 change = (int) val != hdspm_tx_64(hdspm);
2899 hdspm_set_tx_64(hdspm, val);
2900 spin_unlock_irq(&hdspm->lock);
2901 return change;
2902}
2903
Adrian Knoth0dca1792011-01-26 19:32:14 +01002904
Takashi Iwai763f3562005-06-03 11:25:34 +02002905#define HDSPM_C_TMS(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002906{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002907 .name = xname, \
2908 .index = xindex, \
2909 .info = snd_hdspm_info_c_tms, \
2910 .get = snd_hdspm_get_c_tms, \
2911 .put = snd_hdspm_put_c_tms \
2912}
2913
Takashi Iwai98274f02005-11-17 14:52:34 +01002914static int hdspm_c_tms(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002915{
2916 return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0;
2917}
2918
Takashi Iwai98274f02005-11-17 14:52:34 +01002919static int hdspm_set_c_tms(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002920{
2921 if (out)
2922 hdspm->control_register |= HDSPM_clr_tms;
2923 else
2924 hdspm->control_register &= ~HDSPM_clr_tms;
2925 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2926
2927 return 0;
2928}
2929
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002930#define snd_hdspm_info_c_tms snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002931
Takashi Iwai98274f02005-11-17 14:52:34 +01002932static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol,
2933 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002934{
Takashi Iwai98274f02005-11-17 14:52:34 +01002935 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002936
2937 spin_lock_irq(&hdspm->lock);
2938 ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm);
2939 spin_unlock_irq(&hdspm->lock);
2940 return 0;
2941}
2942
Takashi Iwai98274f02005-11-17 14:52:34 +01002943static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,
2944 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002945{
Takashi Iwai98274f02005-11-17 14:52:34 +01002946 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002947 int change;
2948 unsigned int val;
2949
2950 if (!snd_hdspm_use_is_exclusive(hdspm))
2951 return -EBUSY;
2952 val = ucontrol->value.integer.value[0] & 1;
2953 spin_lock_irq(&hdspm->lock);
2954 change = (int) val != hdspm_c_tms(hdspm);
2955 hdspm_set_c_tms(hdspm, val);
2956 spin_unlock_irq(&hdspm->lock);
2957 return change;
2958}
2959
Adrian Knoth0dca1792011-01-26 19:32:14 +01002960
Takashi Iwai763f3562005-06-03 11:25:34 +02002961#define HDSPM_SAFE_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002962{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002963 .name = xname, \
2964 .index = xindex, \
2965 .info = snd_hdspm_info_safe_mode, \
2966 .get = snd_hdspm_get_safe_mode, \
2967 .put = snd_hdspm_put_safe_mode \
2968}
2969
Takashi Iwai98274f02005-11-17 14:52:34 +01002970static int hdspm_safe_mode(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002971{
2972 return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0;
2973}
2974
Takashi Iwai98274f02005-11-17 14:52:34 +01002975static int hdspm_set_safe_mode(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002976{
2977 if (out)
2978 hdspm->control_register |= HDSPM_AutoInp;
2979 else
2980 hdspm->control_register &= ~HDSPM_AutoInp;
2981 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2982
2983 return 0;
2984}
2985
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002986#define snd_hdspm_info_safe_mode snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002987
Takashi Iwai98274f02005-11-17 14:52:34 +01002988static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol,
2989 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002990{
Takashi Iwai98274f02005-11-17 14:52:34 +01002991 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002992
2993 spin_lock_irq(&hdspm->lock);
2994 ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm);
2995 spin_unlock_irq(&hdspm->lock);
2996 return 0;
2997}
2998
Takashi Iwai98274f02005-11-17 14:52:34 +01002999static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
3000 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003001{
Takashi Iwai98274f02005-11-17 14:52:34 +01003002 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003003 int change;
3004 unsigned int val;
3005
3006 if (!snd_hdspm_use_is_exclusive(hdspm))
3007 return -EBUSY;
3008 val = ucontrol->value.integer.value[0] & 1;
3009 spin_lock_irq(&hdspm->lock);
3010 change = (int) val != hdspm_safe_mode(hdspm);
3011 hdspm_set_safe_mode(hdspm, val);
3012 spin_unlock_irq(&hdspm->lock);
3013 return change;
3014}
3015
Adrian Knoth0dca1792011-01-26 19:32:14 +01003016
Remy Bruno3cee5a62006-10-16 12:46:32 +02003017#define HDSPM_EMPHASIS(xname, xindex) \
3018{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3019 .name = xname, \
3020 .index = xindex, \
3021 .info = snd_hdspm_info_emphasis, \
3022 .get = snd_hdspm_get_emphasis, \
3023 .put = snd_hdspm_put_emphasis \
3024}
3025
3026static int hdspm_emphasis(struct hdspm * hdspm)
3027{
3028 return (hdspm->control_register & HDSPM_Emphasis) ? 1 : 0;
3029}
3030
3031static int hdspm_set_emphasis(struct hdspm * hdspm, int emp)
3032{
3033 if (emp)
3034 hdspm->control_register |= HDSPM_Emphasis;
3035 else
3036 hdspm->control_register &= ~HDSPM_Emphasis;
3037 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3038
3039 return 0;
3040}
3041
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003042#define snd_hdspm_info_emphasis snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02003043
3044static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol,
3045 struct snd_ctl_elem_value *ucontrol)
3046{
3047 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3048
3049 spin_lock_irq(&hdspm->lock);
3050 ucontrol->value.enumerated.item[0] = hdspm_emphasis(hdspm);
3051 spin_unlock_irq(&hdspm->lock);
3052 return 0;
3053}
3054
3055static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
3056 struct snd_ctl_elem_value *ucontrol)
3057{
3058 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3059 int change;
3060 unsigned int val;
3061
3062 if (!snd_hdspm_use_is_exclusive(hdspm))
3063 return -EBUSY;
3064 val = ucontrol->value.integer.value[0] & 1;
3065 spin_lock_irq(&hdspm->lock);
3066 change = (int) val != hdspm_emphasis(hdspm);
3067 hdspm_set_emphasis(hdspm, val);
3068 spin_unlock_irq(&hdspm->lock);
3069 return change;
3070}
3071
Adrian Knoth0dca1792011-01-26 19:32:14 +01003072
Remy Bruno3cee5a62006-10-16 12:46:32 +02003073#define HDSPM_DOLBY(xname, xindex) \
3074{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3075 .name = xname, \
3076 .index = xindex, \
3077 .info = snd_hdspm_info_dolby, \
3078 .get = snd_hdspm_get_dolby, \
3079 .put = snd_hdspm_put_dolby \
3080}
3081
3082static int hdspm_dolby(struct hdspm * hdspm)
3083{
3084 return (hdspm->control_register & HDSPM_Dolby) ? 1 : 0;
3085}
3086
3087static int hdspm_set_dolby(struct hdspm * hdspm, int dol)
3088{
3089 if (dol)
3090 hdspm->control_register |= HDSPM_Dolby;
3091 else
3092 hdspm->control_register &= ~HDSPM_Dolby;
3093 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3094
3095 return 0;
3096}
3097
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003098#define snd_hdspm_info_dolby snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02003099
3100static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol,
3101 struct snd_ctl_elem_value *ucontrol)
3102{
3103 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3104
3105 spin_lock_irq(&hdspm->lock);
3106 ucontrol->value.enumerated.item[0] = hdspm_dolby(hdspm);
3107 spin_unlock_irq(&hdspm->lock);
3108 return 0;
3109}
3110
3111static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
3112 struct snd_ctl_elem_value *ucontrol)
3113{
3114 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3115 int change;
3116 unsigned int val;
3117
3118 if (!snd_hdspm_use_is_exclusive(hdspm))
3119 return -EBUSY;
3120 val = ucontrol->value.integer.value[0] & 1;
3121 spin_lock_irq(&hdspm->lock);
3122 change = (int) val != hdspm_dolby(hdspm);
3123 hdspm_set_dolby(hdspm, val);
3124 spin_unlock_irq(&hdspm->lock);
3125 return change;
3126}
3127
Adrian Knoth0dca1792011-01-26 19:32:14 +01003128
Remy Bruno3cee5a62006-10-16 12:46:32 +02003129#define HDSPM_PROFESSIONAL(xname, xindex) \
3130{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3131 .name = xname, \
3132 .index = xindex, \
3133 .info = snd_hdspm_info_professional, \
3134 .get = snd_hdspm_get_professional, \
3135 .put = snd_hdspm_put_professional \
3136}
3137
3138static int hdspm_professional(struct hdspm * hdspm)
3139{
3140 return (hdspm->control_register & HDSPM_Professional) ? 1 : 0;
3141}
3142
3143static int hdspm_set_professional(struct hdspm * hdspm, int dol)
3144{
3145 if (dol)
3146 hdspm->control_register |= HDSPM_Professional;
3147 else
3148 hdspm->control_register &= ~HDSPM_Professional;
3149 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3150
3151 return 0;
3152}
3153
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003154#define snd_hdspm_info_professional snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02003155
3156static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol,
3157 struct snd_ctl_elem_value *ucontrol)
3158{
3159 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3160
3161 spin_lock_irq(&hdspm->lock);
3162 ucontrol->value.enumerated.item[0] = hdspm_professional(hdspm);
3163 spin_unlock_irq(&hdspm->lock);
3164 return 0;
3165}
3166
3167static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,
3168 struct snd_ctl_elem_value *ucontrol)
3169{
3170 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3171 int change;
3172 unsigned int val;
3173
3174 if (!snd_hdspm_use_is_exclusive(hdspm))
3175 return -EBUSY;
3176 val = ucontrol->value.integer.value[0] & 1;
3177 spin_lock_irq(&hdspm->lock);
3178 change = (int) val != hdspm_professional(hdspm);
3179 hdspm_set_professional(hdspm, val);
3180 spin_unlock_irq(&hdspm->lock);
3181 return change;
3182}
3183
Takashi Iwai763f3562005-06-03 11:25:34 +02003184#define HDSPM_INPUT_SELECT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003185{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003186 .name = xname, \
3187 .index = xindex, \
3188 .info = snd_hdspm_info_input_select, \
3189 .get = snd_hdspm_get_input_select, \
3190 .put = snd_hdspm_put_input_select \
3191}
3192
Takashi Iwai98274f02005-11-17 14:52:34 +01003193static int hdspm_input_select(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003194{
3195 return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
3196}
3197
Takashi Iwai98274f02005-11-17 14:52:34 +01003198static int hdspm_set_input_select(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02003199{
3200 if (out)
3201 hdspm->control_register |= HDSPM_InputSelect0;
3202 else
3203 hdspm->control_register &= ~HDSPM_InputSelect0;
3204 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3205
3206 return 0;
3207}
3208
Takashi Iwai98274f02005-11-17 14:52:34 +01003209static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
3210 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003211{
3212 static char *texts[] = { "optical", "coaxial" };
3213
3214 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3215 uinfo->count = 1;
3216 uinfo->value.enumerated.items = 2;
3217
3218 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3219 uinfo->value.enumerated.item =
3220 uinfo->value.enumerated.items - 1;
3221 strcpy(uinfo->value.enumerated.name,
3222 texts[uinfo->value.enumerated.item]);
3223
3224 return 0;
3225}
3226
Takashi Iwai98274f02005-11-17 14:52:34 +01003227static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
3228 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003229{
Takashi Iwai98274f02005-11-17 14:52:34 +01003230 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003231
3232 spin_lock_irq(&hdspm->lock);
3233 ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
3234 spin_unlock_irq(&hdspm->lock);
3235 return 0;
3236}
3237
Takashi Iwai98274f02005-11-17 14:52:34 +01003238static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
3239 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003240{
Takashi Iwai98274f02005-11-17 14:52:34 +01003241 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003242 int change;
3243 unsigned int val;
3244
3245 if (!snd_hdspm_use_is_exclusive(hdspm))
3246 return -EBUSY;
3247 val = ucontrol->value.integer.value[0] & 1;
3248 spin_lock_irq(&hdspm->lock);
3249 change = (int) val != hdspm_input_select(hdspm);
3250 hdspm_set_input_select(hdspm, val);
3251 spin_unlock_irq(&hdspm->lock);
3252 return change;
3253}
3254
Adrian Knoth0dca1792011-01-26 19:32:14 +01003255
Remy Bruno3cee5a62006-10-16 12:46:32 +02003256#define HDSPM_DS_WIRE(xname, xindex) \
3257{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3258 .name = xname, \
3259 .index = xindex, \
3260 .info = snd_hdspm_info_ds_wire, \
3261 .get = snd_hdspm_get_ds_wire, \
3262 .put = snd_hdspm_put_ds_wire \
3263}
3264
3265static int hdspm_ds_wire(struct hdspm * hdspm)
3266{
3267 return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
3268}
3269
3270static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
3271{
3272 if (ds)
3273 hdspm->control_register |= HDSPM_DS_DoubleWire;
3274 else
3275 hdspm->control_register &= ~HDSPM_DS_DoubleWire;
3276 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3277
3278 return 0;
3279}
3280
3281static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
3282 struct snd_ctl_elem_info *uinfo)
3283{
3284 static char *texts[] = { "Single", "Double" };
3285
3286 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3287 uinfo->count = 1;
3288 uinfo->value.enumerated.items = 2;
3289
3290 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3291 uinfo->value.enumerated.item =
3292 uinfo->value.enumerated.items - 1;
3293 strcpy(uinfo->value.enumerated.name,
3294 texts[uinfo->value.enumerated.item]);
3295
3296 return 0;
3297}
3298
3299static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
3300 struct snd_ctl_elem_value *ucontrol)
3301{
3302 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3303
3304 spin_lock_irq(&hdspm->lock);
3305 ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
3306 spin_unlock_irq(&hdspm->lock);
3307 return 0;
3308}
3309
3310static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
3311 struct snd_ctl_elem_value *ucontrol)
3312{
3313 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3314 int change;
3315 unsigned int val;
3316
3317 if (!snd_hdspm_use_is_exclusive(hdspm))
3318 return -EBUSY;
3319 val = ucontrol->value.integer.value[0] & 1;
3320 spin_lock_irq(&hdspm->lock);
3321 change = (int) val != hdspm_ds_wire(hdspm);
3322 hdspm_set_ds_wire(hdspm, val);
3323 spin_unlock_irq(&hdspm->lock);
3324 return change;
3325}
3326
Adrian Knoth0dca1792011-01-26 19:32:14 +01003327
Remy Bruno3cee5a62006-10-16 12:46:32 +02003328#define HDSPM_QS_WIRE(xname, xindex) \
3329{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3330 .name = xname, \
3331 .index = xindex, \
3332 .info = snd_hdspm_info_qs_wire, \
3333 .get = snd_hdspm_get_qs_wire, \
3334 .put = snd_hdspm_put_qs_wire \
3335}
3336
3337static int hdspm_qs_wire(struct hdspm * hdspm)
3338{
3339 if (hdspm->control_register & HDSPM_QS_DoubleWire)
3340 return 1;
3341 if (hdspm->control_register & HDSPM_QS_QuadWire)
3342 return 2;
3343 return 0;
3344}
3345
3346static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
3347{
3348 hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
3349 switch (mode) {
3350 case 0:
3351 break;
3352 case 1:
3353 hdspm->control_register |= HDSPM_QS_DoubleWire;
3354 break;
3355 case 2:
3356 hdspm->control_register |= HDSPM_QS_QuadWire;
3357 break;
3358 }
3359 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3360
3361 return 0;
3362}
3363
3364static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
3365 struct snd_ctl_elem_info *uinfo)
3366{
3367 static char *texts[] = { "Single", "Double", "Quad" };
3368
3369 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3370 uinfo->count = 1;
3371 uinfo->value.enumerated.items = 3;
3372
3373 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3374 uinfo->value.enumerated.item =
3375 uinfo->value.enumerated.items - 1;
3376 strcpy(uinfo->value.enumerated.name,
3377 texts[uinfo->value.enumerated.item]);
3378
3379 return 0;
3380}
3381
3382static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
3383 struct snd_ctl_elem_value *ucontrol)
3384{
3385 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3386
3387 spin_lock_irq(&hdspm->lock);
3388 ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
3389 spin_unlock_irq(&hdspm->lock);
3390 return 0;
3391}
3392
3393static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
3394 struct snd_ctl_elem_value *ucontrol)
3395{
3396 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3397 int change;
3398 int val;
3399
3400 if (!snd_hdspm_use_is_exclusive(hdspm))
3401 return -EBUSY;
3402 val = ucontrol->value.integer.value[0];
3403 if (val < 0)
3404 val = 0;
3405 if (val > 2)
3406 val = 2;
3407 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003408 change = val != hdspm_qs_wire(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003409 hdspm_set_qs_wire(hdspm, val);
3410 spin_unlock_irq(&hdspm->lock);
3411 return change;
3412}
3413
Takashi Iwai763f3562005-06-03 11:25:34 +02003414
3415#define HDSPM_MIXER(xname, xindex) \
3416{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
3417 .name = xname, \
3418 .index = xindex, \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003419 .device = 0, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003420 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
3421 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3422 .info = snd_hdspm_info_mixer, \
3423 .get = snd_hdspm_get_mixer, \
3424 .put = snd_hdspm_put_mixer \
3425}
3426
Takashi Iwai98274f02005-11-17 14:52:34 +01003427static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
3428 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003429{
3430 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3431 uinfo->count = 3;
3432 uinfo->value.integer.min = 0;
3433 uinfo->value.integer.max = 65535;
3434 uinfo->value.integer.step = 1;
3435 return 0;
3436}
3437
Takashi Iwai98274f02005-11-17 14:52:34 +01003438static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
3439 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003440{
Takashi Iwai98274f02005-11-17 14:52:34 +01003441 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003442 int source;
3443 int destination;
3444
3445 source = ucontrol->value.integer.value[0];
3446 if (source < 0)
3447 source = 0;
3448 else if (source >= 2 * HDSPM_MAX_CHANNELS)
3449 source = 2 * HDSPM_MAX_CHANNELS - 1;
3450
3451 destination = ucontrol->value.integer.value[1];
3452 if (destination < 0)
3453 destination = 0;
3454 else if (destination >= HDSPM_MAX_CHANNELS)
3455 destination = HDSPM_MAX_CHANNELS - 1;
3456
3457 spin_lock_irq(&hdspm->lock);
3458 if (source >= HDSPM_MAX_CHANNELS)
3459 ucontrol->value.integer.value[2] =
3460 hdspm_read_pb_gain(hdspm, destination,
3461 source - HDSPM_MAX_CHANNELS);
3462 else
3463 ucontrol->value.integer.value[2] =
3464 hdspm_read_in_gain(hdspm, destination, source);
3465
3466 spin_unlock_irq(&hdspm->lock);
3467
3468 return 0;
3469}
3470
Takashi Iwai98274f02005-11-17 14:52:34 +01003471static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
3472 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003473{
Takashi Iwai98274f02005-11-17 14:52:34 +01003474 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003475 int change;
3476 int source;
3477 int destination;
3478 int gain;
3479
3480 if (!snd_hdspm_use_is_exclusive(hdspm))
3481 return -EBUSY;
3482
3483 source = ucontrol->value.integer.value[0];
3484 destination = ucontrol->value.integer.value[1];
3485
3486 if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
3487 return -1;
3488 if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
3489 return -1;
3490
3491 gain = ucontrol->value.integer.value[2];
3492
3493 spin_lock_irq(&hdspm->lock);
3494
3495 if (source >= HDSPM_MAX_CHANNELS)
3496 change = gain != hdspm_read_pb_gain(hdspm, destination,
3497 source -
3498 HDSPM_MAX_CHANNELS);
3499 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003500 change = gain != hdspm_read_in_gain(hdspm, destination,
3501 source);
Takashi Iwai763f3562005-06-03 11:25:34 +02003502
3503 if (change) {
3504 if (source >= HDSPM_MAX_CHANNELS)
3505 hdspm_write_pb_gain(hdspm, destination,
3506 source - HDSPM_MAX_CHANNELS,
3507 gain);
3508 else
3509 hdspm_write_in_gain(hdspm, destination, source,
3510 gain);
3511 }
3512 spin_unlock_irq(&hdspm->lock);
3513
3514 return change;
3515}
3516
3517/* The simple mixer control(s) provide gain control for the
3518 basic 1:1 mappings of playback streams to output
Adrian Knoth0dca1792011-01-26 19:32:14 +01003519 streams.
Takashi Iwai763f3562005-06-03 11:25:34 +02003520*/
3521
3522#define HDSPM_PLAYBACK_MIXER \
3523{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3524 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
3525 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3526 .info = snd_hdspm_info_playback_mixer, \
3527 .get = snd_hdspm_get_playback_mixer, \
3528 .put = snd_hdspm_put_playback_mixer \
3529}
3530
Takashi Iwai98274f02005-11-17 14:52:34 +01003531static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
3532 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003533{
3534 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3535 uinfo->count = 1;
3536 uinfo->value.integer.min = 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003537 uinfo->value.integer.max = 64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003538 uinfo->value.integer.step = 1;
3539 return 0;
3540}
3541
Takashi Iwai98274f02005-11-17 14:52:34 +01003542static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
3543 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003544{
Takashi Iwai98274f02005-11-17 14:52:34 +01003545 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003546 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003547
3548 channel = ucontrol->id.index - 1;
3549
Takashi Iwaida3cec32008-08-08 17:12:14 +02003550 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3551 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003552
Takashi Iwai763f3562005-06-03 11:25:34 +02003553 spin_lock_irq(&hdspm->lock);
3554 ucontrol->value.integer.value[0] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003555 (hdspm_read_pb_gain(hdspm, channel, channel)*64)/UNITY_GAIN;
Takashi Iwai763f3562005-06-03 11:25:34 +02003556 spin_unlock_irq(&hdspm->lock);
3557
Takashi Iwai763f3562005-06-03 11:25:34 +02003558 return 0;
3559}
3560
Takashi Iwai98274f02005-11-17 14:52:34 +01003561static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
3562 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003563{
Takashi Iwai98274f02005-11-17 14:52:34 +01003564 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003565 int change;
3566 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003567 int gain;
3568
3569 if (!snd_hdspm_use_is_exclusive(hdspm))
3570 return -EBUSY;
3571
3572 channel = ucontrol->id.index - 1;
3573
Takashi Iwaida3cec32008-08-08 17:12:14 +02003574 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3575 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003576
Adrian Knoth0dca1792011-01-26 19:32:14 +01003577 gain = ucontrol->value.integer.value[0]*UNITY_GAIN/64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003578
3579 spin_lock_irq(&hdspm->lock);
3580 change =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003581 gain != hdspm_read_pb_gain(hdspm, channel,
3582 channel);
Takashi Iwai763f3562005-06-03 11:25:34 +02003583 if (change)
Adrian Knoth0dca1792011-01-26 19:32:14 +01003584 hdspm_write_pb_gain(hdspm, channel, channel,
Takashi Iwai763f3562005-06-03 11:25:34 +02003585 gain);
3586 spin_unlock_irq(&hdspm->lock);
3587 return change;
3588}
3589
Adrian Knoth0dca1792011-01-26 19:32:14 +01003590#define HDSPM_SYNC_CHECK(xname, xindex) \
3591{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3592 .name = xname, \
3593 .private_value = xindex, \
3594 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3595 .info = snd_hdspm_info_sync_check, \
3596 .get = snd_hdspm_get_sync_check \
Takashi Iwai763f3562005-06-03 11:25:34 +02003597}
3598
Adrian Knoth0dca1792011-01-26 19:32:14 +01003599
Takashi Iwai98274f02005-11-17 14:52:34 +01003600static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
3601 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003602{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003603 static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" };
Takashi Iwai763f3562005-06-03 11:25:34 +02003604 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3605 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003606 uinfo->value.enumerated.items = 4;
Takashi Iwai763f3562005-06-03 11:25:34 +02003607 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3608 uinfo->value.enumerated.item =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003609 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02003610 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01003611 texts[uinfo->value.enumerated.item]);
Takashi Iwai763f3562005-06-03 11:25:34 +02003612 return 0;
3613}
3614
Adrian Knoth0dca1792011-01-26 19:32:14 +01003615static int hdspm_wc_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003616{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003617 int status, status2;
3618
3619 switch (hdspm->io_type) {
3620 case AES32:
3621 status = hdspm_read(hdspm, HDSPM_statusRegister);
3622 if (status & HDSPM_wcSync)
Takashi Iwai763f3562005-06-03 11:25:34 +02003623 return 2;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003624 else if (status & HDSPM_wcLock)
3625 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003626 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003627 break;
3628
3629 case MADI:
3630 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003631 if (status2 & HDSPM_wcLock) {
3632 if (status2 & HDSPM_wcSync)
3633 return 2;
3634 else
3635 return 1;
3636 }
3637 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003638 break;
3639
3640 case RayDAT:
3641 case AIO:
3642 status = hdspm_read(hdspm, HDSPM_statusRegister);
3643
3644 if (status & 0x2000000)
3645 return 2;
3646 else if (status & 0x1000000)
3647 return 1;
3648 return 0;
3649
3650 break;
3651
3652 case MADIface:
3653 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02003654 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003655
Takashi Iwai763f3562005-06-03 11:25:34 +02003656
Adrian Knoth0dca1792011-01-26 19:32:14 +01003657 return 3;
Takashi Iwai763f3562005-06-03 11:25:34 +02003658}
3659
3660
Adrian Knoth0dca1792011-01-26 19:32:14 +01003661static int hdspm_madi_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003662{
3663 int status = hdspm_read(hdspm, HDSPM_statusRegister);
3664 if (status & HDSPM_madiLock) {
3665 if (status & HDSPM_madiSync)
3666 return 2;
3667 else
3668 return 1;
3669 }
3670 return 0;
3671}
3672
Adrian Knoth0dca1792011-01-26 19:32:14 +01003673
3674static int hdspm_s1_sync_check(struct hdspm *hdspm, int idx)
3675{
3676 int status, lock, sync;
3677
3678 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3679
3680 lock = (status & (0x1<<idx)) ? 1 : 0;
3681 sync = (status & (0x100<<idx)) ? 1 : 0;
3682
3683 if (lock && sync)
3684 return 2;
3685 else if (lock)
3686 return 1;
3687 return 0;
3688}
3689
3690
3691static int hdspm_sync_in_sync_check(struct hdspm *hdspm)
3692{
3693 int status, lock = 0, sync = 0;
3694
3695 switch (hdspm->io_type) {
3696 case RayDAT:
3697 case AIO:
3698 status = hdspm_read(hdspm, HDSPM_RD_STATUS_3);
3699 lock = (status & 0x400) ? 1 : 0;
3700 sync = (status & 0x800) ? 1 : 0;
3701 break;
3702
3703 case MADI:
3704 case AES32:
3705 status = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knotha7edbd52011-02-23 11:43:15 +01003706 lock = (status & HDSPM_syncInLock) ? 1 : 0;
3707 sync = (status & HDSPM_syncInSync) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003708 break;
3709
3710 case MADIface:
3711 break;
3712 }
3713
3714 if (lock && sync)
3715 return 2;
3716 else if (lock)
3717 return 1;
3718
3719 return 0;
3720}
3721
3722static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx)
3723{
3724 int status2, lock, sync;
3725 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
3726
3727 lock = (status2 & (0x0080 >> idx)) ? 1 : 0;
3728 sync = (status2 & (0x8000 >> idx)) ? 1 : 0;
3729
3730 if (sync)
3731 return 2;
3732 else if (lock)
3733 return 1;
3734 return 0;
3735}
3736
3737
3738static int hdspm_tco_sync_check(struct hdspm *hdspm)
3739{
3740 int status;
3741
3742 if (hdspm->tco) {
3743 switch (hdspm->io_type) {
3744 case MADI:
3745 case AES32:
3746 status = hdspm_read(hdspm, HDSPM_statusRegister);
3747 if (status & HDSPM_tcoLock) {
3748 if (status & HDSPM_tcoSync)
3749 return 2;
3750 else
3751 return 1;
3752 }
3753 return 0;
3754
3755 break;
3756
3757 case RayDAT:
3758 case AIO:
3759 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3760
3761 if (status & 0x8000000)
3762 return 2; /* Sync */
3763 if (status & 0x4000000)
3764 return 1; /* Lock */
3765 return 0; /* No signal */
3766 break;
3767
3768 default:
3769 break;
3770 }
3771 }
3772
3773 return 3; /* N/A */
3774}
3775
3776
3777static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
3778 struct snd_ctl_elem_value *ucontrol)
3779{
3780 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3781 int val = -1;
3782
3783 switch (hdspm->io_type) {
3784 case RayDAT:
3785 switch (kcontrol->private_value) {
3786 case 0: /* WC */
3787 val = hdspm_wc_sync_check(hdspm); break;
3788 case 7: /* TCO */
3789 val = hdspm_tco_sync_check(hdspm); break;
3790 case 8: /* SYNC IN */
3791 val = hdspm_sync_in_sync_check(hdspm); break;
3792 default:
3793 val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
3794 }
3795
3796 case AIO:
3797 switch (kcontrol->private_value) {
3798 case 0: /* WC */
3799 val = hdspm_wc_sync_check(hdspm); break;
3800 case 4: /* TCO */
3801 val = hdspm_tco_sync_check(hdspm); break;
3802 case 5: /* SYNC IN */
3803 val = hdspm_sync_in_sync_check(hdspm); break;
3804 default:
3805 val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
3806 }
3807
3808 case MADI:
3809 switch (kcontrol->private_value) {
3810 case 0: /* WC */
3811 val = hdspm_wc_sync_check(hdspm); break;
3812 case 1: /* MADI */
3813 val = hdspm_madi_sync_check(hdspm); break;
3814 case 2: /* TCO */
3815 val = hdspm_tco_sync_check(hdspm); break;
3816 case 3: /* SYNC_IN */
3817 val = hdspm_sync_in_sync_check(hdspm); break;
3818 }
3819
3820 case MADIface:
3821 val = hdspm_madi_sync_check(hdspm); /* MADI */
3822 break;
3823
3824 case AES32:
3825 switch (kcontrol->private_value) {
3826 case 0: /* WC */
3827 val = hdspm_wc_sync_check(hdspm); break;
3828 case 9: /* TCO */
3829 val = hdspm_tco_sync_check(hdspm); break;
3830 case 10 /* SYNC IN */:
3831 val = hdspm_sync_in_sync_check(hdspm); break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01003832 default: /* AES1 to AES8 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01003833 val = hdspm_aes_sync_check(hdspm,
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01003834 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003835 }
3836
3837 }
3838
3839 if (-1 == val)
3840 val = 3;
3841
3842 ucontrol->value.enumerated.item[0] = val;
3843 return 0;
3844}
3845
3846
3847
3848/**
3849 * TCO controls
3850 **/
3851static void hdspm_tco_write(struct hdspm *hdspm)
3852{
3853 unsigned int tc[4] = { 0, 0, 0, 0};
3854
3855 switch (hdspm->tco->input) {
3856 case 0:
3857 tc[2] |= HDSPM_TCO2_set_input_MSB;
3858 break;
3859 case 1:
3860 tc[2] |= HDSPM_TCO2_set_input_LSB;
3861 break;
3862 default:
3863 break;
3864 }
3865
3866 switch (hdspm->tco->framerate) {
3867 case 1:
3868 tc[1] |= HDSPM_TCO1_LTC_Format_LSB;
3869 break;
3870 case 2:
3871 tc[1] |= HDSPM_TCO1_LTC_Format_MSB;
3872 break;
3873 case 3:
3874 tc[1] |= HDSPM_TCO1_LTC_Format_MSB +
3875 HDSPM_TCO1_set_drop_frame_flag;
3876 break;
3877 case 4:
3878 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
3879 HDSPM_TCO1_LTC_Format_MSB;
3880 break;
3881 case 5:
3882 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
3883 HDSPM_TCO1_LTC_Format_MSB +
3884 HDSPM_TCO1_set_drop_frame_flag;
3885 break;
3886 default:
3887 break;
3888 }
3889
3890 switch (hdspm->tco->wordclock) {
3891 case 1:
3892 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_LSB;
3893 break;
3894 case 2:
3895 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_MSB;
3896 break;
3897 default:
3898 break;
3899 }
3900
3901 switch (hdspm->tco->samplerate) {
3902 case 1:
3903 tc[2] |= HDSPM_TCO2_set_freq;
3904 break;
3905 case 2:
3906 tc[2] |= HDSPM_TCO2_set_freq_from_app;
3907 break;
3908 default:
3909 break;
3910 }
3911
3912 switch (hdspm->tco->pull) {
3913 case 1:
3914 tc[2] |= HDSPM_TCO2_set_pull_up;
3915 break;
3916 case 2:
3917 tc[2] |= HDSPM_TCO2_set_pull_down;
3918 break;
3919 case 3:
3920 tc[2] |= HDSPM_TCO2_set_pull_up + HDSPM_TCO2_set_01_4;
3921 break;
3922 case 4:
3923 tc[2] |= HDSPM_TCO2_set_pull_down + HDSPM_TCO2_set_01_4;
3924 break;
3925 default:
3926 break;
3927 }
3928
3929 if (1 == hdspm->tco->term) {
3930 tc[2] |= HDSPM_TCO2_set_term_75R;
3931 }
3932
3933 hdspm_write(hdspm, HDSPM_WR_TCO, tc[0]);
3934 hdspm_write(hdspm, HDSPM_WR_TCO+4, tc[1]);
3935 hdspm_write(hdspm, HDSPM_WR_TCO+8, tc[2]);
3936 hdspm_write(hdspm, HDSPM_WR_TCO+12, tc[3]);
3937}
3938
3939
3940#define HDSPM_TCO_SAMPLE_RATE(xname, xindex) \
3941{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3942 .name = xname, \
3943 .index = xindex, \
3944 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
3945 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3946 .info = snd_hdspm_info_tco_sample_rate, \
3947 .get = snd_hdspm_get_tco_sample_rate, \
3948 .put = snd_hdspm_put_tco_sample_rate \
3949}
3950
3951static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol,
3952 struct snd_ctl_elem_info *uinfo)
3953{
3954 static char *texts[] = { "44.1 kHz", "48 kHz" };
3955 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3956 uinfo->count = 1;
3957 uinfo->value.enumerated.items = 2;
3958
3959 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3960 uinfo->value.enumerated.item =
3961 uinfo->value.enumerated.items - 1;
3962
3963 strcpy(uinfo->value.enumerated.name,
3964 texts[uinfo->value.enumerated.item]);
3965
3966 return 0;
3967}
3968
3969static int snd_hdspm_get_tco_sample_rate(struct snd_kcontrol *kcontrol,
3970 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003971{
Takashi Iwai98274f02005-11-17 14:52:34 +01003972 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003973
Adrian Knoth0dca1792011-01-26 19:32:14 +01003974 ucontrol->value.enumerated.item[0] = hdspm->tco->samplerate;
3975
Takashi Iwai763f3562005-06-03 11:25:34 +02003976 return 0;
3977}
3978
Adrian Knoth0dca1792011-01-26 19:32:14 +01003979static int snd_hdspm_put_tco_sample_rate(struct snd_kcontrol *kcontrol,
3980 struct snd_ctl_elem_value *ucontrol)
Remy Bruno3cee5a62006-10-16 12:46:32 +02003981{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003982 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3983
3984 if (hdspm->tco->samplerate != ucontrol->value.enumerated.item[0]) {
3985 hdspm->tco->samplerate = ucontrol->value.enumerated.item[0];
3986
3987 hdspm_tco_write(hdspm);
3988
3989 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003990 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01003991
Remy Bruno3cee5a62006-10-16 12:46:32 +02003992 return 0;
3993}
3994
Adrian Knoth0dca1792011-01-26 19:32:14 +01003995
3996#define HDSPM_TCO_PULL(xname, xindex) \
3997{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3998 .name = xname, \
3999 .index = xindex, \
4000 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4001 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4002 .info = snd_hdspm_info_tco_pull, \
4003 .get = snd_hdspm_get_tco_pull, \
4004 .put = snd_hdspm_put_tco_pull \
4005}
4006
4007static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol,
4008 struct snd_ctl_elem_info *uinfo)
4009{
4010 static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" };
4011 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4012 uinfo->count = 1;
4013 uinfo->value.enumerated.items = 5;
4014
4015 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4016 uinfo->value.enumerated.item =
4017 uinfo->value.enumerated.items - 1;
4018
4019 strcpy(uinfo->value.enumerated.name,
4020 texts[uinfo->value.enumerated.item]);
4021
4022 return 0;
4023}
4024
4025static int snd_hdspm_get_tco_pull(struct snd_kcontrol *kcontrol,
4026 struct snd_ctl_elem_value *ucontrol)
4027{
4028 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4029
4030 ucontrol->value.enumerated.item[0] = hdspm->tco->pull;
4031
4032 return 0;
4033}
4034
4035static int snd_hdspm_put_tco_pull(struct snd_kcontrol *kcontrol,
4036 struct snd_ctl_elem_value *ucontrol)
4037{
4038 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4039
4040 if (hdspm->tco->pull != ucontrol->value.enumerated.item[0]) {
4041 hdspm->tco->pull = ucontrol->value.enumerated.item[0];
4042
4043 hdspm_tco_write(hdspm);
4044
4045 return 1;
4046 }
4047
4048 return 0;
4049}
4050
4051#define HDSPM_TCO_WCK_CONVERSION(xname, xindex) \
4052{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4053 .name = xname, \
4054 .index = xindex, \
4055 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4056 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4057 .info = snd_hdspm_info_tco_wck_conversion, \
4058 .get = snd_hdspm_get_tco_wck_conversion, \
4059 .put = snd_hdspm_put_tco_wck_conversion \
4060}
4061
4062static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4063 struct snd_ctl_elem_info *uinfo)
4064{
4065 static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
4066 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4067 uinfo->count = 1;
4068 uinfo->value.enumerated.items = 3;
4069
4070 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4071 uinfo->value.enumerated.item =
4072 uinfo->value.enumerated.items - 1;
4073
4074 strcpy(uinfo->value.enumerated.name,
4075 texts[uinfo->value.enumerated.item]);
4076
4077 return 0;
4078}
4079
4080static int snd_hdspm_get_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4081 struct snd_ctl_elem_value *ucontrol)
4082{
4083 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4084
4085 ucontrol->value.enumerated.item[0] = hdspm->tco->wordclock;
4086
4087 return 0;
4088}
4089
4090static int snd_hdspm_put_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4091 struct snd_ctl_elem_value *ucontrol)
4092{
4093 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4094
4095 if (hdspm->tco->wordclock != ucontrol->value.enumerated.item[0]) {
4096 hdspm->tco->wordclock = ucontrol->value.enumerated.item[0];
4097
4098 hdspm_tco_write(hdspm);
4099
4100 return 1;
4101 }
4102
4103 return 0;
4104}
4105
4106
4107#define HDSPM_TCO_FRAME_RATE(xname, xindex) \
4108{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4109 .name = xname, \
4110 .index = xindex, \
4111 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4112 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4113 .info = snd_hdspm_info_tco_frame_rate, \
4114 .get = snd_hdspm_get_tco_frame_rate, \
4115 .put = snd_hdspm_put_tco_frame_rate \
4116}
4117
4118static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol,
4119 struct snd_ctl_elem_info *uinfo)
4120{
4121 static char *texts[] = { "24 fps", "25 fps", "29.97fps",
4122 "29.97 dfps", "30 fps", "30 dfps" };
4123 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4124 uinfo->count = 1;
4125 uinfo->value.enumerated.items = 6;
4126
4127 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4128 uinfo->value.enumerated.item =
4129 uinfo->value.enumerated.items - 1;
4130
4131 strcpy(uinfo->value.enumerated.name,
4132 texts[uinfo->value.enumerated.item]);
4133
4134 return 0;
4135}
4136
4137static int snd_hdspm_get_tco_frame_rate(struct snd_kcontrol *kcontrol,
Remy Bruno3cee5a62006-10-16 12:46:32 +02004138 struct snd_ctl_elem_value *ucontrol)
4139{
Remy Bruno3cee5a62006-10-16 12:46:32 +02004140 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4141
Adrian Knoth0dca1792011-01-26 19:32:14 +01004142 ucontrol->value.enumerated.item[0] = hdspm->tco->framerate;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004143
Remy Bruno3cee5a62006-10-16 12:46:32 +02004144 return 0;
4145}
Takashi Iwai763f3562005-06-03 11:25:34 +02004146
Adrian Knoth0dca1792011-01-26 19:32:14 +01004147static int snd_hdspm_put_tco_frame_rate(struct snd_kcontrol *kcontrol,
4148 struct snd_ctl_elem_value *ucontrol)
4149{
4150 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4151
4152 if (hdspm->tco->framerate != ucontrol->value.enumerated.item[0]) {
4153 hdspm->tco->framerate = ucontrol->value.enumerated.item[0];
4154
4155 hdspm_tco_write(hdspm);
4156
4157 return 1;
4158 }
4159
4160 return 0;
4161}
4162
4163
4164#define HDSPM_TCO_SYNC_SOURCE(xname, xindex) \
4165{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4166 .name = xname, \
4167 .index = xindex, \
4168 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4169 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4170 .info = snd_hdspm_info_tco_sync_source, \
4171 .get = snd_hdspm_get_tco_sync_source, \
4172 .put = snd_hdspm_put_tco_sync_source \
4173}
4174
4175static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol,
4176 struct snd_ctl_elem_info *uinfo)
4177{
4178 static char *texts[] = { "LTC", "Video", "WCK" };
4179 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4180 uinfo->count = 1;
4181 uinfo->value.enumerated.items = 3;
4182
4183 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4184 uinfo->value.enumerated.item =
4185 uinfo->value.enumerated.items - 1;
4186
4187 strcpy(uinfo->value.enumerated.name,
4188 texts[uinfo->value.enumerated.item]);
4189
4190 return 0;
4191}
4192
4193static int snd_hdspm_get_tco_sync_source(struct snd_kcontrol *kcontrol,
4194 struct snd_ctl_elem_value *ucontrol)
4195{
4196 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4197
4198 ucontrol->value.enumerated.item[0] = hdspm->tco->input;
4199
4200 return 0;
4201}
4202
4203static int snd_hdspm_put_tco_sync_source(struct snd_kcontrol *kcontrol,
4204 struct snd_ctl_elem_value *ucontrol)
4205{
4206 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4207
4208 if (hdspm->tco->input != ucontrol->value.enumerated.item[0]) {
4209 hdspm->tco->input = ucontrol->value.enumerated.item[0];
4210
4211 hdspm_tco_write(hdspm);
4212
4213 return 1;
4214 }
4215
4216 return 0;
4217}
4218
4219
4220#define HDSPM_TCO_WORD_TERM(xname, xindex) \
4221{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4222 .name = xname, \
4223 .index = xindex, \
4224 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4225 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4226 .info = snd_hdspm_info_tco_word_term, \
4227 .get = snd_hdspm_get_tco_word_term, \
4228 .put = snd_hdspm_put_tco_word_term \
4229}
4230
4231static int snd_hdspm_info_tco_word_term(struct snd_kcontrol *kcontrol,
4232 struct snd_ctl_elem_info *uinfo)
4233{
4234 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
4235 uinfo->count = 1;
4236 uinfo->value.integer.min = 0;
4237 uinfo->value.integer.max = 1;
4238
4239 return 0;
4240}
4241
4242
4243static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol,
4244 struct snd_ctl_elem_value *ucontrol)
4245{
4246 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4247
4248 ucontrol->value.enumerated.item[0] = hdspm->tco->term;
4249
4250 return 0;
4251}
4252
4253
4254static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol,
4255 struct snd_ctl_elem_value *ucontrol)
4256{
4257 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4258
4259 if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) {
4260 hdspm->tco->term = ucontrol->value.enumerated.item[0];
4261
4262 hdspm_tco_write(hdspm);
4263
4264 return 1;
4265 }
4266
4267 return 0;
4268}
4269
4270
4271
Takashi Iwai763f3562005-06-03 11:25:34 +02004272
Remy Bruno3cee5a62006-10-16 12:46:32 +02004273static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004274 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004275 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Takashi Iwai763f3562005-06-03 11:25:34 +02004276 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4277 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4278 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4279 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004280 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4281 HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
4282 HDSPM_SYNC_CHECK("TCO SyncCHeck", 2),
4283 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
Takashi Iwai763f3562005-06-03 11:25:34 +02004284 HDSPM_LINE_OUT("Line Out", 0),
4285 HDSPM_TX_64("TX 64 channels mode", 0),
4286 HDSPM_C_TMS("Clear Track Marker", 0),
4287 HDSPM_SAFE_MODE("Safe Mode", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004288 HDSPM_INPUT_SELECT("Input Select", 0)
4289};
4290
4291
4292static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
4293 HDSPM_MIXER("Mixer", 0),
4294 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4295 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4296 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4297 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4298 HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
4299 HDSPM_TX_64("TX 64 channels mode", 0),
4300 HDSPM_C_TMS("Clear Track Marker", 0),
Adrian Knothf6ea8052011-02-23 11:43:12 +01004301 HDSPM_SAFE_MODE("Safe Mode", 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004302};
4303
Adrian Knoth0dca1792011-01-26 19:32:14 +01004304static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004305 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004306 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004307 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4308 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4309 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4310 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004311 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004312 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4313 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4314 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4315 HDSPM_SYNC_CHECK("ADAT SyncCheck", 3),
4316 HDSPM_SYNC_CHECK("TCO SyncCheck", 4),
4317 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 5),
4318 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4319 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4320 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4321 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT Frequency", 3),
4322 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 4),
4323 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5)
4324
4325 /*
4326 HDSPM_INPUT_SELECT("Input Select", 0),
4327 HDSPM_SPDIF_OPTICAL("SPDIF Out Optical", 0),
4328 HDSPM_PROFESSIONAL("SPDIF Out Professional", 0);
4329 HDSPM_SPDIF_IN("SPDIF In", 0);
4330 HDSPM_BREAKOUT_CABLE("Breakout Cable", 0);
4331 HDSPM_INPUT_LEVEL("Input Level", 0);
4332 HDSPM_OUTPUT_LEVEL("Output Level", 0);
4333 HDSPM_PHONES("Phones", 0);
4334 */
4335};
4336
4337static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = {
4338 HDSPM_MIXER("Mixer", 0),
4339 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4340 HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0),
4341 HDSPM_PREF_SYNC_REF("Pref Sync Ref", 0),
4342 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4343 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4344 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4345 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4346 HDSPM_SYNC_CHECK("ADAT1 SyncCheck", 3),
4347 HDSPM_SYNC_CHECK("ADAT2 SyncCheck", 4),
4348 HDSPM_SYNC_CHECK("ADAT3 SyncCheck", 5),
4349 HDSPM_SYNC_CHECK("ADAT4 SyncCheck", 6),
4350 HDSPM_SYNC_CHECK("TCO SyncCheck", 7),
4351 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 8),
4352 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4353 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4354 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4355 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT1 Frequency", 3),
4356 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT2 Frequency", 4),
4357 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT3 Frequency", 5),
4358 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT4 Frequency", 6),
4359 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 7),
4360 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8)
4361};
4362
4363static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
4364 HDSPM_MIXER("Mixer", 0),
4365 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4366 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4367 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4368 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4369 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4370 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4371 HDSPM_SYNC_CHECK("WC Sync Check", 0),
4372 HDSPM_SYNC_CHECK("AES1 Sync Check", 1),
4373 HDSPM_SYNC_CHECK("AES2 Sync Check", 2),
4374 HDSPM_SYNC_CHECK("AES3 Sync Check", 3),
4375 HDSPM_SYNC_CHECK("AES4 Sync Check", 4),
4376 HDSPM_SYNC_CHECK("AES5 Sync Check", 5),
4377 HDSPM_SYNC_CHECK("AES6 Sync Check", 6),
4378 HDSPM_SYNC_CHECK("AES7 Sync Check", 7),
4379 HDSPM_SYNC_CHECK("AES8 Sync Check", 8),
4380 HDSPM_SYNC_CHECK("TCO Sync Check", 9),
4381 HDSPM_SYNC_CHECK("SYNC IN Sync Check", 10),
4382 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4383 HDSPM_AUTOSYNC_SAMPLE_RATE("AES1 Frequency", 1),
4384 HDSPM_AUTOSYNC_SAMPLE_RATE("AES2 Frequency", 2),
4385 HDSPM_AUTOSYNC_SAMPLE_RATE("AES3 Frequency", 3),
4386 HDSPM_AUTOSYNC_SAMPLE_RATE("AES4 Frequency", 4),
4387 HDSPM_AUTOSYNC_SAMPLE_RATE("AES5 Frequency", 5),
4388 HDSPM_AUTOSYNC_SAMPLE_RATE("AES6 Frequency", 6),
4389 HDSPM_AUTOSYNC_SAMPLE_RATE("AES7 Frequency", 7),
4390 HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8),
4391 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9),
4392 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004393 HDSPM_LINE_OUT("Line Out", 0),
4394 HDSPM_EMPHASIS("Emphasis", 0),
4395 HDSPM_DOLBY("Non Audio", 0),
4396 HDSPM_PROFESSIONAL("Professional", 0),
4397 HDSPM_C_TMS("Clear Track Marker", 0),
4398 HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
4399 HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
4400};
4401
Adrian Knoth0dca1792011-01-26 19:32:14 +01004402
4403
4404/* Control elements for the optional TCO module */
4405static struct snd_kcontrol_new snd_hdspm_controls_tco[] = {
4406 HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0),
4407 HDSPM_TCO_PULL("TCO Pull", 0),
4408 HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0),
4409 HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0),
4410 HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0),
4411 HDSPM_TCO_WORD_TERM("TCO Word Term", 0)
4412};
4413
4414
Takashi Iwai98274f02005-11-17 14:52:34 +01004415static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
Takashi Iwai763f3562005-06-03 11:25:34 +02004416
4417
Takashi Iwai98274f02005-11-17 14:52:34 +01004418static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004419{
4420 int i;
4421
Adrian Knoth0dca1792011-01-26 19:32:14 +01004422 for (i = hdspm->ds_out_channels; i < hdspm->ss_out_channels; ++i) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004423 if (hdspm->system_sample_rate > 48000) {
4424 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004425 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
4426 SNDRV_CTL_ELEM_ACCESS_READ |
4427 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004428 } else {
4429 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004430 SNDRV_CTL_ELEM_ACCESS_READWRITE |
4431 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004432 }
4433 snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
Adrian Knoth0dca1792011-01-26 19:32:14 +01004434 SNDRV_CTL_EVENT_MASK_INFO,
4435 &hdspm->playback_mixer_ctls[i]->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02004436 }
4437
4438 return 0;
4439}
4440
4441
Adrian Knoth0dca1792011-01-26 19:32:14 +01004442static int snd_hdspm_create_controls(struct snd_card *card,
4443 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004444{
4445 unsigned int idx, limit;
4446 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01004447 struct snd_kcontrol *kctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004448 struct snd_kcontrol_new *list = NULL;
Takashi Iwai763f3562005-06-03 11:25:34 +02004449
Adrian Knoth0dca1792011-01-26 19:32:14 +01004450 switch (hdspm->io_type) {
4451 case MADI:
4452 list = snd_hdspm_controls_madi;
4453 limit = ARRAY_SIZE(snd_hdspm_controls_madi);
4454 break;
4455 case MADIface:
4456 list = snd_hdspm_controls_madiface;
4457 limit = ARRAY_SIZE(snd_hdspm_controls_madiface);
4458 break;
4459 case AIO:
4460 list = snd_hdspm_controls_aio;
4461 limit = ARRAY_SIZE(snd_hdspm_controls_aio);
4462 break;
4463 case RayDAT:
4464 list = snd_hdspm_controls_raydat;
4465 limit = ARRAY_SIZE(snd_hdspm_controls_raydat);
4466 break;
4467 case AES32:
4468 list = snd_hdspm_controls_aes32;
4469 limit = ARRAY_SIZE(snd_hdspm_controls_aes32);
4470 break;
4471 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004472
Adrian Knoth0dca1792011-01-26 19:32:14 +01004473 if (NULL != list) {
4474 for (idx = 0; idx < limit; idx++) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004475 err = snd_ctl_add(card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004476 snd_ctl_new1(&list[idx], hdspm));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004477 if (err < 0)
4478 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004479 }
4480 }
4481
Takashi Iwai763f3562005-06-03 11:25:34 +02004482
Adrian Knoth0dca1792011-01-26 19:32:14 +01004483 /* create simple 1:1 playback mixer controls */
Takashi Iwai763f3562005-06-03 11:25:34 +02004484 snd_hdspm_playback_mixer.name = "Chn";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004485 if (hdspm->system_sample_rate >= 128000) {
4486 limit = hdspm->qs_out_channels;
4487 } else if (hdspm->system_sample_rate >= 64000) {
4488 limit = hdspm->ds_out_channels;
4489 } else {
4490 limit = hdspm->ss_out_channels;
4491 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004492 for (idx = 0; idx < limit; ++idx) {
4493 snd_hdspm_playback_mixer.index = idx + 1;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004494 kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm);
4495 err = snd_ctl_add(card, kctl);
4496 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004497 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004498 hdspm->playback_mixer_ctls[idx] = kctl;
4499 }
4500
Adrian Knoth0dca1792011-01-26 19:32:14 +01004501
4502 if (hdspm->tco) {
4503 /* add tco control elements */
4504 list = snd_hdspm_controls_tco;
4505 limit = ARRAY_SIZE(snd_hdspm_controls_tco);
4506 for (idx = 0; idx < limit; idx++) {
4507 err = snd_ctl_add(card,
4508 snd_ctl_new1(&list[idx], hdspm));
4509 if (err < 0)
4510 return err;
4511 }
4512 }
4513
Takashi Iwai763f3562005-06-03 11:25:34 +02004514 return 0;
4515}
4516
4517/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01004518 /proc interface
Takashi Iwai763f3562005-06-03 11:25:34 +02004519 ------------------------------------------------------------*/
4520
4521static void
Remy Bruno3cee5a62006-10-16 12:46:32 +02004522snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
4523 struct snd_info_buffer *buffer)
Takashi Iwai763f3562005-06-03 11:25:34 +02004524{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004525 struct hdspm *hdspm = entry->private_data;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004526 unsigned int status, status2, control, freq;
4527
Takashi Iwai763f3562005-06-03 11:25:34 +02004528 char *pref_sync_ref;
4529 char *autosync_ref;
4530 char *system_clock_mode;
Takashi Iwai763f3562005-06-03 11:25:34 +02004531 char *insel;
Takashi Iwai763f3562005-06-03 11:25:34 +02004532 int x, x2;
4533
Adrian Knoth0dca1792011-01-26 19:32:14 +01004534 /* TCO stuff */
4535 int a, ltc, frames, seconds, minutes, hours;
4536 unsigned int period;
4537 u64 freq_const = 0;
4538 u32 rate;
4539
Takashi Iwai763f3562005-06-03 11:25:34 +02004540 status = hdspm_read(hdspm, HDSPM_statusRegister);
4541 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004542 control = hdspm->control_register;
4543 freq = hdspm_read(hdspm, HDSPM_timecodeRegister);
Takashi Iwai763f3562005-06-03 11:25:34 +02004544
4545 snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004546 hdspm->card_name, hdspm->card->number + 1,
4547 hdspm->firmware_rev,
4548 (status2 & HDSPM_version0) |
4549 (status2 & HDSPM_version1) | (status2 &
4550 HDSPM_version2));
4551
4552 snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n",
4553 (hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF,
4554 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF);
Takashi Iwai763f3562005-06-03 11:25:34 +02004555
4556 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004557 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
Takashi Iwai763f3562005-06-03 11:25:34 +02004558
4559 snd_iprintf(buffer, "--- System ---\n");
4560
4561 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004562 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4563 status & HDSPM_audioIRQPending,
4564 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4565 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4566 hdspm->irq_count);
Takashi Iwai763f3562005-06-03 11:25:34 +02004567 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004568 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4569 "estimated= %ld (bytes)\n",
4570 ((status & HDSPM_BufferID) ? 1 : 0),
4571 (status & HDSPM_BufferPositionMask),
4572 (status & HDSPM_BufferPositionMask) %
4573 (2 * (int)hdspm->period_bytes),
4574 ((status & HDSPM_BufferPositionMask) - 64) %
4575 (2 * (int)hdspm->period_bytes),
4576 (long) hdspm_hw_pointer(hdspm) * 4);
Takashi Iwai763f3562005-06-03 11:25:34 +02004577
4578 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004579 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4580 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4581 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4582 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4583 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
Takashi Iwai763f3562005-06-03 11:25:34 +02004584 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004585 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4586 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4587 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4588 snd_iprintf(buffer,
4589 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4590 "status2=0x%x\n",
4591 hdspm->control_register, hdspm->control2_register,
4592 status, status2);
4593 if (status & HDSPM_tco_detect) {
4594 snd_iprintf(buffer, "TCO module detected.\n");
4595 a = hdspm_read(hdspm, HDSPM_RD_TCO+4);
4596 if (a & HDSPM_TCO1_LTC_Input_valid) {
4597 snd_iprintf(buffer, " LTC valid, ");
4598 switch (a & (HDSPM_TCO1_LTC_Format_LSB |
4599 HDSPM_TCO1_LTC_Format_MSB)) {
4600 case 0:
4601 snd_iprintf(buffer, "24 fps, ");
4602 break;
4603 case HDSPM_TCO1_LTC_Format_LSB:
4604 snd_iprintf(buffer, "25 fps, ");
4605 break;
4606 case HDSPM_TCO1_LTC_Format_MSB:
4607 snd_iprintf(buffer, "29.97 fps, ");
4608 break;
4609 default:
4610 snd_iprintf(buffer, "30 fps, ");
4611 break;
4612 }
4613 if (a & HDSPM_TCO1_set_drop_frame_flag) {
4614 snd_iprintf(buffer, "drop frame\n");
4615 } else {
4616 snd_iprintf(buffer, "full frame\n");
4617 }
4618 } else {
4619 snd_iprintf(buffer, " no LTC\n");
4620 }
4621 if (a & HDSPM_TCO1_Video_Input_Format_NTSC) {
4622 snd_iprintf(buffer, " Video: NTSC\n");
4623 } else if (a & HDSPM_TCO1_Video_Input_Format_PAL) {
4624 snd_iprintf(buffer, " Video: PAL\n");
4625 } else {
4626 snd_iprintf(buffer, " No video\n");
4627 }
4628 if (a & HDSPM_TCO1_TCO_lock) {
4629 snd_iprintf(buffer, " Sync: lock\n");
4630 } else {
4631 snd_iprintf(buffer, " Sync: no lock\n");
4632 }
4633
4634 switch (hdspm->io_type) {
4635 case MADI:
4636 case AES32:
4637 freq_const = 110069313433624ULL;
4638 break;
4639 case RayDAT:
4640 case AIO:
4641 freq_const = 104857600000000ULL;
4642 break;
4643 case MADIface:
4644 break; /* no TCO possible */
4645 }
4646
4647 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
4648 snd_iprintf(buffer, " period: %u\n", period);
4649
4650
4651 /* rate = freq_const/period; */
4652 rate = div_u64(freq_const, period);
4653
4654 if (control & HDSPM_QuadSpeed) {
4655 rate *= 4;
4656 } else if (control & HDSPM_DoubleSpeed) {
4657 rate *= 2;
4658 }
4659
4660 snd_iprintf(buffer, " Frequency: %u Hz\n",
4661 (unsigned int) rate);
4662
4663 ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
4664 frames = ltc & 0xF;
4665 ltc >>= 4;
4666 frames += (ltc & 0x3) * 10;
4667 ltc >>= 4;
4668 seconds = ltc & 0xF;
4669 ltc >>= 4;
4670 seconds += (ltc & 0x7) * 10;
4671 ltc >>= 4;
4672 minutes = ltc & 0xF;
4673 ltc >>= 4;
4674 minutes += (ltc & 0x7) * 10;
4675 ltc >>= 4;
4676 hours = ltc & 0xF;
4677 ltc >>= 4;
4678 hours += (ltc & 0x3) * 10;
4679 snd_iprintf(buffer,
4680 " LTC In: %02d:%02d:%02d:%02d\n",
4681 hours, minutes, seconds, frames);
4682
4683 } else {
4684 snd_iprintf(buffer, "No TCO module detected.\n");
4685 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004686
4687 snd_iprintf(buffer, "--- Settings ---\n");
4688
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004689 x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
Adrian Knoth0dca1792011-01-26 19:32:14 +01004690 HDSPM_LatencyMask));
Takashi Iwai763f3562005-06-03 11:25:34 +02004691
4692 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004693 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4694 x, (unsigned long) hdspm->period_bytes);
Takashi Iwai763f3562005-06-03 11:25:34 +02004695
Adrian Knoth0dca1792011-01-26 19:32:14 +01004696 snd_iprintf(buffer, "Line out: %s\n",
4697 (hdspm->control_register & HDSPM_LineOut) ? "on " : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004698
4699 switch (hdspm->control_register & HDSPM_InputMask) {
4700 case HDSPM_InputOptical:
4701 insel = "Optical";
4702 break;
4703 case HDSPM_InputCoaxial:
4704 insel = "Coaxial";
4705 break;
4706 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01004707 insel = "Unkown";
Takashi Iwai763f3562005-06-03 11:25:34 +02004708 }
4709
Takashi Iwai763f3562005-06-03 11:25:34 +02004710 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004711 "ClearTrackMarker = %s, Transmit in %s Channel Mode, "
4712 "Auto Input %s\n",
4713 (hdspm->control_register & HDSPM_clr_tms) ? "on" : "off",
4714 (hdspm->control_register & HDSPM_TX_64ch) ? "64" : "56",
4715 (hdspm->control_register & HDSPM_AutoInp) ? "on" : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004716
Adrian Knoth0dca1792011-01-26 19:32:14 +01004717
Remy Bruno3cee5a62006-10-16 12:46:32 +02004718 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
Adrian Knoth0dca1792011-01-26 19:32:14 +01004719 system_clock_mode = "AutoSync";
Remy Bruno3cee5a62006-10-16 12:46:32 +02004720 else
Takashi Iwai763f3562005-06-03 11:25:34 +02004721 system_clock_mode = "Master";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004722 snd_iprintf(buffer, "AutoSync Reference: %s\n", system_clock_mode);
Takashi Iwai763f3562005-06-03 11:25:34 +02004723
4724 switch (hdspm_pref_sync_ref(hdspm)) {
4725 case HDSPM_SYNC_FROM_WORD:
4726 pref_sync_ref = "Word Clock";
4727 break;
4728 case HDSPM_SYNC_FROM_MADI:
4729 pref_sync_ref = "MADI Sync";
4730 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004731 case HDSPM_SYNC_FROM_TCO:
4732 pref_sync_ref = "TCO";
4733 break;
4734 case HDSPM_SYNC_FROM_SYNC_IN:
4735 pref_sync_ref = "Sync In";
4736 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004737 default:
4738 pref_sync_ref = "XXXX Clock";
4739 break;
4740 }
4741 snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004742 pref_sync_ref);
Takashi Iwai763f3562005-06-03 11:25:34 +02004743
4744 snd_iprintf(buffer, "System Clock Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004745 hdspm->system_sample_rate);
Takashi Iwai763f3562005-06-03 11:25:34 +02004746
4747
4748 snd_iprintf(buffer, "--- Status:\n");
4749
4750 x = status & HDSPM_madiSync;
4751 x2 = status2 & HDSPM_wcSync;
4752
4753 snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004754 (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
4755 "NoLock",
4756 (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
4757 "NoLock");
Takashi Iwai763f3562005-06-03 11:25:34 +02004758
4759 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004760 case HDSPM_AUTOSYNC_FROM_SYNC_IN:
4761 autosync_ref = "Sync In";
4762 break;
4763 case HDSPM_AUTOSYNC_FROM_TCO:
4764 autosync_ref = "TCO";
4765 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004766 case HDSPM_AUTOSYNC_FROM_WORD:
4767 autosync_ref = "Word Clock";
4768 break;
4769 case HDSPM_AUTOSYNC_FROM_MADI:
4770 autosync_ref = "MADI Sync";
4771 break;
4772 case HDSPM_AUTOSYNC_FROM_NONE:
4773 autosync_ref = "Input not valid";
4774 break;
4775 default:
4776 autosync_ref = "---";
4777 break;
4778 }
4779 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004780 "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
4781 autosync_ref, hdspm_external_sample_rate(hdspm),
4782 (status & HDSPM_madiFreqMask) >> 22,
4783 (status2 & HDSPM_wcFreqMask) >> 5);
Takashi Iwai763f3562005-06-03 11:25:34 +02004784
4785 snd_iprintf(buffer, "Input: %s, Mode=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004786 (status & HDSPM_AB_int) ? "Coax" : "Optical",
4787 (status & HDSPM_RX_64ch) ? "64 channels" :
4788 "56 channels");
Takashi Iwai763f3562005-06-03 11:25:34 +02004789
4790 snd_iprintf(buffer, "\n");
4791}
4792
Remy Bruno3cee5a62006-10-16 12:46:32 +02004793static void
4794snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
4795 struct snd_info_buffer *buffer)
4796{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004797 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004798 unsigned int status;
4799 unsigned int status2;
4800 unsigned int timecode;
4801 int pref_syncref;
4802 char *autosync_ref;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004803 int x;
4804
4805 status = hdspm_read(hdspm, HDSPM_statusRegister);
4806 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
4807 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
4808
4809 snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
4810 hdspm->card_name, hdspm->card->number + 1,
4811 hdspm->firmware_rev);
4812
4813 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
4814 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
4815
4816 snd_iprintf(buffer, "--- System ---\n");
4817
4818 snd_iprintf(buffer,
4819 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4820 status & HDSPM_audioIRQPending,
4821 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4822 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4823 hdspm->irq_count);
4824 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004825 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4826 "estimated= %ld (bytes)\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004827 ((status & HDSPM_BufferID) ? 1 : 0),
4828 (status & HDSPM_BufferPositionMask),
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004829 (status & HDSPM_BufferPositionMask) %
4830 (2 * (int)hdspm->period_bytes),
4831 ((status & HDSPM_BufferPositionMask) - 64) %
4832 (2 * (int)hdspm->period_bytes),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004833 (long) hdspm_hw_pointer(hdspm) * 4);
4834
4835 snd_iprintf(buffer,
4836 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4837 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4838 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4839 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4840 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
4841 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004842 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4843 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4844 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4845 snd_iprintf(buffer,
4846 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4847 "status2=0x%x\n",
4848 hdspm->control_register, hdspm->control2_register,
4849 status, status2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02004850
4851 snd_iprintf(buffer, "--- Settings ---\n");
4852
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004853 x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
Adrian Knoth0dca1792011-01-26 19:32:14 +01004854 HDSPM_LatencyMask));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004855
4856 snd_iprintf(buffer,
4857 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4858 x, (unsigned long) hdspm->period_bytes);
4859
Adrian Knoth0dca1792011-01-26 19:32:14 +01004860 snd_iprintf(buffer, "Line out: %s\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004861 (hdspm->
Adrian Knoth0dca1792011-01-26 19:32:14 +01004862 control_register & HDSPM_LineOut) ? "on " : "off");
Remy Bruno3cee5a62006-10-16 12:46:32 +02004863
4864 snd_iprintf(buffer,
4865 "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
4866 (hdspm->
4867 control_register & HDSPM_clr_tms) ? "on" : "off",
4868 (hdspm->
4869 control_register & HDSPM_Emphasis) ? "on" : "off",
4870 (hdspm->
4871 control_register & HDSPM_Dolby) ? "on" : "off");
4872
Remy Bruno3cee5a62006-10-16 12:46:32 +02004873
4874 pref_syncref = hdspm_pref_sync_ref(hdspm);
4875 if (pref_syncref == 0)
4876 snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
4877 else
4878 snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
4879 pref_syncref);
4880
4881 snd_iprintf(buffer, "System Clock Frequency: %d\n",
4882 hdspm->system_sample_rate);
4883
4884 snd_iprintf(buffer, "Double speed: %s\n",
4885 hdspm->control_register & HDSPM_DS_DoubleWire?
4886 "Double wire" : "Single wire");
4887 snd_iprintf(buffer, "Quad speed: %s\n",
4888 hdspm->control_register & HDSPM_QS_DoubleWire?
4889 "Double wire" :
4890 hdspm->control_register & HDSPM_QS_QuadWire?
4891 "Quad wire" : "Single wire");
4892
4893 snd_iprintf(buffer, "--- Status:\n");
4894
4895 snd_iprintf(buffer, "Word: %s Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004896 (status & HDSPM_AES32_wcLock) ? "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004897 HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004898
4899 for (x = 0; x < 8; x++) {
4900 snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004901 x+1,
4902 (status2 & (HDSPM_LockAES >> x)) ?
Adrian Knoth0dca1792011-01-26 19:32:14 +01004903 "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004904 HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004905 }
4906
4907 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004908 case HDSPM_AES32_AUTOSYNC_FROM_NONE:
4909 autosync_ref = "None"; break;
4910 case HDSPM_AES32_AUTOSYNC_FROM_WORD:
4911 autosync_ref = "Word Clock"; break;
4912 case HDSPM_AES32_AUTOSYNC_FROM_AES1:
4913 autosync_ref = "AES1"; break;
4914 case HDSPM_AES32_AUTOSYNC_FROM_AES2:
4915 autosync_ref = "AES2"; break;
4916 case HDSPM_AES32_AUTOSYNC_FROM_AES3:
4917 autosync_ref = "AES3"; break;
4918 case HDSPM_AES32_AUTOSYNC_FROM_AES4:
4919 autosync_ref = "AES4"; break;
4920 case HDSPM_AES32_AUTOSYNC_FROM_AES5:
4921 autosync_ref = "AES5"; break;
4922 case HDSPM_AES32_AUTOSYNC_FROM_AES6:
4923 autosync_ref = "AES6"; break;
4924 case HDSPM_AES32_AUTOSYNC_FROM_AES7:
4925 autosync_ref = "AES7"; break;
4926 case HDSPM_AES32_AUTOSYNC_FROM_AES8:
4927 autosync_ref = "AES8"; break;
4928 default:
4929 autosync_ref = "---"; break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004930 }
4931 snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
4932
4933 snd_iprintf(buffer, "\n");
4934}
4935
Adrian Knoth0dca1792011-01-26 19:32:14 +01004936static void
4937snd_hdspm_proc_read_raydat(struct snd_info_entry *entry,
4938 struct snd_info_buffer *buffer)
4939{
4940 struct hdspm *hdspm = entry->private_data;
4941 unsigned int status1, status2, status3, control, i;
4942 unsigned int lock, sync;
4943
4944 status1 = hdspm_read(hdspm, HDSPM_RD_STATUS_1); /* s1 */
4945 status2 = hdspm_read(hdspm, HDSPM_RD_STATUS_2); /* freq */
4946 status3 = hdspm_read(hdspm, HDSPM_RD_STATUS_3); /* s2 */
4947
4948 control = hdspm->control_register;
4949
4950 snd_iprintf(buffer, "STATUS1: 0x%08x\n", status1);
4951 snd_iprintf(buffer, "STATUS2: 0x%08x\n", status2);
4952 snd_iprintf(buffer, "STATUS3: 0x%08x\n", status3);
4953
4954
4955 snd_iprintf(buffer, "\n*** CLOCK MODE\n\n");
4956
4957 snd_iprintf(buffer, "Clock mode : %s\n",
4958 (hdspm_system_clock_mode(hdspm) == 0) ? "master" : "slave");
4959 snd_iprintf(buffer, "System frequency: %d Hz\n",
4960 hdspm_get_system_sample_rate(hdspm));
4961
4962 snd_iprintf(buffer, "\n*** INPUT STATUS\n\n");
4963
4964 lock = 0x1;
4965 sync = 0x100;
4966
4967 for (i = 0; i < 8; i++) {
4968 snd_iprintf(buffer, "s1_input %d: Lock %d, Sync %d, Freq %s\n",
4969 i,
4970 (status1 & lock) ? 1 : 0,
4971 (status1 & sync) ? 1 : 0,
4972 texts_freq[(status2 >> (i * 4)) & 0xF]);
4973
4974 lock = lock<<1;
4975 sync = sync<<1;
4976 }
4977
4978 snd_iprintf(buffer, "WC input: Lock %d, Sync %d, Freq %s\n",
4979 (status1 & 0x1000000) ? 1 : 0,
4980 (status1 & 0x2000000) ? 1 : 0,
4981 texts_freq[(status1 >> 16) & 0xF]);
4982
4983 snd_iprintf(buffer, "TCO input: Lock %d, Sync %d, Freq %s\n",
4984 (status1 & 0x4000000) ? 1 : 0,
4985 (status1 & 0x8000000) ? 1 : 0,
4986 texts_freq[(status1 >> 20) & 0xF]);
4987
4988 snd_iprintf(buffer, "SYNC IN: Lock %d, Sync %d, Freq %s\n",
4989 (status3 & 0x400) ? 1 : 0,
4990 (status3 & 0x800) ? 1 : 0,
4991 texts_freq[(status2 >> 12) & 0xF]);
4992
4993}
4994
Remy Bruno3cee5a62006-10-16 12:46:32 +02004995#ifdef CONFIG_SND_DEBUG
4996static void
Adrian Knoth0dca1792011-01-26 19:32:14 +01004997snd_hdspm_proc_read_debug(struct snd_info_entry *entry,
Remy Bruno3cee5a62006-10-16 12:46:32 +02004998 struct snd_info_buffer *buffer)
4999{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005000 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005001
5002 int j,i;
5003
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005004 for (i = 0; i < 256 /* 1024*64 */; i += j) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02005005 snd_iprintf(buffer, "0x%08X: ", i);
5006 for (j = 0; j < 16; j += 4)
5007 snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
5008 snd_iprintf(buffer, "\n");
5009 }
5010}
5011#endif
5012
5013
Adrian Knoth0dca1792011-01-26 19:32:14 +01005014static void snd_hdspm_proc_ports_in(struct snd_info_entry *entry,
5015 struct snd_info_buffer *buffer)
5016{
5017 struct hdspm *hdspm = entry->private_data;
5018 int i;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005019
Adrian Knoth0dca1792011-01-26 19:32:14 +01005020 snd_iprintf(buffer, "# generated by hdspm\n");
5021
5022 for (i = 0; i < hdspm->max_channels_in; i++) {
5023 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_in[i]);
5024 }
5025}
5026
5027static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry,
5028 struct snd_info_buffer *buffer)
5029{
5030 struct hdspm *hdspm = entry->private_data;
5031 int i;
5032
5033 snd_iprintf(buffer, "# generated by hdspm\n");
5034
5035 for (i = 0; i < hdspm->max_channels_out; i++) {
5036 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_out[i]);
5037 }
5038}
5039
5040
5041static void __devinit snd_hdspm_proc_init(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005042{
Takashi Iwai98274f02005-11-17 14:52:34 +01005043 struct snd_info_entry *entry;
Takashi Iwai763f3562005-06-03 11:25:34 +02005044
Adrian Knoth0dca1792011-01-26 19:32:14 +01005045 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) {
5046 switch (hdspm->io_type) {
5047 case AES32:
5048 snd_info_set_text_ops(entry, hdspm,
5049 snd_hdspm_proc_read_aes32);
5050 break;
5051 case MADI:
5052 snd_info_set_text_ops(entry, hdspm,
5053 snd_hdspm_proc_read_madi);
5054 break;
5055 case MADIface:
5056 /* snd_info_set_text_ops(entry, hdspm,
5057 snd_hdspm_proc_read_madiface); */
5058 break;
5059 case RayDAT:
5060 snd_info_set_text_ops(entry, hdspm,
5061 snd_hdspm_proc_read_raydat);
5062 break;
5063 case AIO:
5064 break;
5065 }
5066 }
5067
5068 if (!snd_card_proc_new(hdspm->card, "ports.in", &entry)) {
5069 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_in);
5070 }
5071
5072 if (!snd_card_proc_new(hdspm->card, "ports.out", &entry)) {
5073 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_out);
5074 }
5075
Remy Bruno3cee5a62006-10-16 12:46:32 +02005076#ifdef CONFIG_SND_DEBUG
5077 /* debug file to read all hdspm registers */
5078 if (!snd_card_proc_new(hdspm->card, "debug", &entry))
5079 snd_info_set_text_ops(entry, hdspm,
5080 snd_hdspm_proc_read_debug);
5081#endif
Takashi Iwai763f3562005-06-03 11:25:34 +02005082}
5083
5084/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005085 hdspm intitialize
Takashi Iwai763f3562005-06-03 11:25:34 +02005086 ------------------------------------------------------------*/
5087
Takashi Iwai98274f02005-11-17 14:52:34 +01005088static int snd_hdspm_set_defaults(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005089{
Takashi Iwai763f3562005-06-03 11:25:34 +02005090 /* ASSUMPTION: hdspm->lock is either held, or there is no need to
Joe Perches561de312007-12-18 13:13:47 +01005091 hold it (e.g. during module initialization).
Adrian Knoth0dca1792011-01-26 19:32:14 +01005092 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005093
5094 /* set defaults: */
5095
Adrian Knoth0dca1792011-01-26 19:32:14 +01005096 hdspm->settings_register = 0;
5097
5098 switch (hdspm->io_type) {
5099 case MADI:
5100 case MADIface:
5101 hdspm->control_register =
5102 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5103 break;
5104
5105 case RayDAT:
5106 case AIO:
5107 hdspm->settings_register = 0x1 + 0x1000;
5108 /* Magic values are: LAT_0, LAT_2, Master, freq1, tx64ch, inp_0,
5109 * line_out */
5110 hdspm->control_register =
5111 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5112 break;
5113
5114 case AES32:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005115 hdspm->control_register =
5116 HDSPM_ClockModeMaster | /* Master Cloack Mode on */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005117 hdspm_encode_latency(7) | /* latency max=8192samples */
Remy Bruno3cee5a62006-10-16 12:46:32 +02005118 HDSPM_SyncRef0 | /* AES1 is syncclock */
5119 HDSPM_LineOut | /* Analog output in */
5120 HDSPM_Professional; /* Professional mode */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005121 break;
5122 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005123
5124 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5125
Adrian Knoth0dca1792011-01-26 19:32:14 +01005126 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005127 /* No control2 register for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005128#ifdef SNDRV_BIG_ENDIAN
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005129 hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
Takashi Iwai763f3562005-06-03 11:25:34 +02005130#else
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005131 hdspm->control2_register = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005132#endif
5133
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005134 hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
5135 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005136 hdspm_compute_period_size(hdspm);
5137
5138 /* silence everything */
5139
5140 all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
5141
Adrian Knoth0dca1792011-01-26 19:32:14 +01005142 if (hdspm->io_type == AIO || hdspm->io_type == RayDAT) {
5143 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
Takashi Iwai763f3562005-06-03 11:25:34 +02005144 }
5145
5146 /* set a default rate so that the channel map is set up. */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005147 hdspm_set_rate(hdspm, 48000, 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02005148
5149 return 0;
5150}
5151
5152
5153/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005154 interrupt
Takashi Iwai763f3562005-06-03 11:25:34 +02005155 ------------------------------------------------------------*/
5156
David Howells7d12e782006-10-05 14:55:46 +01005157static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02005158{
Takashi Iwai98274f02005-11-17 14:52:34 +01005159 struct hdspm *hdspm = (struct hdspm *) dev_id;
Takashi Iwai763f3562005-06-03 11:25:34 +02005160 unsigned int status;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005161 int i, audio, midi, schedule = 0;
5162 /* cycles_t now; */
Takashi Iwai763f3562005-06-03 11:25:34 +02005163
5164 status = hdspm_read(hdspm, HDSPM_statusRegister);
5165
5166 audio = status & HDSPM_audioIRQPending;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005167 midi = status & (HDSPM_midi0IRQPending | HDSPM_midi1IRQPending |
5168 HDSPM_midi2IRQPending | HDSPM_midi3IRQPending);
Takashi Iwai763f3562005-06-03 11:25:34 +02005169
Adrian Knoth0dca1792011-01-26 19:32:14 +01005170 /* now = get_cycles(); */
5171 /**
5172 * LAT_2..LAT_0 period counter (win) counter (mac)
5173 * 6 4096 ~256053425 ~514672358
5174 * 5 2048 ~128024983 ~257373821
5175 * 4 1024 ~64023706 ~128718089
5176 * 3 512 ~32005945 ~64385999
5177 * 2 256 ~16003039 ~32260176
5178 * 1 128 ~7998738 ~16194507
5179 * 0 64 ~3998231 ~8191558
5180 **/
5181 /*
5182 snd_printk(KERN_INFO "snd_hdspm_interrupt %llu @ %llx\n",
5183 now-hdspm->last_interrupt, status & 0xFFC0);
5184 hdspm->last_interrupt = now;
5185 */
5186
5187 if (!audio && !midi)
Takashi Iwai763f3562005-06-03 11:25:34 +02005188 return IRQ_NONE;
5189
5190 hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
5191 hdspm->irq_count++;
5192
Takashi Iwai763f3562005-06-03 11:25:34 +02005193
5194 if (audio) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005195 if (hdspm->capture_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005196 snd_pcm_period_elapsed(hdspm->capture_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005197
5198 if (hdspm->playback_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005199 snd_pcm_period_elapsed(hdspm->playback_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005200 }
5201
Adrian Knoth0dca1792011-01-26 19:32:14 +01005202 if (midi) {
5203 i = 0;
5204 while (i < hdspm->midiPorts) {
5205 if ((hdspm_read(hdspm,
5206 hdspm->midi[i].statusIn) & 0xff) &&
5207 (status & hdspm->midi[i].irq)) {
5208 /* we disable interrupts for this input until
5209 * processing is done
5210 */
5211 hdspm->control_register &= ~hdspm->midi[i].ie;
5212 hdspm_write(hdspm, HDSPM_controlRegister,
5213 hdspm->control_register);
5214 hdspm->midi[i].pending = 1;
5215 schedule = 1;
5216 }
5217
5218 i++;
5219 }
5220
5221 if (schedule)
5222 tasklet_hi_schedule(&hdspm->midi_tasklet);
Takashi Iwai763f3562005-06-03 11:25:34 +02005223 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005224
Takashi Iwai763f3562005-06-03 11:25:34 +02005225 return IRQ_HANDLED;
5226}
5227
5228/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005229 pcm interface
Takashi Iwai763f3562005-06-03 11:25:34 +02005230 ------------------------------------------------------------*/
5231
5232
Adrian Knoth0dca1792011-01-26 19:32:14 +01005233static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream
5234 *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005235{
Takashi Iwai98274f02005-11-17 14:52:34 +01005236 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005237 return hdspm_hw_pointer(hdspm);
5238}
5239
Takashi Iwai763f3562005-06-03 11:25:34 +02005240
Takashi Iwai98274f02005-11-17 14:52:34 +01005241static int snd_hdspm_reset(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005242{
Takashi Iwai98274f02005-11-17 14:52:34 +01005243 struct snd_pcm_runtime *runtime = substream->runtime;
5244 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5245 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005246
5247 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5248 other = hdspm->capture_substream;
5249 else
5250 other = hdspm->playback_substream;
5251
5252 if (hdspm->running)
5253 runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
5254 else
5255 runtime->status->hw_ptr = 0;
5256 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005257 struct snd_pcm_substream *s;
5258 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01005259 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005260 if (s == other) {
5261 oruntime->status->hw_ptr =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005262 runtime->status->hw_ptr;
Takashi Iwai763f3562005-06-03 11:25:34 +02005263 break;
5264 }
5265 }
5266 }
5267 return 0;
5268}
5269
Takashi Iwai98274f02005-11-17 14:52:34 +01005270static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
5271 struct snd_pcm_hw_params *params)
Takashi Iwai763f3562005-06-03 11:25:34 +02005272{
Takashi Iwai98274f02005-11-17 14:52:34 +01005273 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005274 int err;
5275 int i;
5276 pid_t this_pid;
5277 pid_t other_pid;
Takashi Iwai763f3562005-06-03 11:25:34 +02005278
5279 spin_lock_irq(&hdspm->lock);
5280
5281 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5282 this_pid = hdspm->playback_pid;
5283 other_pid = hdspm->capture_pid;
5284 } else {
5285 this_pid = hdspm->capture_pid;
5286 other_pid = hdspm->playback_pid;
5287 }
5288
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005289 if (other_pid > 0 && this_pid != other_pid) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005290
5291 /* The other stream is open, and not by the same
5292 task as this one. Make sure that the parameters
5293 that matter are the same.
Adrian Knoth0dca1792011-01-26 19:32:14 +01005294 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005295
5296 if (params_rate(params) != hdspm->system_sample_rate) {
5297 spin_unlock_irq(&hdspm->lock);
5298 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005299 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005300 return -EBUSY;
5301 }
5302
5303 if (params_period_size(params) != hdspm->period_bytes / 4) {
5304 spin_unlock_irq(&hdspm->lock);
5305 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005306 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005307 return -EBUSY;
5308 }
5309
5310 }
5311 /* We're fine. */
5312 spin_unlock_irq(&hdspm->lock);
5313
5314 /* how to make sure that the rate matches an externally-set one ? */
5315
5316 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005317 err = hdspm_set_rate(hdspm, params_rate(params), 0);
5318 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005319 snd_printk(KERN_INFO "err on hdspm_set_rate: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005320 spin_unlock_irq(&hdspm->lock);
5321 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005322 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005323 return err;
5324 }
5325 spin_unlock_irq(&hdspm->lock);
5326
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005327 err = hdspm_set_interrupt_interval(hdspm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005328 params_period_size(params));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005329 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005330 snd_printk(KERN_INFO "err on hdspm_set_interrupt_interval: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005331 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005332 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005333 return err;
5334 }
5335
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005336 /* Memory allocation, takashi's method, dont know if we should
5337 * spinlock
5338 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005339 /* malloc all buffer even if not enabled to get sure */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005340 /* Update for MADI rev 204: we need to allocate for all channels,
5341 * otherwise it doesn't work at 96kHz */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005342
Takashi Iwai763f3562005-06-03 11:25:34 +02005343 err =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005344 snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
5345 if (err < 0) {
5346 snd_printk(KERN_INFO "err on snd_pcm_lib_malloc_pages: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005347 return err;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005348 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005349
Takashi Iwai763f3562005-06-03 11:25:34 +02005350 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5351
Takashi Iwai77a23f22008-08-21 13:00:13 +02005352 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferOut,
Takashi Iwai763f3562005-06-03 11:25:34 +02005353 params_channels(params));
5354
5355 for (i = 0; i < params_channels(params); ++i)
5356 snd_hdspm_enable_out(hdspm, i, 1);
5357
5358 hdspm->playback_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005359 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005360 snd_printdd("Allocated sample buffer for playback at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005361 hdspm->playback_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005362 } else {
Takashi Iwai77a23f22008-08-21 13:00:13 +02005363 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn,
Takashi Iwai763f3562005-06-03 11:25:34 +02005364 params_channels(params));
5365
5366 for (i = 0; i < params_channels(params); ++i)
5367 snd_hdspm_enable_in(hdspm, i, 1);
5368
5369 hdspm->capture_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005370 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005371 snd_printdd("Allocated sample buffer for capture at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005372 hdspm->capture_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005373 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005374
Remy Bruno3cee5a62006-10-16 12:46:32 +02005375 /*
5376 snd_printdd("Allocated sample buffer for %s at 0x%08X\n",
5377 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5378 "playback" : "capture",
Takashi Iwai77a23f22008-08-21 13:00:13 +02005379 snd_pcm_sgbuf_get_addr(substream, 0));
Adrian Knoth0dca1792011-01-26 19:32:14 +01005380 */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005381 /*
Adrian Knoth0dca1792011-01-26 19:32:14 +01005382 snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n",
5383 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5384 "playback" : "capture",
5385 params_rate(params), params_channels(params),
5386 params_buffer_size(params));
5387 */
5388
5389
5390 /* Switch to native float format if requested */
5391 if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) {
5392 if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT))
5393 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE float format.\n");
5394
5395 hdspm->control_register |= HDSPe_FLOAT_FORMAT;
5396 } else if (SNDRV_PCM_FORMAT_S32_LE == params_format(params)) {
5397 if (hdspm->control_register & HDSPe_FLOAT_FORMAT)
5398 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE integer format.\n");
5399
5400 hdspm->control_register &= ~HDSPe_FLOAT_FORMAT;
5401 }
5402 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5403
Takashi Iwai763f3562005-06-03 11:25:34 +02005404 return 0;
5405}
5406
Takashi Iwai98274f02005-11-17 14:52:34 +01005407static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005408{
5409 int i;
Takashi Iwai98274f02005-11-17 14:52:34 +01005410 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005411
5412 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5413
Adrian Knoth0dca1792011-01-26 19:32:14 +01005414 /* params_channels(params) should be enough,
Takashi Iwai763f3562005-06-03 11:25:34 +02005415 but to get sure in case of error */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005416 for (i = 0; i < hdspm->max_channels_out; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005417 snd_hdspm_enable_out(hdspm, i, 0);
5418
5419 hdspm->playback_buffer = NULL;
5420 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005421 for (i = 0; i < hdspm->max_channels_in; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005422 snd_hdspm_enable_in(hdspm, i, 0);
5423
5424 hdspm->capture_buffer = NULL;
5425
5426 }
5427
5428 snd_pcm_lib_free_pages(substream);
5429
5430 return 0;
5431}
5432
Adrian Knoth0dca1792011-01-26 19:32:14 +01005433
Takashi Iwai98274f02005-11-17 14:52:34 +01005434static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005435 struct snd_pcm_channel_info *info)
Takashi Iwai763f3562005-06-03 11:25:34 +02005436{
Takashi Iwai98274f02005-11-17 14:52:34 +01005437 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005438
Adrian Knoth0dca1792011-01-26 19:32:14 +01005439 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5440 if (snd_BUG_ON(info->channel >= hdspm->max_channels_out)) {
5441 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel out of range (%d)\n", info->channel);
5442 return -EINVAL;
5443 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005444
Adrian Knoth0dca1792011-01-26 19:32:14 +01005445 if (hdspm->channel_map_out[info->channel] < 0) {
5446 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel %d mapped out\n", info->channel);
5447 return -EINVAL;
5448 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005449
Adrian Knoth0dca1792011-01-26 19:32:14 +01005450 info->offset = hdspm->channel_map_out[info->channel] *
5451 HDSPM_CHANNEL_BUFFER_BYTES;
5452 } else {
5453 if (snd_BUG_ON(info->channel >= hdspm->max_channels_in)) {
5454 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel out of range (%d)\n", info->channel);
5455 return -EINVAL;
5456 }
5457
5458 if (hdspm->channel_map_in[info->channel] < 0) {
5459 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel %d mapped out\n", info->channel);
5460 return -EINVAL;
5461 }
5462
5463 info->offset = hdspm->channel_map_in[info->channel] *
5464 HDSPM_CHANNEL_BUFFER_BYTES;
5465 }
5466
Takashi Iwai763f3562005-06-03 11:25:34 +02005467 info->first = 0;
5468 info->step = 32;
5469 return 0;
5470}
5471
Adrian Knoth0dca1792011-01-26 19:32:14 +01005472
Takashi Iwai98274f02005-11-17 14:52:34 +01005473static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005474 unsigned int cmd, void *arg)
Takashi Iwai763f3562005-06-03 11:25:34 +02005475{
5476 switch (cmd) {
5477 case SNDRV_PCM_IOCTL1_RESET:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005478 return snd_hdspm_reset(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005479
5480 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Adrian Knoth0dca1792011-01-26 19:32:14 +01005481 {
5482 struct snd_pcm_channel_info *info = arg;
5483 return snd_hdspm_channel_info(substream, info);
5484 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005485 default:
5486 break;
5487 }
5488
5489 return snd_pcm_lib_ioctl(substream, cmd, arg);
5490}
5491
Takashi Iwai98274f02005-11-17 14:52:34 +01005492static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
Takashi Iwai763f3562005-06-03 11:25:34 +02005493{
Takashi Iwai98274f02005-11-17 14:52:34 +01005494 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5495 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005496 int running;
5497
5498 spin_lock(&hdspm->lock);
5499 running = hdspm->running;
5500 switch (cmd) {
5501 case SNDRV_PCM_TRIGGER_START:
5502 running |= 1 << substream->stream;
5503 break;
5504 case SNDRV_PCM_TRIGGER_STOP:
5505 running &= ~(1 << substream->stream);
5506 break;
5507 default:
5508 snd_BUG();
5509 spin_unlock(&hdspm->lock);
5510 return -EINVAL;
5511 }
5512 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5513 other = hdspm->capture_substream;
5514 else
5515 other = hdspm->playback_substream;
5516
5517 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005518 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01005519 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005520 if (s == other) {
5521 snd_pcm_trigger_done(s, substream);
5522 if (cmd == SNDRV_PCM_TRIGGER_START)
5523 running |= 1 << s->stream;
5524 else
5525 running &= ~(1 << s->stream);
5526 goto _ok;
5527 }
5528 }
5529 if (cmd == SNDRV_PCM_TRIGGER_START) {
5530 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005531 && substream->stream ==
5532 SNDRV_PCM_STREAM_CAPTURE)
Takashi Iwai763f3562005-06-03 11:25:34 +02005533 hdspm_silence_playback(hdspm);
5534 } else {
5535 if (running &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01005536 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Takashi Iwai763f3562005-06-03 11:25:34 +02005537 hdspm_silence_playback(hdspm);
5538 }
5539 } else {
5540 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
5541 hdspm_silence_playback(hdspm);
5542 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005543_ok:
Takashi Iwai763f3562005-06-03 11:25:34 +02005544 snd_pcm_trigger_done(substream, substream);
5545 if (!hdspm->running && running)
5546 hdspm_start_audio(hdspm);
5547 else if (hdspm->running && !running)
5548 hdspm_stop_audio(hdspm);
5549 hdspm->running = running;
5550 spin_unlock(&hdspm->lock);
5551
5552 return 0;
5553}
5554
Takashi Iwai98274f02005-11-17 14:52:34 +01005555static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005556{
5557 return 0;
5558}
5559
Adrian Knoth0dca1792011-01-26 19:32:14 +01005560static unsigned int period_sizes_old[] = {
5561 64, 128, 256, 512, 1024, 2048, 4096
5562};
5563
5564static unsigned int period_sizes_new[] = {
5565 32, 64, 128, 256, 512, 1024, 2048, 4096
5566};
5567
5568/* RayDAT and AIO always have a buffer of 16384 samples per channel */
5569static unsigned int raydat_aio_buffer_sizes[] = {
5570 16384
5571};
Takashi Iwai763f3562005-06-03 11:25:34 +02005572
Takashi Iwai98274f02005-11-17 14:52:34 +01005573static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005574 .info = (SNDRV_PCM_INFO_MMAP |
5575 SNDRV_PCM_INFO_MMAP_VALID |
5576 SNDRV_PCM_INFO_NONINTERLEAVED |
5577 SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
5578 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5579 .rates = (SNDRV_PCM_RATE_32000 |
5580 SNDRV_PCM_RATE_44100 |
5581 SNDRV_PCM_RATE_48000 |
5582 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005583 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5584 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ),
Takashi Iwai763f3562005-06-03 11:25:34 +02005585 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005586 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005587 .channels_min = 1,
5588 .channels_max = HDSPM_MAX_CHANNELS,
5589 .buffer_bytes_max =
5590 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
5591 .period_bytes_min = (64 * 4),
Adrian Knoth0dca1792011-01-26 19:32:14 +01005592 .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005593 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005594 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005595 .fifo_size = 0
5596};
5597
Takashi Iwai98274f02005-11-17 14:52:34 +01005598static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005599 .info = (SNDRV_PCM_INFO_MMAP |
5600 SNDRV_PCM_INFO_MMAP_VALID |
5601 SNDRV_PCM_INFO_NONINTERLEAVED |
5602 SNDRV_PCM_INFO_SYNC_START),
5603 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5604 .rates = (SNDRV_PCM_RATE_32000 |
5605 SNDRV_PCM_RATE_44100 |
5606 SNDRV_PCM_RATE_48000 |
5607 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005608 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5609 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
Takashi Iwai763f3562005-06-03 11:25:34 +02005610 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005611 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005612 .channels_min = 1,
5613 .channels_max = HDSPM_MAX_CHANNELS,
5614 .buffer_bytes_max =
5615 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
5616 .period_bytes_min = (64 * 4),
Adrian Knoth0dca1792011-01-26 19:32:14 +01005617 .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005618 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005619 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005620 .fifo_size = 0
5621};
5622
Adrian Knoth0dca1792011-01-26 19:32:14 +01005623static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_old = {
5624 .count = ARRAY_SIZE(period_sizes_old),
5625 .list = period_sizes_old,
Takashi Iwai763f3562005-06-03 11:25:34 +02005626 .mask = 0
5627};
5628
Adrian Knoth0dca1792011-01-26 19:32:14 +01005629static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_new = {
5630 .count = ARRAY_SIZE(period_sizes_new),
5631 .list = period_sizes_new,
5632 .mask = 0
5633};
Takashi Iwai763f3562005-06-03 11:25:34 +02005634
Adrian Knoth0dca1792011-01-26 19:32:14 +01005635static struct snd_pcm_hw_constraint_list hw_constraints_raydat_io_buffer = {
5636 .count = ARRAY_SIZE(raydat_aio_buffer_sizes),
5637 .list = raydat_aio_buffer_sizes,
5638 .mask = 0
5639};
5640
5641static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
5642 struct snd_pcm_hw_rule *rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005643{
Takashi Iwai98274f02005-11-17 14:52:34 +01005644 struct hdspm *hdspm = rule->private;
5645 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005646 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005647 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005648 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5649
Adrian Knoth0dca1792011-01-26 19:32:14 +01005650 if (r->min > 96000 && r->max <= 192000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005651 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005652 .min = hdspm->qs_in_channels,
5653 .max = hdspm->qs_in_channels,
5654 .integer = 1,
5655 };
5656 return snd_interval_refine(c, &t);
5657 } else if (r->min > 48000 && r->max <= 96000) {
5658 struct snd_interval t = {
5659 .min = hdspm->ds_in_channels,
5660 .max = hdspm->ds_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005661 .integer = 1,
5662 };
5663 return snd_interval_refine(c, &t);
5664 } else if (r->max < 64000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005665 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005666 .min = hdspm->ss_in_channels,
5667 .max = hdspm->ss_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005668 .integer = 1,
5669 };
5670 return snd_interval_refine(c, &t);
5671 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005672
Takashi Iwai763f3562005-06-03 11:25:34 +02005673 return 0;
5674}
5675
Adrian Knoth0dca1792011-01-26 19:32:14 +01005676static int snd_hdspm_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
Takashi Iwai98274f02005-11-17 14:52:34 +01005677 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005678{
Takashi Iwai98274f02005-11-17 14:52:34 +01005679 struct hdspm *hdspm = rule->private;
5680 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005681 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005682 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005683 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5684
Adrian Knoth0dca1792011-01-26 19:32:14 +01005685 if (r->min > 96000 && r->max <= 192000) {
5686 struct snd_interval t = {
5687 .min = hdspm->qs_out_channels,
5688 .max = hdspm->qs_out_channels,
5689 .integer = 1,
5690 };
5691 return snd_interval_refine(c, &t);
5692 } else if (r->min > 48000 && r->max <= 96000) {
5693 struct snd_interval t = {
5694 .min = hdspm->ds_out_channels,
5695 .max = hdspm->ds_out_channels,
5696 .integer = 1,
5697 };
5698 return snd_interval_refine(c, &t);
5699 } else if (r->max < 64000) {
5700 struct snd_interval t = {
5701 .min = hdspm->ss_out_channels,
5702 .max = hdspm->ss_out_channels,
5703 .integer = 1,
5704 };
5705 return snd_interval_refine(c, &t);
5706 } else {
5707 }
5708 return 0;
5709}
5710
5711static int snd_hdspm_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
5712 struct snd_pcm_hw_rule * rule)
5713{
5714 struct hdspm *hdspm = rule->private;
5715 struct snd_interval *c =
5716 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5717 struct snd_interval *r =
5718 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5719
5720 if (c->min >= hdspm->ss_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005721 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005722 .min = 32000,
5723 .max = 48000,
5724 .integer = 1,
5725 };
5726 return snd_interval_refine(r, &t);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005727 } else if (c->max <= hdspm->qs_in_channels) {
5728 struct snd_interval t = {
5729 .min = 128000,
5730 .max = 192000,
5731 .integer = 1,
5732 };
5733 return snd_interval_refine(r, &t);
5734 } else if (c->max <= hdspm->ds_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005735 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005736 .min = 64000,
5737 .max = 96000,
5738 .integer = 1,
5739 };
Takashi Iwai763f3562005-06-03 11:25:34 +02005740 return snd_interval_refine(r, &t);
5741 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005742
5743 return 0;
5744}
5745static int snd_hdspm_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
5746 struct snd_pcm_hw_rule *rule)
5747{
5748 struct hdspm *hdspm = rule->private;
5749 struct snd_interval *c =
5750 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5751 struct snd_interval *r =
5752 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5753
5754 if (c->min >= hdspm->ss_out_channels) {
5755 struct snd_interval t = {
5756 .min = 32000,
5757 .max = 48000,
5758 .integer = 1,
5759 };
5760 return snd_interval_refine(r, &t);
5761 } else if (c->max <= hdspm->qs_out_channels) {
5762 struct snd_interval t = {
5763 .min = 128000,
5764 .max = 192000,
5765 .integer = 1,
5766 };
5767 return snd_interval_refine(r, &t);
5768 } else if (c->max <= hdspm->ds_out_channels) {
5769 struct snd_interval t = {
5770 .min = 64000,
5771 .max = 96000,
5772 .integer = 1,
5773 };
5774 return snd_interval_refine(r, &t);
5775 }
5776
Takashi Iwai763f3562005-06-03 11:25:34 +02005777 return 0;
5778}
5779
Adrian Knoth0dca1792011-01-26 19:32:14 +01005780static int snd_hdspm_hw_rule_in_channels(struct snd_pcm_hw_params *params,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005781 struct snd_pcm_hw_rule *rule)
5782{
5783 unsigned int list[3];
5784 struct hdspm *hdspm = rule->private;
5785 struct snd_interval *c = hw_param_interval(params,
5786 SNDRV_PCM_HW_PARAM_CHANNELS);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005787
5788 list[0] = hdspm->qs_in_channels;
5789 list[1] = hdspm->ds_in_channels;
5790 list[2] = hdspm->ss_in_channels;
5791 return snd_interval_list(c, 3, list, 0);
5792}
5793
5794static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params,
5795 struct snd_pcm_hw_rule *rule)
5796{
5797 unsigned int list[3];
5798 struct hdspm *hdspm = rule->private;
5799 struct snd_interval *c = hw_param_interval(params,
5800 SNDRV_PCM_HW_PARAM_CHANNELS);
5801
5802 list[0] = hdspm->qs_out_channels;
5803 list[1] = hdspm->ds_out_channels;
5804 list[2] = hdspm->ss_out_channels;
5805 return snd_interval_list(c, 3, list, 0);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005806}
5807
5808
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005809static unsigned int hdspm_aes32_sample_rates[] = {
5810 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000
5811};
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005812
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005813static struct snd_pcm_hw_constraint_list
5814hdspm_hw_constraints_aes32_sample_rates = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005815 .count = ARRAY_SIZE(hdspm_aes32_sample_rates),
5816 .list = hdspm_aes32_sample_rates,
5817 .mask = 0
5818};
5819
Takashi Iwai98274f02005-11-17 14:52:34 +01005820static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005821{
Takashi Iwai98274f02005-11-17 14:52:34 +01005822 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5823 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02005824
Takashi Iwai763f3562005-06-03 11:25:34 +02005825 spin_lock_irq(&hdspm->lock);
5826
5827 snd_pcm_set_sync(substream);
5828
Adrian Knoth0dca1792011-01-26 19:32:14 +01005829
Takashi Iwai763f3562005-06-03 11:25:34 +02005830 runtime->hw = snd_hdspm_playback_subinfo;
5831
5832 if (hdspm->capture_substream == NULL)
5833 hdspm_stop_audio(hdspm);
5834
5835 hdspm->playback_pid = current->pid;
5836 hdspm->playback_substream = substream;
5837
5838 spin_unlock_irq(&hdspm->lock);
5839
5840 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
5841
Adrian Knoth0dca1792011-01-26 19:32:14 +01005842 switch (hdspm->io_type) {
5843 case AIO:
5844 case RayDAT:
5845 snd_pcm_hw_constraint_list(runtime, 0,
5846 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5847 &hw_constraints_period_sizes_new);
5848 snd_pcm_hw_constraint_list(runtime, 0,
5849 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
5850 &hw_constraints_raydat_io_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005851
Adrian Knoth0dca1792011-01-26 19:32:14 +01005852 break;
5853
5854 default:
5855 snd_pcm_hw_constraint_list(runtime, 0,
5856 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5857 &hw_constraints_period_sizes_old);
5858 }
5859
5860 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005861 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
5862 &hdspm_hw_constraints_aes32_sample_rates);
5863 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005864 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005865 snd_hdspm_hw_rule_rate_out_channels, hdspm,
5866 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005867 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01005868
5869 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5870 snd_hdspm_hw_rule_out_channels, hdspm,
5871 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
5872
5873 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5874 snd_hdspm_hw_rule_out_channels_rate, hdspm,
5875 SNDRV_PCM_HW_PARAM_RATE, -1);
5876
Takashi Iwai763f3562005-06-03 11:25:34 +02005877 return 0;
5878}
5879
Takashi Iwai98274f02005-11-17 14:52:34 +01005880static int snd_hdspm_playback_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005881{
Takashi Iwai98274f02005-11-17 14:52:34 +01005882 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005883
5884 spin_lock_irq(&hdspm->lock);
5885
5886 hdspm->playback_pid = -1;
5887 hdspm->playback_substream = NULL;
5888
5889 spin_unlock_irq(&hdspm->lock);
5890
5891 return 0;
5892}
5893
5894
Takashi Iwai98274f02005-11-17 14:52:34 +01005895static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005896{
Takashi Iwai98274f02005-11-17 14:52:34 +01005897 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5898 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02005899
5900 spin_lock_irq(&hdspm->lock);
5901 snd_pcm_set_sync(substream);
5902 runtime->hw = snd_hdspm_capture_subinfo;
5903
5904 if (hdspm->playback_substream == NULL)
5905 hdspm_stop_audio(hdspm);
5906
5907 hdspm->capture_pid = current->pid;
5908 hdspm->capture_substream = substream;
5909
5910 spin_unlock_irq(&hdspm->lock);
5911
5912 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005913 switch (hdspm->io_type) {
5914 case AIO:
5915 case RayDAT:
5916 snd_pcm_hw_constraint_list(runtime, 0,
5917 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5918 &hw_constraints_period_sizes_new);
5919 snd_pcm_hw_constraint_list(runtime, 0,
5920 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
5921 &hw_constraints_raydat_io_buffer);
5922 break;
5923
5924 default:
5925 snd_pcm_hw_constraint_list(runtime, 0,
5926 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5927 &hw_constraints_period_sizes_old);
5928 }
5929
5930 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005931 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
5932 &hdspm_hw_constraints_aes32_sample_rates);
5933 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005934 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth88fabbf2011-02-23 11:43:10 +01005935 snd_hdspm_hw_rule_rate_in_channels, hdspm,
5936 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005937 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01005938
5939 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5940 snd_hdspm_hw_rule_in_channels, hdspm,
5941 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
5942
5943 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5944 snd_hdspm_hw_rule_in_channels_rate, hdspm,
5945 SNDRV_PCM_HW_PARAM_RATE, -1);
5946
Takashi Iwai763f3562005-06-03 11:25:34 +02005947 return 0;
5948}
5949
Takashi Iwai98274f02005-11-17 14:52:34 +01005950static int snd_hdspm_capture_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005951{
Takashi Iwai98274f02005-11-17 14:52:34 +01005952 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005953
5954 spin_lock_irq(&hdspm->lock);
5955
5956 hdspm->capture_pid = -1;
5957 hdspm->capture_substream = NULL;
5958
5959 spin_unlock_irq(&hdspm->lock);
5960 return 0;
5961}
5962
Adrian Knoth0dca1792011-01-26 19:32:14 +01005963static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
Takashi Iwai763f3562005-06-03 11:25:34 +02005964{
Adrian Knoth0dca1792011-01-26 19:32:14 +01005965 /* we have nothing to initialize but the call is required */
5966 return 0;
5967}
5968
5969static inline int copy_u32_le(void __user *dest, void __iomem *src)
5970{
5971 u32 val = readl(src);
5972 return copy_to_user(dest, &val, 4);
5973}
5974
5975static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
5976 unsigned int cmd, unsigned long __user arg)
5977{
5978 void __user *argp = (void __user *)arg;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005979 struct hdspm *hdspm = hw->private_data;
Takashi Iwai98274f02005-11-17 14:52:34 +01005980 struct hdspm_mixer_ioctl mixer;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005981 struct hdspm_config info;
5982 struct hdspm_status status;
Takashi Iwai98274f02005-11-17 14:52:34 +01005983 struct hdspm_version hdspm_version;
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005984 struct hdspm_peak_rms *levels;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005985 struct hdspm_ltc ltc;
5986 unsigned int statusregister;
5987 long unsigned int s;
5988 int i = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005989
5990 switch (cmd) {
5991
Takashi Iwai763f3562005-06-03 11:25:34 +02005992 case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005993 levels = &hdspm->peak_rms;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005994 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005995 levels->input_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005996 readl(hdspm->iobase +
5997 HDSPM_MADI_INPUT_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005998 levels->playback_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005999 readl(hdspm->iobase +
6000 HDSPM_MADI_PLAYBACK_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006001 levels->output_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006002 readl(hdspm->iobase +
6003 HDSPM_MADI_OUTPUT_PEAK + i*4);
6004
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006005 levels->input_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006006 ((uint64_t) readl(hdspm->iobase +
6007 HDSPM_MADI_INPUT_RMS_H + i*4) << 32) |
6008 (uint64_t) readl(hdspm->iobase +
6009 HDSPM_MADI_INPUT_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006010 levels->playback_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006011 ((uint64_t)readl(hdspm->iobase +
6012 HDSPM_MADI_PLAYBACK_RMS_H+i*4) << 32) |
6013 (uint64_t)readl(hdspm->iobase +
6014 HDSPM_MADI_PLAYBACK_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006015 levels->output_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006016 ((uint64_t)readl(hdspm->iobase +
6017 HDSPM_MADI_OUTPUT_RMS_H + i*4) << 32) |
6018 (uint64_t)readl(hdspm->iobase +
6019 HDSPM_MADI_OUTPUT_RMS_L + i*4);
6020 }
6021
6022 if (hdspm->system_sample_rate > 96000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006023 levels->speed = qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006024 } else if (hdspm->system_sample_rate > 48000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006025 levels->speed = ds;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006026 } else {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006027 levels->speed = ss;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006028 }
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006029 levels->status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006030
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006031 s = copy_to_user(argp, levels, sizeof(struct hdspm_peak_rms));
Adrian Knoth0dca1792011-01-26 19:32:14 +01006032 if (0 != s) {
6033 /* snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu
6034 [Levels]\n", sizeof(struct hdspm_peak_rms), s);
6035 */
Takashi Iwai763f3562005-06-03 11:25:34 +02006036 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006037 }
6038 break;
6039
6040 case SNDRV_HDSPM_IOCTL_GET_LTC:
6041 ltc.ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
6042 i = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
6043 if (i & HDSPM_TCO1_LTC_Input_valid) {
6044 switch (i & (HDSPM_TCO1_LTC_Format_LSB |
6045 HDSPM_TCO1_LTC_Format_MSB)) {
6046 case 0:
6047 ltc.format = fps_24;
6048 break;
6049 case HDSPM_TCO1_LTC_Format_LSB:
6050 ltc.format = fps_25;
6051 break;
6052 case HDSPM_TCO1_LTC_Format_MSB:
6053 ltc.format = fps_2997;
6054 break;
6055 default:
6056 ltc.format = 30;
6057 break;
6058 }
6059 if (i & HDSPM_TCO1_set_drop_frame_flag) {
6060 ltc.frame = drop_frame;
6061 } else {
6062 ltc.frame = full_frame;
6063 }
6064 } else {
6065 ltc.format = format_invalid;
6066 ltc.frame = frame_invalid;
6067 }
6068 if (i & HDSPM_TCO1_Video_Input_Format_NTSC) {
6069 ltc.input_format = ntsc;
6070 } else if (i & HDSPM_TCO1_Video_Input_Format_PAL) {
6071 ltc.input_format = pal;
6072 } else {
6073 ltc.input_format = no_video;
6074 }
6075
6076 s = copy_to_user(argp, &ltc, sizeof(struct hdspm_ltc));
6077 if (0 != s) {
6078 /*
6079 snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */
Takashi Iwai763f3562005-06-03 11:25:34 +02006080 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006081 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006082
6083 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02006084
Adrian Knoth0dca1792011-01-26 19:32:14 +01006085 case SNDRV_HDSPM_IOCTL_GET_CONFIG:
Takashi Iwai763f3562005-06-03 11:25:34 +02006086
Adrian Knoth4ab69a22011-02-23 11:43:14 +01006087 memset(&info, 0, sizeof(info));
Takashi Iwai763f3562005-06-03 11:25:34 +02006088 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006089 info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
6090 info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006091
6092 info.system_sample_rate = hdspm->system_sample_rate;
6093 info.autosync_sample_rate =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006094 hdspm_external_sample_rate(hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006095 info.system_clock_mode = hdspm_system_clock_mode(hdspm);
6096 info.clock_source = hdspm_clock_source(hdspm);
6097 info.autosync_ref = hdspm_autosync_ref(hdspm);
6098 info.line_out = hdspm_line_out(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006099 info.passthru = 0;
6100 spin_unlock_irq(&hdspm->lock);
6101 if (copy_to_user((void __user *) arg, &info, sizeof(info)))
6102 return -EFAULT;
6103 break;
6104
Adrian Knoth0dca1792011-01-26 19:32:14 +01006105 case SNDRV_HDSPM_IOCTL_GET_STATUS:
6106 status.card_type = hdspm->io_type;
6107
6108 status.autosync_source = hdspm_autosync_ref(hdspm);
6109
6110 status.card_clock = 110069313433624ULL;
6111 status.master_period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
6112
6113 switch (hdspm->io_type) {
6114 case MADI:
6115 case MADIface:
6116 status.card_specific.madi.sync_wc =
6117 hdspm_wc_sync_check(hdspm);
6118 status.card_specific.madi.sync_madi =
6119 hdspm_madi_sync_check(hdspm);
6120 status.card_specific.madi.sync_tco =
6121 hdspm_tco_sync_check(hdspm);
6122 status.card_specific.madi.sync_in =
6123 hdspm_sync_in_sync_check(hdspm);
6124
6125 statusregister =
6126 hdspm_read(hdspm, HDSPM_statusRegister);
6127 status.card_specific.madi.madi_input =
6128 (statusregister & HDSPM_AB_int) ? 1 : 0;
6129 status.card_specific.madi.channel_format =
6130 (statusregister & HDSPM_TX_64ch) ? 1 : 0;
6131 /* TODO: Mac driver sets it when f_s>48kHz */
6132 status.card_specific.madi.frame_format = 0;
6133
6134 default:
6135 break;
6136 }
6137
6138 if (copy_to_user((void __user *) arg, &status, sizeof(status)))
6139 return -EFAULT;
6140
6141
6142 break;
6143
Takashi Iwai763f3562005-06-03 11:25:34 +02006144 case SNDRV_HDSPM_IOCTL_GET_VERSION:
Adrian Knoth0dca1792011-01-26 19:32:14 +01006145 hdspm_version.card_type = hdspm->io_type;
6146 strncpy(hdspm_version.cardname, hdspm->card_name,
6147 sizeof(hdspm_version.cardname));
6148 hdspm_version.serial = (hdspm_read(hdspm,
6149 HDSPM_midiStatusIn0)>>8) & 0xFFFFFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02006150 hdspm_version.firmware_rev = hdspm->firmware_rev;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006151 hdspm_version.addons = 0;
6152 if (hdspm->tco)
6153 hdspm_version.addons |= HDSPM_ADDON_TCO;
6154
Takashi Iwai763f3562005-06-03 11:25:34 +02006155 if (copy_to_user((void __user *) arg, &hdspm_version,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006156 sizeof(hdspm_version)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006157 return -EFAULT;
6158 break;
6159
6160 case SNDRV_HDSPM_IOCTL_GET_MIXER:
6161 if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer)))
6162 return -EFAULT;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006163 if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006164 sizeof(struct hdspm_mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006165 return -EFAULT;
6166 break;
6167
6168 default:
6169 return -EINVAL;
6170 }
6171 return 0;
6172}
6173
Takashi Iwai98274f02005-11-17 14:52:34 +01006174static struct snd_pcm_ops snd_hdspm_playback_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006175 .open = snd_hdspm_playback_open,
6176 .close = snd_hdspm_playback_release,
6177 .ioctl = snd_hdspm_ioctl,
6178 .hw_params = snd_hdspm_hw_params,
6179 .hw_free = snd_hdspm_hw_free,
6180 .prepare = snd_hdspm_prepare,
6181 .trigger = snd_hdspm_trigger,
6182 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006183 .page = snd_pcm_sgbuf_ops_page,
6184};
6185
Takashi Iwai98274f02005-11-17 14:52:34 +01006186static struct snd_pcm_ops snd_hdspm_capture_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006187 .open = snd_hdspm_capture_open,
6188 .close = snd_hdspm_capture_release,
6189 .ioctl = snd_hdspm_ioctl,
6190 .hw_params = snd_hdspm_hw_params,
6191 .hw_free = snd_hdspm_hw_free,
6192 .prepare = snd_hdspm_prepare,
6193 .trigger = snd_hdspm_trigger,
6194 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006195 .page = snd_pcm_sgbuf_ops_page,
6196};
6197
Takashi Iwai98274f02005-11-17 14:52:34 +01006198static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
6199 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006200{
Takashi Iwai98274f02005-11-17 14:52:34 +01006201 struct snd_hwdep *hw;
Takashi Iwai763f3562005-06-03 11:25:34 +02006202 int err;
6203
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006204 err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw);
6205 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006206 return err;
6207
6208 hdspm->hwdep = hw;
6209 hw->private_data = hdspm;
6210 strcpy(hw->name, "HDSPM hwdep interface");
6211
Adrian Knoth0dca1792011-01-26 19:32:14 +01006212 hw->ops.open = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006213 hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006214 hw->ops.release = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006215
6216 return 0;
6217}
6218
6219
6220/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01006221 memory interface
Takashi Iwai763f3562005-06-03 11:25:34 +02006222 ------------------------------------------------------------*/
Adrian Knoth0dca1792011-01-26 19:32:14 +01006223static int __devinit snd_hdspm_preallocate_memory(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006224{
6225 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01006226 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006227 size_t wanted;
6228
6229 pcm = hdspm->pcm;
6230
Remy Bruno3cee5a62006-10-16 12:46:32 +02006231 wanted = HDSPM_DMA_AREA_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02006232
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006233 err =
Takashi Iwai763f3562005-06-03 11:25:34 +02006234 snd_pcm_lib_preallocate_pages_for_all(pcm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006235 SNDRV_DMA_TYPE_DEV_SG,
Takashi Iwai763f3562005-06-03 11:25:34 +02006236 snd_dma_pci_data(hdspm->pci),
6237 wanted,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006238 wanted);
6239 if (err < 0) {
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006240 snd_printdd("Could not preallocate %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006241
6242 return err;
6243 } else
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006244 snd_printdd(" Preallocated %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006245
6246 return 0;
6247}
6248
Adrian Knoth0dca1792011-01-26 19:32:14 +01006249
6250static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +02006251 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02006252 unsigned int reg, int channels)
6253{
6254 int i;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006255
6256 /* continuous memory segment */
Takashi Iwai763f3562005-06-03 11:25:34 +02006257 for (i = 0; i < (channels * 16); i++)
6258 hdspm_write(hdspm, reg + 4 * i,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006259 snd_pcm_sgbuf_get_addr(substream, 4096 * i));
Takashi Iwai763f3562005-06-03 11:25:34 +02006260}
6261
Adrian Knoth0dca1792011-01-26 19:32:14 +01006262
Takashi Iwai763f3562005-06-03 11:25:34 +02006263/* ------------- ALSA Devices ---------------------------- */
Takashi Iwai98274f02005-11-17 14:52:34 +01006264static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006265 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006266{
Takashi Iwai98274f02005-11-17 14:52:34 +01006267 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006268 int err;
6269
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006270 err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm);
6271 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006272 return err;
6273
6274 hdspm->pcm = pcm;
6275 pcm->private_data = hdspm;
6276 strcpy(pcm->name, hdspm->card_name);
6277
6278 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
6279 &snd_hdspm_playback_ops);
6280 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
6281 &snd_hdspm_capture_ops);
6282
6283 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
6284
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006285 err = snd_hdspm_preallocate_memory(hdspm);
6286 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006287 return err;
6288
6289 return 0;
6290}
6291
Takashi Iwai98274f02005-11-17 14:52:34 +01006292static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006293{
Adrian Knoth7c7102b2011-02-28 15:14:50 +01006294 int i;
6295
6296 for (i = 0; i < hdspm->midiPorts; i++)
6297 snd_hdspm_flush_midi_input(hdspm, i);
Takashi Iwai763f3562005-06-03 11:25:34 +02006298}
6299
Takashi Iwai98274f02005-11-17 14:52:34 +01006300static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
6301 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006302{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006303 int err, i;
Takashi Iwai763f3562005-06-03 11:25:34 +02006304
6305 snd_printdd("Create card...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006306 err = snd_hdspm_create_pcm(card, hdspm);
6307 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006308 return err;
6309
Adrian Knoth0dca1792011-01-26 19:32:14 +01006310 i = 0;
6311 while (i < hdspm->midiPorts) {
6312 err = snd_hdspm_create_midi(card, hdspm, i);
6313 if (err < 0) {
6314 return err;
6315 }
6316 i++;
6317 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006318
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006319 err = snd_hdspm_create_controls(card, hdspm);
6320 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006321 return err;
6322
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006323 err = snd_hdspm_create_hwdep(card, hdspm);
6324 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006325 return err;
6326
6327 snd_printdd("proc init...\n");
6328 snd_hdspm_proc_init(hdspm);
6329
6330 hdspm->system_sample_rate = -1;
6331 hdspm->last_external_sample_rate = -1;
6332 hdspm->last_internal_sample_rate = -1;
6333 hdspm->playback_pid = -1;
6334 hdspm->capture_pid = -1;
6335 hdspm->capture_substream = NULL;
6336 hdspm->playback_substream = NULL;
6337
6338 snd_printdd("Set defaults...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006339 err = snd_hdspm_set_defaults(hdspm);
6340 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006341 return err;
6342
6343 snd_printdd("Update mixer controls...\n");
6344 hdspm_update_simple_mixer_controls(hdspm);
6345
6346 snd_printdd("Initializeing complete ???\n");
6347
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006348 err = snd_card_register(card);
6349 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006350 snd_printk(KERN_ERR "HDSPM: error registering card\n");
6351 return err;
6352 }
6353
6354 snd_printdd("... yes now\n");
6355
6356 return 0;
6357}
6358
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006359static int __devinit snd_hdspm_create(struct snd_card *card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006360 struct hdspm *hdspm) {
6361
Takashi Iwai763f3562005-06-03 11:25:34 +02006362 struct pci_dev *pci = hdspm->pci;
6363 int err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006364 unsigned long io_extent;
6365
6366 hdspm->irq = -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02006367 hdspm->card = card;
6368
6369 spin_lock_init(&hdspm->lock);
6370
Takashi Iwai763f3562005-06-03 11:25:34 +02006371 pci_read_config_word(hdspm->pci,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006372 PCI_CLASS_REVISION, &hdspm->firmware_rev);
Remy Bruno3cee5a62006-10-16 12:46:32 +02006373
Takashi Iwai763f3562005-06-03 11:25:34 +02006374 strcpy(card->mixername, "Xilinx FPGA");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006375 strcpy(card->driver, "HDSPM");
6376
6377 switch (hdspm->firmware_rev) {
6378 case HDSPM_MADI_REV:
6379 hdspm->io_type = MADI;
6380 hdspm->card_name = "RME MADI";
6381 hdspm->midiPorts = 3;
6382 break;
6383 case HDSPM_RAYDAT_REV:
6384 hdspm->io_type = RayDAT;
6385 hdspm->card_name = "RME RayDAT";
6386 hdspm->midiPorts = 2;
6387 break;
6388 case HDSPM_AIO_REV:
6389 hdspm->io_type = AIO;
6390 hdspm->card_name = "RME AIO";
6391 hdspm->midiPorts = 1;
6392 break;
6393 case HDSPM_MADIFACE_REV:
6394 hdspm->io_type = MADIface;
6395 hdspm->card_name = "RME MADIface";
6396 hdspm->midiPorts = 1;
6397 break;
6398 case HDSPM_AES_REV:
Adrian Knoth526ea862011-02-28 15:14:48 +01006399 case HDSPM_AES32_REV:
Adrian Knoth0dca1792011-01-26 19:32:14 +01006400 hdspm->io_type = AES32;
6401 hdspm->card_name = "RME AES32";
6402 hdspm->midiPorts = 2;
6403 break;
Adrian Knoth5027f342011-02-28 15:14:49 +01006404 default:
6405 snd_printk(KERN_ERR "HDSPM: unknown firmware revision %x\n",
6406 hdspm->firmware_rev);
6407 return -ENODEV;
Remy Bruno3cee5a62006-10-16 12:46:32 +02006408 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006409
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006410 err = pci_enable_device(pci);
6411 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006412 return err;
6413
6414 pci_set_master(hdspm->pci);
6415
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006416 err = pci_request_regions(pci, "hdspm");
6417 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006418 return err;
6419
6420 hdspm->port = pci_resource_start(pci, 0);
6421 io_extent = pci_resource_len(pci, 0);
6422
6423 snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006424 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006425
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006426 hdspm->iobase = ioremap_nocache(hdspm->port, io_extent);
6427 if (!hdspm->iobase) {
6428 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006429 "unable to remap region 0x%lx-0x%lx\n",
6430 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006431 return -EBUSY;
6432 }
6433 snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006434 (unsigned long)hdspm->iobase, hdspm->port,
6435 hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006436
6437 if (request_irq(pci->irq, snd_hdspm_interrupt,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006438 IRQF_SHARED, "hdspm", hdspm)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006439 snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
6440 return -EBUSY;
6441 }
6442
6443 snd_printdd("use IRQ %d\n", pci->irq);
6444
6445 hdspm->irq = pci->irq;
Takashi Iwai763f3562005-06-03 11:25:34 +02006446
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006447 snd_printdd("kmalloc Mixer memory of %zd Bytes\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006448 sizeof(struct hdspm_mixer));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006449 hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL);
6450 if (!hdspm->mixer) {
6451 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006452 "unable to kmalloc Mixer memory of %d Bytes\n",
6453 (int)sizeof(struct hdspm_mixer));
Takashi Iwai763f3562005-06-03 11:25:34 +02006454 return err;
6455 }
6456
Adrian Knoth0dca1792011-01-26 19:32:14 +01006457 hdspm->port_names_in = NULL;
6458 hdspm->port_names_out = NULL;
6459
6460 switch (hdspm->io_type) {
6461 case AES32:
Adrian Knothd2d10a22011-02-28 15:14:47 +01006462 hdspm->ss_in_channels = hdspm->ss_out_channels = AES32_CHANNELS;
6463 hdspm->ds_in_channels = hdspm->ds_out_channels = AES32_CHANNELS;
6464 hdspm->qs_in_channels = hdspm->qs_out_channels = AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006465
6466 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6467 channel_map_aes32;
6468 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6469 channel_map_aes32;
6470 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6471 channel_map_aes32;
6472 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6473 texts_ports_aes32;
6474 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6475 texts_ports_aes32;
6476 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6477 texts_ports_aes32;
6478
Adrian Knothd2d10a22011-02-28 15:14:47 +01006479 hdspm->max_channels_out = hdspm->max_channels_in =
6480 AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006481 hdspm->port_names_in = hdspm->port_names_out =
6482 texts_ports_aes32;
6483 hdspm->channel_map_in = hdspm->channel_map_out =
6484 channel_map_aes32;
6485
Adrian Knoth0dca1792011-01-26 19:32:14 +01006486 break;
6487
6488 case MADI:
6489 case MADIface:
6490 hdspm->ss_in_channels = hdspm->ss_out_channels =
6491 MADI_SS_CHANNELS;
6492 hdspm->ds_in_channels = hdspm->ds_out_channels =
6493 MADI_DS_CHANNELS;
6494 hdspm->qs_in_channels = hdspm->qs_out_channels =
6495 MADI_QS_CHANNELS;
6496
6497 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6498 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006499 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006500 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006501 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006502 channel_map_unity_ss;
6503
6504 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6505 texts_ports_madi;
6506 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6507 texts_ports_madi;
6508 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6509 texts_ports_madi;
6510 break;
6511
6512 case AIO:
6513 if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) {
6514 snd_printk(KERN_INFO "HDSPM: AEB input board found, but not supported\n");
6515 }
6516
6517 hdspm->ss_in_channels = AIO_IN_SS_CHANNELS;
6518 hdspm->ds_in_channels = AIO_IN_DS_CHANNELS;
6519 hdspm->qs_in_channels = AIO_IN_QS_CHANNELS;
6520 hdspm->ss_out_channels = AIO_OUT_SS_CHANNELS;
6521 hdspm->ds_out_channels = AIO_OUT_DS_CHANNELS;
6522 hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS;
6523
6524 hdspm->channel_map_out_ss = channel_map_aio_out_ss;
6525 hdspm->channel_map_out_ds = channel_map_aio_out_ds;
6526 hdspm->channel_map_out_qs = channel_map_aio_out_qs;
6527
6528 hdspm->channel_map_in_ss = channel_map_aio_in_ss;
6529 hdspm->channel_map_in_ds = channel_map_aio_in_ds;
6530 hdspm->channel_map_in_qs = channel_map_aio_in_qs;
6531
6532 hdspm->port_names_in_ss = texts_ports_aio_in_ss;
6533 hdspm->port_names_out_ss = texts_ports_aio_out_ss;
6534 hdspm->port_names_in_ds = texts_ports_aio_in_ds;
6535 hdspm->port_names_out_ds = texts_ports_aio_out_ds;
6536 hdspm->port_names_in_qs = texts_ports_aio_in_qs;
6537 hdspm->port_names_out_qs = texts_ports_aio_out_qs;
6538
6539 break;
6540
6541 case RayDAT:
6542 hdspm->ss_in_channels = hdspm->ss_out_channels =
6543 RAYDAT_SS_CHANNELS;
6544 hdspm->ds_in_channels = hdspm->ds_out_channels =
6545 RAYDAT_DS_CHANNELS;
6546 hdspm->qs_in_channels = hdspm->qs_out_channels =
6547 RAYDAT_QS_CHANNELS;
6548
6549 hdspm->max_channels_in = RAYDAT_SS_CHANNELS;
6550 hdspm->max_channels_out = RAYDAT_SS_CHANNELS;
6551
6552 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6553 channel_map_raydat_ss;
6554 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6555 channel_map_raydat_ds;
6556 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6557 channel_map_raydat_qs;
6558 hdspm->channel_map_in = hdspm->channel_map_out =
6559 channel_map_raydat_ss;
6560
6561 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6562 texts_ports_raydat_ss;
6563 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6564 texts_ports_raydat_ds;
6565 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6566 texts_ports_raydat_qs;
6567
6568
6569 break;
6570
6571 }
6572
6573 /* TCO detection */
6574 switch (hdspm->io_type) {
6575 case AIO:
6576 case RayDAT:
6577 if (hdspm_read(hdspm, HDSPM_statusRegister2) &
6578 HDSPM_s2_tco_detect) {
6579 hdspm->midiPorts++;
6580 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6581 GFP_KERNEL);
6582 if (NULL != hdspm->tco) {
6583 hdspm_tco_write(hdspm);
6584 }
6585 snd_printk(KERN_INFO "HDSPM: AIO/RayDAT TCO module found\n");
6586 } else {
6587 hdspm->tco = NULL;
6588 }
6589 break;
6590
6591 case MADI:
6592 if (hdspm_read(hdspm, HDSPM_statusRegister) & HDSPM_tco_detect) {
6593 hdspm->midiPorts++;
6594 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6595 GFP_KERNEL);
6596 if (NULL != hdspm->tco) {
6597 hdspm_tco_write(hdspm);
6598 }
6599 snd_printk(KERN_INFO "HDSPM: MADI TCO module found\n");
6600 } else {
6601 hdspm->tco = NULL;
6602 }
6603 break;
6604
6605 default:
6606 hdspm->tco = NULL;
6607 }
6608
6609 /* texts */
6610 switch (hdspm->io_type) {
6611 case AES32:
6612 if (hdspm->tco) {
6613 hdspm->texts_autosync = texts_autosync_aes_tco;
6614 hdspm->texts_autosync_items = 10;
6615 } else {
6616 hdspm->texts_autosync = texts_autosync_aes;
6617 hdspm->texts_autosync_items = 9;
6618 }
6619 break;
6620
6621 case MADI:
6622 if (hdspm->tco) {
6623 hdspm->texts_autosync = texts_autosync_madi_tco;
6624 hdspm->texts_autosync_items = 4;
6625 } else {
6626 hdspm->texts_autosync = texts_autosync_madi;
6627 hdspm->texts_autosync_items = 3;
6628 }
6629 break;
6630
6631 case MADIface:
6632
6633 break;
6634
6635 case RayDAT:
6636 if (hdspm->tco) {
6637 hdspm->texts_autosync = texts_autosync_raydat_tco;
6638 hdspm->texts_autosync_items = 9;
6639 } else {
6640 hdspm->texts_autosync = texts_autosync_raydat;
6641 hdspm->texts_autosync_items = 8;
6642 }
6643 break;
6644
6645 case AIO:
6646 if (hdspm->tco) {
6647 hdspm->texts_autosync = texts_autosync_aio_tco;
6648 hdspm->texts_autosync_items = 6;
6649 } else {
6650 hdspm->texts_autosync = texts_autosync_aio;
6651 hdspm->texts_autosync_items = 5;
6652 }
6653 break;
6654
6655 }
6656
6657 tasklet_init(&hdspm->midi_tasklet,
6658 hdspm_midi_tasklet, (unsigned long) hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006659
6660 snd_printdd("create alsa devices.\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006661 err = snd_hdspm_create_alsa_devices(card, hdspm);
6662 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006663 return err;
6664
6665 snd_hdspm_initialize_midi_flush(hdspm);
6666
6667 return 0;
6668}
6669
Adrian Knoth0dca1792011-01-26 19:32:14 +01006670
Takashi Iwai98274f02005-11-17 14:52:34 +01006671static int snd_hdspm_free(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006672{
6673
6674 if (hdspm->port) {
6675
6676 /* stop th audio, and cancel all interrupts */
6677 hdspm->control_register &=
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006678 ~(HDSPM_Start | HDSPM_AudioInterruptEnable |
Adrian Knoth0dca1792011-01-26 19:32:14 +01006679 HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable |
6680 HDSPM_Midi2InterruptEnable | HDSPM_Midi3InterruptEnable);
Takashi Iwai763f3562005-06-03 11:25:34 +02006681 hdspm_write(hdspm, HDSPM_controlRegister,
6682 hdspm->control_register);
6683 }
6684
6685 if (hdspm->irq >= 0)
6686 free_irq(hdspm->irq, (void *) hdspm);
6687
Jesper Juhlfc584222005-10-24 15:11:28 +02006688 kfree(hdspm->mixer);
Takashi Iwai763f3562005-06-03 11:25:34 +02006689
6690 if (hdspm->iobase)
6691 iounmap(hdspm->iobase);
6692
Takashi Iwai763f3562005-06-03 11:25:34 +02006693 if (hdspm->port)
6694 pci_release_regions(hdspm->pci);
6695
6696 pci_disable_device(hdspm->pci);
6697 return 0;
6698}
6699
Adrian Knoth0dca1792011-01-26 19:32:14 +01006700
Takashi Iwai98274f02005-11-17 14:52:34 +01006701static void snd_hdspm_card_free(struct snd_card *card)
Takashi Iwai763f3562005-06-03 11:25:34 +02006702{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006703 struct hdspm *hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006704
6705 if (hdspm)
6706 snd_hdspm_free(hdspm);
6707}
6708
Adrian Knoth0dca1792011-01-26 19:32:14 +01006709
Takashi Iwai763f3562005-06-03 11:25:34 +02006710static int __devinit snd_hdspm_probe(struct pci_dev *pci,
6711 const struct pci_device_id *pci_id)
6712{
6713 static int dev;
Takashi Iwai98274f02005-11-17 14:52:34 +01006714 struct hdspm *hdspm;
6715 struct snd_card *card;
Takashi Iwai763f3562005-06-03 11:25:34 +02006716 int err;
6717
6718 if (dev >= SNDRV_CARDS)
6719 return -ENODEV;
6720 if (!enable[dev]) {
6721 dev++;
6722 return -ENOENT;
6723 }
6724
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006725 err = snd_card_create(index[dev], id[dev],
Adrian Knoth0dca1792011-01-26 19:32:14 +01006726 THIS_MODULE, sizeof(struct hdspm), &card);
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006727 if (err < 0)
6728 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006729
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006730 hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006731 card->private_free = snd_hdspm_card_free;
6732 hdspm->dev = dev;
6733 hdspm->pci = pci;
6734
Takashi Iwaic187c042007-02-19 15:27:33 +01006735 snd_card_set_dev(card, &pci->dev);
6736
Adrian Knoth0dca1792011-01-26 19:32:14 +01006737 err = snd_hdspm_create(card, hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006738 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006739 snd_card_free(card);
6740 return err;
6741 }
6742
Adrian Knoth0dca1792011-01-26 19:32:14 +01006743 if (hdspm->io_type != MADIface) {
6744 sprintf(card->shortname, "%s_%x",
6745 hdspm->card_name,
6746 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF);
6747 sprintf(card->longname, "%s S/N 0x%x at 0x%lx, irq %d",
6748 hdspm->card_name,
6749 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF,
6750 hdspm->port, hdspm->irq);
6751 } else {
6752 sprintf(card->shortname, "%s", hdspm->card_name);
6753 sprintf(card->longname, "%s at 0x%lx, irq %d",
6754 hdspm->card_name, hdspm->port, hdspm->irq);
6755 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006756
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006757 err = snd_card_register(card);
6758 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006759 snd_card_free(card);
6760 return err;
6761 }
6762
6763 pci_set_drvdata(pci, card);
6764
6765 dev++;
6766 return 0;
6767}
6768
6769static void __devexit snd_hdspm_remove(struct pci_dev *pci)
6770{
6771 snd_card_free(pci_get_drvdata(pci));
6772 pci_set_drvdata(pci, NULL);
6773}
6774
6775static struct pci_driver driver = {
6776 .name = "RME Hammerfall DSP MADI",
Takashi Iwai763f3562005-06-03 11:25:34 +02006777 .id_table = snd_hdspm_ids,
6778 .probe = snd_hdspm_probe,
6779 .remove = __devexit_p(snd_hdspm_remove),
6780};
6781
6782
6783static int __init alsa_card_hdspm_init(void)
6784{
6785 return pci_register_driver(&driver);
6786}
6787
6788static void __exit alsa_card_hdspm_exit(void)
6789{
6790 pci_unregister_driver(&driver);
6791}
6792
6793module_init(alsa_card_hdspm_init)
6794module_exit(alsa_card_hdspm_exit)