blob: bdd8c7742a1f37282c786fd9b485fd804945c3ec [file] [log] [blame]
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001/*
Takashi Iwai763f3562005-06-03 11:25:34 +02002 * ALSA driver for RME Hammerfall DSP MADI audio interface(s)
3 *
4 * Copyright (c) 2003 Winfried Ritsch (IEM)
5 * code based on hdsp.c Paul Davis
6 * Marcus Andersson
7 * Thomas Charbonnel
Remy Bruno3cee5a62006-10-16 12:46:32 +02008 * Modified 2006-06-01 for AES32 support by Remy Bruno
9 * <remy.bruno@trinnov.com>
Takashi Iwai763f3562005-06-03 11:25:34 +020010 *
Adrian Knoth0dca1792011-01-26 19:32:14 +010011 * Modified 2009-04-13 for proper metering by Florian Faber
12 * <faber@faberman.de>
13 *
14 * Modified 2009-04-14 for native float support by Florian Faber
15 * <faber@faberman.de>
16 *
17 * Modified 2009-04-26 fixed bug in rms metering by Florian Faber
18 * <faber@faberman.de>
19 *
20 * Modified 2009-04-30 added hw serial number support by Florian Faber
21 *
22 * Modified 2011-01-14 added S/PDIF input on RayDATs by Adrian Knoth
23 *
24 * Modified 2011-01-25 variable period sizes on RayDAT/AIO by Adrian Knoth
25 *
Takashi Iwai763f3562005-06-03 11:25:34 +020026 * This program is free software; you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License as published by
28 * the Free Software Foundation; either version 2 of the License, or
29 * (at your option) any later version.
30 *
31 * This program is distributed in the hope that it will be useful,
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 * GNU General Public License for more details.
35 *
36 * You should have received a copy of the GNU General Public License
37 * along with this program; if not, write to the Free Software
38 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 *
40 */
Takashi Iwai763f3562005-06-03 11:25:34 +020041#include <linux/init.h>
42#include <linux/delay.h>
43#include <linux/interrupt.h>
Paul Gortmaker65a77212011-07-15 13:13:37 -040044#include <linux/module.h>
Takashi Iwai763f3562005-06-03 11:25:34 +020045#include <linux/slab.h>
46#include <linux/pci.h>
Takashi Iwai3f7440a2009-06-05 17:40:04 +020047#include <linux/math64.h>
Takashi Iwai763f3562005-06-03 11:25:34 +020048#include <asm/io.h>
49
50#include <sound/core.h>
51#include <sound/control.h>
52#include <sound/pcm.h>
Adrian Knoth0dca1792011-01-26 19:32:14 +010053#include <sound/pcm_params.h>
Takashi Iwai763f3562005-06-03 11:25:34 +020054#include <sound/info.h>
55#include <sound/asoundef.h>
56#include <sound/rawmidi.h>
57#include <sound/hwdep.h>
58#include <sound/initval.h>
59
60#include <sound/hdspm.h>
61
62static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
63static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
Rusty Russella67ff6a2011-12-15 13:49:36 +103064static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
Takashi Iwai763f3562005-06-03 11:25:34 +020065
Takashi Iwai763f3562005-06-03 11:25:34 +020066module_param_array(index, int, NULL, 0444);
67MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");
68
69module_param_array(id, charp, NULL, 0444);
70MODULE_PARM_DESC(id, "ID string for RME HDSPM interface.");
71
72module_param_array(enable, bool, NULL, 0444);
73MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");
74
Takashi Iwai763f3562005-06-03 11:25:34 +020075
76MODULE_AUTHOR
Adrian Knoth0dca1792011-01-26 19:32:14 +010077(
78 "Winfried Ritsch <ritsch_AT_iem.at>, "
79 "Paul Davis <paul@linuxaudiosystems.com>, "
80 "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, "
81 "Remy Bruno <remy.bruno@trinnov.com>, "
82 "Florian Faber <faberman@linuxproaudio.org>, "
83 "Adrian Knoth <adi@drcomp.erfurt.thur.de>"
84);
Takashi Iwai763f3562005-06-03 11:25:34 +020085MODULE_DESCRIPTION("RME HDSPM");
86MODULE_LICENSE("GPL");
87MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
88
Adrian Knoth0dca1792011-01-26 19:32:14 +010089/* --- Write registers. ---
Takashi Iwai763f3562005-06-03 11:25:34 +020090 These are defined as byte-offsets from the iobase value. */
91
Adrian Knoth0dca1792011-01-26 19:32:14 +010092#define HDSPM_WR_SETTINGS 0
93#define HDSPM_outputBufferAddress 32
94#define HDSPM_inputBufferAddress 36
Takashi Iwai763f3562005-06-03 11:25:34 +020095#define HDSPM_controlRegister 64
96#define HDSPM_interruptConfirmation 96
97#define HDSPM_control2Reg 256 /* not in specs ???????? */
Remy Brunoffb2c3c2007-03-07 19:08:46 +010098#define HDSPM_freqReg 256 /* for AES32 */
Adrian Knoth0dca1792011-01-26 19:32:14 +010099#define HDSPM_midiDataOut0 352 /* just believe in old code */
100#define HDSPM_midiDataOut1 356
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100101#define HDSPM_eeprom_wr 384 /* for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200102
103/* DMA enable for 64 channels, only Bit 0 is relevant */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100104#define HDSPM_outputEnableBase 512 /* 512-767 input DMA */
Takashi Iwai763f3562005-06-03 11:25:34 +0200105#define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */
106
Adrian Knoth0dca1792011-01-26 19:32:14 +0100107/* 16 page addresses for each of the 64 channels DMA buffer in and out
Takashi Iwai763f3562005-06-03 11:25:34 +0200108 (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */
109#define HDSPM_pageAddressBufferOut 8192
110#define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4)
111
112#define HDSPM_MADI_mixerBase 32768 /* 32768-65535 for 2x64x64 Fader */
113
114#define HDSPM_MATRIX_MIXER_SIZE 8192 /* = 2*64*64 * 4 Byte => 32kB */
115
116/* --- Read registers. ---
117 These are defined as byte-offsets from the iobase value */
118#define HDSPM_statusRegister 0
Remy Bruno3cee5a62006-10-16 12:46:32 +0200119/*#define HDSPM_statusRegister2 96 */
120/* after RME Windows driver sources, status2 is 4-byte word # 48 = word at
121 * offset 192, for AES32 *and* MADI
122 * => need to check that offset 192 is working on MADI */
123#define HDSPM_statusRegister2 192
124#define HDSPM_timecodeRegister 128
Takashi Iwai763f3562005-06-03 11:25:34 +0200125
Adrian Knoth0dca1792011-01-26 19:32:14 +0100126/* AIO, RayDAT */
127#define HDSPM_RD_STATUS_0 0
128#define HDSPM_RD_STATUS_1 64
129#define HDSPM_RD_STATUS_2 128
130#define HDSPM_RD_STATUS_3 192
131
132#define HDSPM_RD_TCO 256
133#define HDSPM_RD_PLL_FREQ 512
134#define HDSPM_WR_TCO 128
135
136#define HDSPM_TCO1_TCO_lock 0x00000001
137#define HDSPM_TCO1_WCK_Input_Range_LSB 0x00000002
138#define HDSPM_TCO1_WCK_Input_Range_MSB 0x00000004
139#define HDSPM_TCO1_LTC_Input_valid 0x00000008
140#define HDSPM_TCO1_WCK_Input_valid 0x00000010
141#define HDSPM_TCO1_Video_Input_Format_NTSC 0x00000020
142#define HDSPM_TCO1_Video_Input_Format_PAL 0x00000040
143
144#define HDSPM_TCO1_set_TC 0x00000100
145#define HDSPM_TCO1_set_drop_frame_flag 0x00000200
146#define HDSPM_TCO1_LTC_Format_LSB 0x00000400
147#define HDSPM_TCO1_LTC_Format_MSB 0x00000800
148
149#define HDSPM_TCO2_TC_run 0x00010000
150#define HDSPM_TCO2_WCK_IO_ratio_LSB 0x00020000
151#define HDSPM_TCO2_WCK_IO_ratio_MSB 0x00040000
152#define HDSPM_TCO2_set_num_drop_frames_LSB 0x00080000
153#define HDSPM_TCO2_set_num_drop_frames_MSB 0x00100000
154#define HDSPM_TCO2_set_jam_sync 0x00200000
155#define HDSPM_TCO2_set_flywheel 0x00400000
156
157#define HDSPM_TCO2_set_01_4 0x01000000
158#define HDSPM_TCO2_set_pull_down 0x02000000
159#define HDSPM_TCO2_set_pull_up 0x04000000
160#define HDSPM_TCO2_set_freq 0x08000000
161#define HDSPM_TCO2_set_term_75R 0x10000000
162#define HDSPM_TCO2_set_input_LSB 0x20000000
163#define HDSPM_TCO2_set_input_MSB 0x40000000
164#define HDSPM_TCO2_set_freq_from_app 0x80000000
165
166
167#define HDSPM_midiDataOut0 352
168#define HDSPM_midiDataOut1 356
169#define HDSPM_midiDataOut2 368
170
Takashi Iwai763f3562005-06-03 11:25:34 +0200171#define HDSPM_midiDataIn0 360
172#define HDSPM_midiDataIn1 364
Adrian Knoth0dca1792011-01-26 19:32:14 +0100173#define HDSPM_midiDataIn2 372
174#define HDSPM_midiDataIn3 376
Takashi Iwai763f3562005-06-03 11:25:34 +0200175
176/* status is data bytes in MIDI-FIFO (0-128) */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100177#define HDSPM_midiStatusOut0 384
178#define HDSPM_midiStatusOut1 388
179#define HDSPM_midiStatusOut2 400
180
181#define HDSPM_midiStatusIn0 392
182#define HDSPM_midiStatusIn1 396
183#define HDSPM_midiStatusIn2 404
184#define HDSPM_midiStatusIn3 408
Takashi Iwai763f3562005-06-03 11:25:34 +0200185
186
187/* the meters are regular i/o-mapped registers, but offset
188 considerably from the rest. the peak registers are reset
Adrian Knoth0dca1792011-01-26 19:32:14 +0100189 when read; the least-significant 4 bits are full-scale counters;
Takashi Iwai763f3562005-06-03 11:25:34 +0200190 the actual peak value is in the most-significant 24 bits.
191*/
Adrian Knoth0dca1792011-01-26 19:32:14 +0100192
193#define HDSPM_MADI_INPUT_PEAK 4096
194#define HDSPM_MADI_PLAYBACK_PEAK 4352
195#define HDSPM_MADI_OUTPUT_PEAK 4608
196
197#define HDSPM_MADI_INPUT_RMS_L 6144
198#define HDSPM_MADI_PLAYBACK_RMS_L 6400
199#define HDSPM_MADI_OUTPUT_RMS_L 6656
200
201#define HDSPM_MADI_INPUT_RMS_H 7168
202#define HDSPM_MADI_PLAYBACK_RMS_H 7424
203#define HDSPM_MADI_OUTPUT_RMS_H 7680
Takashi Iwai763f3562005-06-03 11:25:34 +0200204
205/* --- Control Register bits --------- */
206#define HDSPM_Start (1<<0) /* start engine */
207
208#define HDSPM_Latency0 (1<<1) /* buffer size = 2^n */
209#define HDSPM_Latency1 (1<<2) /* where n is defined */
210#define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */
211
Adrian Knoth0dca1792011-01-26 19:32:14 +0100212#define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Autosync */
213#define HDSPM_c0Master 0x1 /* Master clock bit in settings
214 register [RayDAT, AIO] */
Takashi Iwai763f3562005-06-03 11:25:34 +0200215
216#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */
217
218#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */
219#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */
220#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200221#define HDSPM_QuadSpeed (1<<31) /* quad speed bit */
Takashi Iwai763f3562005-06-03 11:25:34 +0200222
Remy Bruno3cee5a62006-10-16 12:46:32 +0200223#define HDSPM_Professional (1<<9) /* Professional */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200224#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200225 56channelMODE=0 */ /* MADI ONLY*/
226#define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200227
Adrian Knoth0dca1792011-01-26 19:32:14 +0100228#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200229 0=off, 1=on */ /* MADI ONLY */
230#define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200231
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200232#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax
233 * -- MADI ONLY
234 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200235#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
236
Remy Bruno3cee5a62006-10-16 12:46:32 +0200237#define HDSPM_SyncRef2 (1<<13)
238#define HDSPM_SyncRef3 (1<<25)
Takashi Iwai763f3562005-06-03 11:25:34 +0200239
Remy Bruno3cee5a62006-10-16 12:46:32 +0200240#define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100241#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use
Takashi Iwai763f3562005-06-03 11:25:34 +0200242 AES additional bits in
243 lower 5 Audiodatabits ??? */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200244#define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */
245#define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200246
Adrian Knoth0dca1792011-01-26 19:32:14 +0100247#define HDSPM_Midi0InterruptEnable 0x0400000
248#define HDSPM_Midi1InterruptEnable 0x0800000
249#define HDSPM_Midi2InterruptEnable 0x0200000
250#define HDSPM_Midi3InterruptEnable 0x4000000
Takashi Iwai763f3562005-06-03 11:25:34 +0200251
252#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100253#define HDSPe_FLOAT_FORMAT 0x2000000
Takashi Iwai763f3562005-06-03 11:25:34 +0200254
Remy Bruno3cee5a62006-10-16 12:46:32 +0200255#define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */
256#define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */
257#define HDSPM_QS_QuadWire (1<<28) /* AES32 ONLY */
258
259#define HDSPM_wclk_sel (1<<30)
Takashi Iwai763f3562005-06-03 11:25:34 +0200260
Adrian Knoth384f7782013-07-05 11:27:53 +0200261/* additional control register bits for AIO*/
262#define HDSPM_c0_Wck48 0x20 /* also RayDAT */
263#define HDSPM_c0_Input0 0x1000
264#define HDSPM_c0_Input1 0x2000
265#define HDSPM_c0_Spdif_Opt 0x4000
266#define HDSPM_c0_Pro 0x8000
267#define HDSPM_c0_clr_tms 0x10000
268#define HDSPM_c0_AEB1 0x20000
269#define HDSPM_c0_AEB2 0x40000
270#define HDSPM_c0_LineOut 0x80000
271#define HDSPM_c0_AD_GAIN0 0x100000
272#define HDSPM_c0_AD_GAIN1 0x200000
273#define HDSPM_c0_DA_GAIN0 0x400000
274#define HDSPM_c0_DA_GAIN1 0x800000
275#define HDSPM_c0_PH_GAIN0 0x1000000
276#define HDSPM_c0_PH_GAIN1 0x2000000
277#define HDSPM_c0_Sym6db 0x4000000
278
279
Takashi Iwai763f3562005-06-03 11:25:34 +0200280/* --- bit helper defines */
281#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200282#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|\
283 HDSPM_DoubleSpeed|HDSPM_QuadSpeed)
Takashi Iwai763f3562005-06-03 11:25:34 +0200284#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1)
285#define HDSPM_InputOptical 0
286#define HDSPM_InputCoaxial (HDSPM_InputSelect0)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200287#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\
288 HDSPM_SyncRef2|HDSPM_SyncRef3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200289
Adrian Knoth0dca1792011-01-26 19:32:14 +0100290#define HDSPM_c0_SyncRef0 0x2
291#define HDSPM_c0_SyncRef1 0x4
292#define HDSPM_c0_SyncRef2 0x8
293#define HDSPM_c0_SyncRef3 0x10
294#define HDSPM_c0_SyncRefMask (HDSPM_c0_SyncRef0 | HDSPM_c0_SyncRef1 |\
295 HDSPM_c0_SyncRef2 | HDSPM_c0_SyncRef3)
296
297#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */
298#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */
299#define HDSPM_SYNC_FROM_TCO 2
300#define HDSPM_SYNC_FROM_SYNC_IN 3
Takashi Iwai763f3562005-06-03 11:25:34 +0200301
302#define HDSPM_Frequency32KHz HDSPM_Frequency0
303#define HDSPM_Frequency44_1KHz HDSPM_Frequency1
304#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0)
305#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0)
306#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200307#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|\
308 HDSPM_Frequency0)
Remy Bruno3cee5a62006-10-16 12:46:32 +0200309#define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0)
310#define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200311#define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\
312 HDSPM_Frequency0)
Takashi Iwai763f3562005-06-03 11:25:34 +0200313
Takashi Iwai763f3562005-06-03 11:25:34 +0200314
315/* Synccheck Status */
316#define HDSPM_SYNC_CHECK_NO_LOCK 0
317#define HDSPM_SYNC_CHECK_LOCK 1
318#define HDSPM_SYNC_CHECK_SYNC 2
319
320/* AutoSync References - used by "autosync_ref" control switch */
321#define HDSPM_AUTOSYNC_FROM_WORD 0
322#define HDSPM_AUTOSYNC_FROM_MADI 1
Adrian Knoth0dca1792011-01-26 19:32:14 +0100323#define HDSPM_AUTOSYNC_FROM_TCO 2
324#define HDSPM_AUTOSYNC_FROM_SYNC_IN 3
325#define HDSPM_AUTOSYNC_FROM_NONE 4
Takashi Iwai763f3562005-06-03 11:25:34 +0200326
327/* Possible sources of MADI input */
328#define HDSPM_OPTICAL 0 /* optical */
329#define HDSPM_COAXIAL 1 /* BNC */
330
331#define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask)
Adrian Knoth0dca1792011-01-26 19:32:14 +0100332#define hdspm_decode_latency(x) ((((x) & HDSPM_LatencyMask)>>1))
Takashi Iwai763f3562005-06-03 11:25:34 +0200333
334#define hdspm_encode_in(x) (((x)&0x3)<<14)
335#define hdspm_decode_in(x) (((x)>>14)&0x3)
336
337/* --- control2 register bits --- */
338#define HDSPM_TMS (1<<0)
339#define HDSPM_TCK (1<<1)
340#define HDSPM_TDI (1<<2)
341#define HDSPM_JTAG (1<<3)
342#define HDSPM_PWDN (1<<4)
343#define HDSPM_PROGRAM (1<<5)
344#define HDSPM_CONFIG_MODE_0 (1<<6)
345#define HDSPM_CONFIG_MODE_1 (1<<7)
346/*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/
347#define HDSPM_BIGENDIAN_MODE (1<<9)
348#define HDSPM_RD_MULTIPLE (1<<10)
349
Remy Bruno3cee5a62006-10-16 12:46:32 +0200350/* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200351 that do not conflict with specific bits for AES32 seem to be valid also
352 for the AES32
353 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200354#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200355#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn MODE=0 */
356#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1
357 * (like inp0)
358 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100359
Takashi Iwai763f3562005-06-03 11:25:34 +0200360#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100361#define HDSPM_madiSync (1<<18) /* MADI is in sync */
362
Adrian Knothb0bf5502013-07-05 11:28:05 +0200363#define HDSPM_tcoLockMadi 0x00000020 /* Optional TCO locked status for HDSPe MADI*/
364#define HDSPM_tcoSync 0x10000000 /* Optional TCO sync status for HDSPe MADI and AES32!*/
Adrian Knoth0dca1792011-01-26 19:32:14 +0100365
Adrian Knothb0bf5502013-07-05 11:28:05 +0200366#define HDSPM_syncInLock 0x00010000 /* Sync In lock status for HDSPe MADI! */
367#define HDSPM_syncInSync 0x00020000 /* Sync In sync status for HDSPe MADI! */
Takashi Iwai763f3562005-06-03 11:25:34 +0200368
369#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100370 /* since 64byte accurate, last 6 bits are not used */
Takashi Iwai763f3562005-06-03 11:25:34 +0200371
Adrian Knoth0dca1792011-01-26 19:32:14 +0100372
373
Takashi Iwai763f3562005-06-03 11:25:34 +0200374#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */
375
376#define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */
377#define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */
378#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */
379#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */
380
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200381#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with
382 * Interrupt
383 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100384#define HDSPM_tco_detect 0x08000000
Adrian Knothb0bf5502013-07-05 11:28:05 +0200385#define HDSPM_tcoLockAes 0x20000000 /* Optional TCO locked status for HDSPe AES */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100386
387#define HDSPM_s2_tco_detect 0x00000040
388#define HDSPM_s2_AEBO_D 0x00000080
389#define HDSPM_s2_AEBI_D 0x00000100
390
391
392#define HDSPM_midi0IRQPending 0x40000000
393#define HDSPM_midi1IRQPending 0x80000000
394#define HDSPM_midi2IRQPending 0x20000000
395#define HDSPM_midi2IRQPendingAES 0x00000020
396#define HDSPM_midi3IRQPending 0x00200000
Takashi Iwai763f3562005-06-03 11:25:34 +0200397
398/* --- status bit helpers */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200399#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\
400 HDSPM_madiFreq2|HDSPM_madiFreq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200401#define HDSPM_madiFreq32 (HDSPM_madiFreq0)
402#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1)
403#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1)
404#define HDSPM_madiFreq64 (HDSPM_madiFreq2)
405#define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2)
406#define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2)
407#define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2)
408#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
409#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0)
410
Remy Bruno3cee5a62006-10-16 12:46:32 +0200411/* Status2 Register bits */ /* MADI ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200412
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300413#define HDSPM_version0 (1<<0) /* not really defined but I guess */
Takashi Iwai763f3562005-06-03 11:25:34 +0200414#define HDSPM_version1 (1<<1) /* in former cards it was ??? */
415#define HDSPM_version2 (1<<2)
416
417#define HDSPM_wcLock (1<<3) /* Wordclock is detected and locked */
418#define HDSPM_wcSync (1<<4) /* Wordclock is in sync with systemclock */
419
420#define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */
421#define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */
Adrian Knotha8cd7142013-05-31 12:57:09 +0200422#define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, 111=128 */
423#define HDSPM_wc_freq3 0x800 /* 1000=176.4, 1001=192 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200424
Adrian Knoth0dca1792011-01-26 19:32:14 +0100425#define HDSPM_SyncRef0 0x10000 /* Sync Reference */
426#define HDSPM_SyncRef1 0x20000
427
428#define HDSPM_SelSyncRef0 (1<<8) /* AutoSync Source */
Takashi Iwai763f3562005-06-03 11:25:34 +0200429#define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */
430#define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */
431
432#define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync)
433
Adrian Knotha8cd7142013-05-31 12:57:09 +0200434#define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2|\
435 HDSPM_wc_freq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200436#define HDSPM_wcFreq32 (HDSPM_wc_freq0)
437#define HDSPM_wcFreq44_1 (HDSPM_wc_freq1)
438#define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1)
439#define HDSPM_wcFreq64 (HDSPM_wc_freq2)
440#define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2)
441#define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2)
Adrian Knotha8cd7142013-05-31 12:57:09 +0200442#define HDSPM_wcFreq128 (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2)
443#define HDSPM_wcFreq176_4 (HDSPM_wc_freq3)
444#define HDSPM_wcFreq192 (HDSPM_wc_freq0|HDSPM_wc_freq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200445
Adrian Knoth0dca1792011-01-26 19:32:14 +0100446#define HDSPM_status1_F_0 0x0400000
447#define HDSPM_status1_F_1 0x0800000
448#define HDSPM_status1_F_2 0x1000000
449#define HDSPM_status1_F_3 0x2000000
450#define HDSPM_status1_freqMask (HDSPM_status1_F_0|HDSPM_status1_F_1|HDSPM_status1_F_2|HDSPM_status1_F_3)
451
Takashi Iwai763f3562005-06-03 11:25:34 +0200452
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200453#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
454 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200455#define HDSPM_SelSyncRef_WORD 0
456#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0)
Adrian Knoth0dca1792011-01-26 19:32:14 +0100457#define HDSPM_SelSyncRef_TCO (HDSPM_SelSyncRef1)
458#define HDSPM_SelSyncRef_SyncIn (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200459#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
460 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200461
Remy Bruno3cee5a62006-10-16 12:46:32 +0200462/*
463 For AES32, bits for status, status2 and timecode are different
464*/
465/* status */
466#define HDSPM_AES32_wcLock 0x0200000
Andre Schramm56bde0f2013-01-09 14:40:18 +0100467#define HDSPM_AES32_wcSync 0x0100000
Remy Bruno3cee5a62006-10-16 12:46:32 +0200468#define HDSPM_AES32_wcFreq_bit 22
Adrian Knoth0dca1792011-01-26 19:32:14 +0100469/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function
Remy Bruno3cee5a62006-10-16 12:46:32 +0200470 HDSPM_bit2freq */
471#define HDSPM_AES32_syncref_bit 16
472/* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */
473
474#define HDSPM_AES32_AUTOSYNC_FROM_WORD 0
475#define HDSPM_AES32_AUTOSYNC_FROM_AES1 1
476#define HDSPM_AES32_AUTOSYNC_FROM_AES2 2
477#define HDSPM_AES32_AUTOSYNC_FROM_AES3 3
478#define HDSPM_AES32_AUTOSYNC_FROM_AES4 4
479#define HDSPM_AES32_AUTOSYNC_FROM_AES5 5
480#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6
481#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7
482#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8
Adrian Knothb0bf5502013-07-05 11:28:05 +0200483#define HDSPM_AES32_AUTOSYNC_FROM_TCO 9
484#define HDSPM_AES32_AUTOSYNC_FROM_SYNC_IN 10
485#define HDSPM_AES32_AUTOSYNC_FROM_NONE 11
Remy Bruno3cee5a62006-10-16 12:46:32 +0200486
487/* status2 */
488/* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */
489#define HDSPM_LockAES 0x80
490#define HDSPM_LockAES1 0x80
491#define HDSPM_LockAES2 0x40
492#define HDSPM_LockAES3 0x20
493#define HDSPM_LockAES4 0x10
494#define HDSPM_LockAES5 0x8
495#define HDSPM_LockAES6 0x4
496#define HDSPM_LockAES7 0x2
497#define HDSPM_LockAES8 0x1
498/*
499 Timecode
500 After windows driver sources, bits 4*i to 4*i+3 give the input frequency on
501 AES i+1
502 bits 3210
503 0001 32kHz
504 0010 44.1kHz
505 0011 48kHz
506 0100 64kHz
507 0101 88.2kHz
508 0110 96kHz
509 0111 128kHz
510 1000 176.4kHz
511 1001 192kHz
512 NB: Timecode register doesn't seem to work on AES32 card revision 230
513*/
514
Takashi Iwai763f3562005-06-03 11:25:34 +0200515/* Mixer Values */
516#define UNITY_GAIN 32768 /* = 65536/2 */
517#define MINUS_INFINITY_GAIN 0
518
Takashi Iwai763f3562005-06-03 11:25:34 +0200519/* Number of channels for different Speed Modes */
520#define MADI_SS_CHANNELS 64
521#define MADI_DS_CHANNELS 32
522#define MADI_QS_CHANNELS 16
523
Adrian Knoth0dca1792011-01-26 19:32:14 +0100524#define RAYDAT_SS_CHANNELS 36
525#define RAYDAT_DS_CHANNELS 20
526#define RAYDAT_QS_CHANNELS 12
527
528#define AIO_IN_SS_CHANNELS 14
529#define AIO_IN_DS_CHANNELS 10
530#define AIO_IN_QS_CHANNELS 8
531#define AIO_OUT_SS_CHANNELS 16
532#define AIO_OUT_DS_CHANNELS 12
533#define AIO_OUT_QS_CHANNELS 10
534
Adrian Knothd2d10a22011-02-28 15:14:47 +0100535#define AES32_CHANNELS 16
536
Takashi Iwai763f3562005-06-03 11:25:34 +0200537/* the size of a substream (1 mono data stream) */
538#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024)
539#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
540
541/* the size of the area we need to allocate for DMA transfers. the
542 size is the same regardless of the number of channels, and
Adrian Knoth0dca1792011-01-26 19:32:14 +0100543 also the latency to use.
Takashi Iwai763f3562005-06-03 11:25:34 +0200544 for one direction !!!
545*/
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100546#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
Takashi Iwai763f3562005-06-03 11:25:34 +0200547#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
548
Adrian Knoth0dca1792011-01-26 19:32:14 +0100549#define HDSPM_RAYDAT_REV 211
550#define HDSPM_AIO_REV 212
551#define HDSPM_MADIFACE_REV 213
Remy Bruno3cee5a62006-10-16 12:46:32 +0200552
Remy Bruno65345992007-08-31 12:21:08 +0200553/* speed factor modes */
554#define HDSPM_SPEED_SINGLE 0
555#define HDSPM_SPEED_DOUBLE 1
556#define HDSPM_SPEED_QUAD 2
Adrian Knoth0dca1792011-01-26 19:32:14 +0100557
Remy Bruno65345992007-08-31 12:21:08 +0200558/* names for speed modes */
559static char *hdspm_speed_names[] = { "single", "double", "quad" };
560
Adrian Knoth0dca1792011-01-26 19:32:14 +0100561static char *texts_autosync_aes_tco[] = { "Word Clock",
562 "AES1", "AES2", "AES3", "AES4",
563 "AES5", "AES6", "AES7", "AES8",
564 "TCO" };
565static char *texts_autosync_aes[] = { "Word Clock",
566 "AES1", "AES2", "AES3", "AES4",
567 "AES5", "AES6", "AES7", "AES8" };
568static char *texts_autosync_madi_tco[] = { "Word Clock",
569 "MADI", "TCO", "Sync In" };
570static char *texts_autosync_madi[] = { "Word Clock",
571 "MADI", "Sync In" };
572
573static char *texts_autosync_raydat_tco[] = {
574 "Word Clock",
575 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
576 "AES", "SPDIF", "TCO", "Sync In"
577};
578static char *texts_autosync_raydat[] = {
579 "Word Clock",
580 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
581 "AES", "SPDIF", "Sync In"
582};
583static char *texts_autosync_aio_tco[] = {
584 "Word Clock",
585 "ADAT", "AES", "SPDIF", "TCO", "Sync In"
586};
587static char *texts_autosync_aio[] = { "Word Clock",
588 "ADAT", "AES", "SPDIF", "Sync In" };
589
590static char *texts_freq[] = {
591 "No Lock",
592 "32 kHz",
593 "44.1 kHz",
594 "48 kHz",
595 "64 kHz",
596 "88.2 kHz",
597 "96 kHz",
598 "128 kHz",
599 "176.4 kHz",
600 "192 kHz"
601};
602
Adrian Knoth0dca1792011-01-26 19:32:14 +0100603static char *texts_ports_madi[] = {
604 "MADI.1", "MADI.2", "MADI.3", "MADI.4", "MADI.5", "MADI.6",
605 "MADI.7", "MADI.8", "MADI.9", "MADI.10", "MADI.11", "MADI.12",
606 "MADI.13", "MADI.14", "MADI.15", "MADI.16", "MADI.17", "MADI.18",
607 "MADI.19", "MADI.20", "MADI.21", "MADI.22", "MADI.23", "MADI.24",
608 "MADI.25", "MADI.26", "MADI.27", "MADI.28", "MADI.29", "MADI.30",
609 "MADI.31", "MADI.32", "MADI.33", "MADI.34", "MADI.35", "MADI.36",
610 "MADI.37", "MADI.38", "MADI.39", "MADI.40", "MADI.41", "MADI.42",
611 "MADI.43", "MADI.44", "MADI.45", "MADI.46", "MADI.47", "MADI.48",
612 "MADI.49", "MADI.50", "MADI.51", "MADI.52", "MADI.53", "MADI.54",
613 "MADI.55", "MADI.56", "MADI.57", "MADI.58", "MADI.59", "MADI.60",
614 "MADI.61", "MADI.62", "MADI.63", "MADI.64",
615};
616
617
618static char *texts_ports_raydat_ss[] = {
619 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT1.5", "ADAT1.6",
620 "ADAT1.7", "ADAT1.8", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
621 "ADAT2.5", "ADAT2.6", "ADAT2.7", "ADAT2.8", "ADAT3.1", "ADAT3.2",
622 "ADAT3.3", "ADAT3.4", "ADAT3.5", "ADAT3.6", "ADAT3.7", "ADAT3.8",
623 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4", "ADAT4.5", "ADAT4.6",
624 "ADAT4.7", "ADAT4.8",
625 "AES.L", "AES.R",
626 "SPDIF.L", "SPDIF.R"
627};
628
629static char *texts_ports_raydat_ds[] = {
630 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4",
631 "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
632 "ADAT3.1", "ADAT3.2", "ADAT3.3", "ADAT3.4",
633 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4",
634 "AES.L", "AES.R",
635 "SPDIF.L", "SPDIF.R"
636};
637
638static char *texts_ports_raydat_qs[] = {
639 "ADAT1.1", "ADAT1.2",
640 "ADAT2.1", "ADAT2.2",
641 "ADAT3.1", "ADAT3.2",
642 "ADAT4.1", "ADAT4.2",
643 "AES.L", "AES.R",
644 "SPDIF.L", "SPDIF.R"
645};
646
647
648static char *texts_ports_aio_in_ss[] = {
649 "Analogue.L", "Analogue.R",
650 "AES.L", "AES.R",
651 "SPDIF.L", "SPDIF.R",
652 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200653 "ADAT.7", "ADAT.8",
654 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100655};
656
657static char *texts_ports_aio_out_ss[] = {
658 "Analogue.L", "Analogue.R",
659 "AES.L", "AES.R",
660 "SPDIF.L", "SPDIF.R",
661 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
662 "ADAT.7", "ADAT.8",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200663 "Phone.L", "Phone.R",
664 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100665};
666
667static char *texts_ports_aio_in_ds[] = {
668 "Analogue.L", "Analogue.R",
669 "AES.L", "AES.R",
670 "SPDIF.L", "SPDIF.R",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200671 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
672 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100673};
674
675static char *texts_ports_aio_out_ds[] = {
676 "Analogue.L", "Analogue.R",
677 "AES.L", "AES.R",
678 "SPDIF.L", "SPDIF.R",
679 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200680 "Phone.L", "Phone.R",
681 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100682};
683
684static char *texts_ports_aio_in_qs[] = {
685 "Analogue.L", "Analogue.R",
686 "AES.L", "AES.R",
687 "SPDIF.L", "SPDIF.R",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200688 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
689 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100690};
691
692static char *texts_ports_aio_out_qs[] = {
693 "Analogue.L", "Analogue.R",
694 "AES.L", "AES.R",
695 "SPDIF.L", "SPDIF.R",
696 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200697 "Phone.L", "Phone.R",
698 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100699};
700
Adrian Knoth432d2502011-02-23 11:43:08 +0100701static char *texts_ports_aes32[] = {
702 "AES.1", "AES.2", "AES.3", "AES.4", "AES.5", "AES.6", "AES.7",
703 "AES.8", "AES.9.", "AES.10", "AES.11", "AES.12", "AES.13", "AES.14",
704 "AES.15", "AES.16"
705};
706
Adrian Knoth55a57602011-01-27 11:23:15 +0100707/* These tables map the ALSA channels 1..N to the channels that we
708 need to use in order to find the relevant channel buffer. RME
709 refers to this kind of mapping as between "the ADAT channel and
710 the DMA channel." We index it using the logical audio channel,
711 and the value is the DMA channel (i.e. channel buffer number)
712 where the data for that channel can be read/written from/to.
713*/
714
715static char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = {
716 0, 1, 2, 3, 4, 5, 6, 7,
717 8, 9, 10, 11, 12, 13, 14, 15,
718 16, 17, 18, 19, 20, 21, 22, 23,
719 24, 25, 26, 27, 28, 29, 30, 31,
720 32, 33, 34, 35, 36, 37, 38, 39,
721 40, 41, 42, 43, 44, 45, 46, 47,
722 48, 49, 50, 51, 52, 53, 54, 55,
723 56, 57, 58, 59, 60, 61, 62, 63
724};
725
Adrian Knoth55a57602011-01-27 11:23:15 +0100726static char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = {
727 4, 5, 6, 7, 8, 9, 10, 11, /* ADAT 1 */
728 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT 2 */
729 20, 21, 22, 23, 24, 25, 26, 27, /* ADAT 3 */
730 28, 29, 30, 31, 32, 33, 34, 35, /* 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};
738
739static char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = {
740 4, 5, 6, 7, /* ADAT 1 */
741 8, 9, 10, 11, /* ADAT 2 */
742 12, 13, 14, 15, /* ADAT 3 */
743 16, 17, 18, 19, /* ADAT 4 */
744 0, 1, /* AES */
745 2, 3, /* SPDIF */
746 -1, -1, -1, -1,
747 -1, -1, -1, -1, -1, -1, -1, -1,
748 -1, -1, -1, -1, -1, -1, -1, -1,
749 -1, -1, -1, -1, -1, -1, -1, -1,
750 -1, -1, -1, -1, -1, -1, -1, -1,
751 -1, -1, -1, -1, -1, -1, -1, -1,
752};
753
754static char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = {
755 4, 5, /* ADAT 1 */
756 6, 7, /* ADAT 2 */
757 8, 9, /* ADAT 3 */
758 10, 11, /* ADAT 4 */
759 0, 1, /* AES */
760 2, 3, /* SPDIF */
761 -1, -1, -1, -1,
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_ss[HDSPM_MAX_CHANNELS] = {
771 0, 1, /* line in */
772 8, 9, /* aes in, */
773 10, 11, /* spdif in */
774 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT in */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200775 2, 3, 4, 5, /* AEB */
776 -1, -1, -1, -1, -1, -1,
Adrian Knoth55a57602011-01-27 11:23:15 +0100777 -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_ss[HDSPM_MAX_CHANNELS] = {
785 0, 1, /* line out */
786 8, 9, /* aes out */
787 10, 11, /* spdif out */
788 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT out */
789 6, 7, /* phone out */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200790 2, 3, 4, 5, /* AEB */
791 -1, -1, -1, -1,
Adrian Knoth55a57602011-01-27 11:23:15 +0100792 -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_ds[HDSPM_MAX_CHANNELS] = {
800 0, 1, /* line in */
801 8, 9, /* aes in */
802 10, 11, /* spdif in */
803 12, 14, 16, 18, /* adat in */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200804 2, 3, 4, 5, /* AEB */
805 -1, -1,
Adrian Knoth55a57602011-01-27 11:23:15 +0100806 -1, -1, -1, -1, -1, -1, -1, -1,
807 -1, -1, -1, -1, -1, -1, -1, -1,
808 -1, -1, -1, -1, -1, -1, -1, -1,
809 -1, -1, -1, -1, -1, -1, -1, -1,
810 -1, -1, -1, -1, -1, -1, -1, -1,
811 -1, -1, -1, -1, -1, -1, -1, -1
812};
813
814static char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = {
815 0, 1, /* line out */
816 8, 9, /* aes out */
817 10, 11, /* spdif out */
818 12, 14, 16, 18, /* adat out */
819 6, 7, /* phone out */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200820 2, 3, 4, 5, /* AEB */
Adrian Knoth55a57602011-01-27 11:23:15 +0100821 -1, -1, -1, -1, -1, -1, -1, -1,
822 -1, -1, -1, -1, -1, -1, -1, -1,
823 -1, -1, -1, -1, -1, -1, -1, -1,
824 -1, -1, -1, -1, -1, -1, -1, -1,
825 -1, -1, -1, -1, -1, -1, -1, -1,
826 -1, -1, -1, -1, -1, -1, -1, -1
827};
828
829static char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = {
830 0, 1, /* line in */
831 8, 9, /* aes in */
832 10, 11, /* spdif in */
833 12, 16, /* adat in */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200834 2, 3, 4, 5, /* AEB */
835 -1, -1, -1, -1,
Adrian Knoth55a57602011-01-27 11:23:15 +0100836 -1, -1, -1, -1, -1, -1, -1, -1,
837 -1, -1, -1, -1, -1, -1, -1, -1,
838 -1, -1, -1, -1, -1, -1, -1, -1,
839 -1, -1, -1, -1, -1, -1, -1, -1,
840 -1, -1, -1, -1, -1, -1, -1, -1,
841 -1, -1, -1, -1, -1, -1, -1, -1
842};
843
844static char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = {
845 0, 1, /* line out */
846 8, 9, /* aes out */
847 10, 11, /* spdif out */
848 12, 16, /* adat out */
849 6, 7, /* phone out */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200850 2, 3, 4, 5, /* AEB */
851 -1, -1,
Adrian Knoth55a57602011-01-27 11:23:15 +0100852 -1, -1, -1, -1, -1, -1, -1, -1,
853 -1, -1, -1, -1, -1, -1, -1, -1,
854 -1, -1, -1, -1, -1, -1, -1, -1,
855 -1, -1, -1, -1, -1, -1, -1, -1,
856 -1, -1, -1, -1, -1, -1, -1, -1,
857 -1, -1, -1, -1, -1, -1, -1, -1
858};
859
Adrian Knoth432d2502011-02-23 11:43:08 +0100860static char channel_map_aes32[HDSPM_MAX_CHANNELS] = {
861 0, 1, 2, 3, 4, 5, 6, 7,
862 8, 9, 10, 11, 12, 13, 14, 15,
863 -1, -1, -1, -1, -1, -1, -1, -1,
864 -1, -1, -1, -1, -1, -1, -1, -1,
865 -1, -1, -1, -1, -1, -1, -1, -1,
866 -1, -1, -1, -1, -1, -1, -1, -1,
867 -1, -1, -1, -1, -1, -1, -1, -1,
868 -1, -1, -1, -1, -1, -1, -1, -1
869};
870
Takashi Iwai98274f02005-11-17 14:52:34 +0100871struct hdspm_midi {
872 struct hdspm *hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +0200873 int id;
Takashi Iwai98274f02005-11-17 14:52:34 +0100874 struct snd_rawmidi *rmidi;
875 struct snd_rawmidi_substream *input;
876 struct snd_rawmidi_substream *output;
Takashi Iwai763f3562005-06-03 11:25:34 +0200877 char istimer; /* timer in use */
878 struct timer_list timer;
879 spinlock_t lock;
880 int pending;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100881 int dataIn;
882 int statusIn;
883 int dataOut;
884 int statusOut;
885 int ie;
886 int irq;
887};
888
889struct hdspm_tco {
890 int input;
891 int framerate;
892 int wordclock;
893 int samplerate;
894 int pull;
895 int term; /* 0 = off, 1 = on */
Takashi Iwai763f3562005-06-03 11:25:34 +0200896};
897
Takashi Iwai98274f02005-11-17 14:52:34 +0100898struct hdspm {
Takashi Iwai763f3562005-06-03 11:25:34 +0200899 spinlock_t lock;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200900 /* only one playback and/or capture stream */
901 struct snd_pcm_substream *capture_substream;
902 struct snd_pcm_substream *playback_substream;
Takashi Iwai763f3562005-06-03 11:25:34 +0200903
904 char *card_name; /* for procinfo */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200905 unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
906
Adrian Knoth0dca1792011-01-26 19:32:14 +0100907 uint8_t io_type;
Takashi Iwai763f3562005-06-03 11:25:34 +0200908
Takashi Iwai763f3562005-06-03 11:25:34 +0200909 int monitor_outs; /* set up monitoring outs init flag */
910
911 u32 control_register; /* cached value */
912 u32 control2_register; /* cached value */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100913 u32 settings_register;
Takashi Iwai763f3562005-06-03 11:25:34 +0200914
Adrian Knoth0dca1792011-01-26 19:32:14 +0100915 struct hdspm_midi midi[4];
Takashi Iwai763f3562005-06-03 11:25:34 +0200916 struct tasklet_struct midi_tasklet;
917
918 size_t period_bytes;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100919 unsigned char ss_in_channels;
920 unsigned char ds_in_channels;
921 unsigned char qs_in_channels;
922 unsigned char ss_out_channels;
923 unsigned char ds_out_channels;
924 unsigned char qs_out_channels;
925
926 unsigned char max_channels_in;
927 unsigned char max_channels_out;
928
Takashi Iwai286bed02011-06-30 12:45:36 +0200929 signed char *channel_map_in;
930 signed char *channel_map_out;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100931
Takashi Iwai286bed02011-06-30 12:45:36 +0200932 signed char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs;
933 signed char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100934
935 char **port_names_in;
936 char **port_names_out;
937
938 char **port_names_in_ss, **port_names_in_ds, **port_names_in_qs;
939 char **port_names_out_ss, **port_names_out_ds, **port_names_out_qs;
Takashi Iwai763f3562005-06-03 11:25:34 +0200940
941 unsigned char *playback_buffer; /* suitably aligned address */
942 unsigned char *capture_buffer; /* suitably aligned address */
943
944 pid_t capture_pid; /* process id which uses capture */
945 pid_t playback_pid; /* process id which uses capture */
946 int running; /* running status */
947
948 int last_external_sample_rate; /* samplerate mystic ... */
949 int last_internal_sample_rate;
950 int system_sample_rate;
951
Takashi Iwai763f3562005-06-03 11:25:34 +0200952 int dev; /* Hardware vars... */
953 int irq;
954 unsigned long port;
955 void __iomem *iobase;
956
957 int irq_count; /* for debug */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100958 int midiPorts;
Takashi Iwai763f3562005-06-03 11:25:34 +0200959
Takashi Iwai98274f02005-11-17 14:52:34 +0100960 struct snd_card *card; /* one card */
961 struct snd_pcm *pcm; /* has one pcm */
962 struct snd_hwdep *hwdep; /* and a hwdep for additional ioctl */
Takashi Iwai763f3562005-06-03 11:25:34 +0200963 struct pci_dev *pci; /* and an pci info */
964
965 /* Mixer vars */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200966 /* fast alsa mixer */
967 struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS];
968 /* but input to much, so not used */
969 struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS];
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300970 /* full mixer accessible over mixer ioctl or hwdep-device */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200971 struct hdspm_mixer *mixer;
Takashi Iwai763f3562005-06-03 11:25:34 +0200972
Adrian Knoth0dca1792011-01-26 19:32:14 +0100973 struct hdspm_tco *tco; /* NULL if no TCO detected */
Takashi Iwai763f3562005-06-03 11:25:34 +0200974
Adrian Knoth0dca1792011-01-26 19:32:14 +0100975 char **texts_autosync;
976 int texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +0200977
Adrian Knoth0dca1792011-01-26 19:32:14 +0100978 cycles_t last_interrupt;
Jaroslav Kysela730a5862011-01-27 13:03:15 +0100979
Adrian Knoth7d53a632012-01-04 14:31:16 +0100980 unsigned int serial;
981
Jaroslav Kysela730a5862011-01-27 13:03:15 +0100982 struct hdspm_peak_rms peak_rms;
Takashi Iwai763f3562005-06-03 11:25:34 +0200983};
984
Takashi Iwai763f3562005-06-03 11:25:34 +0200985
Alexey Dobriyancebe41d2010-02-06 00:21:03 +0200986static DEFINE_PCI_DEVICE_TABLE(snd_hdspm_ids) = {
Takashi Iwai763f3562005-06-03 11:25:34 +0200987 {
988 .vendor = PCI_VENDOR_ID_XILINX,
989 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
990 .subvendor = PCI_ANY_ID,
991 .subdevice = PCI_ANY_ID,
992 .class = 0,
993 .class_mask = 0,
994 .driver_data = 0},
995 {0,}
996};
997
998MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
999
1000/* prototypes */
Bill Pembertone23e7a12012-12-06 12:35:10 -05001001static int snd_hdspm_create_alsa_devices(struct snd_card *card,
1002 struct hdspm *hdspm);
1003static int snd_hdspm_create_pcm(struct snd_card *card,
1004 struct hdspm *hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001005
Adrian Knoth0dca1792011-01-26 19:32:14 +01001006static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
Adrian Knoth3f7bf912013-03-10 00:37:21 +01001007static inline int hdspm_get_pll_freq(struct hdspm *hdspm);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001008static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
1009static int hdspm_autosync_ref(struct hdspm *hdspm);
Adrian Knoth34be7eb2013-07-05 11:27:56 +02001010static int hdspm_set_toggle_setting(struct hdspm *hdspm, u32 regmask, int out);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001011static int snd_hdspm_set_defaults(struct hdspm *hdspm);
Adrian Knoth21a164d2012-10-19 17:42:23 +02001012static int hdspm_system_clock_mode(struct hdspm *hdspm);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001013static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +02001014 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02001015 unsigned int reg, int channels);
1016
Remy Bruno3cee5a62006-10-16 12:46:32 +02001017static inline int HDSPM_bit2freq(int n)
1018{
Denys Vlasenko62cef822008-04-14 13:04:18 +02001019 static const int bit2freq_tab[] = {
1020 0, 32000, 44100, 48000, 64000, 88200,
Remy Bruno3cee5a62006-10-16 12:46:32 +02001021 96000, 128000, 176400, 192000 };
1022 if (n < 1 || n > 9)
1023 return 0;
1024 return bit2freq_tab[n];
1025}
1026
Adrian Knothb2ed6322013-07-05 11:27:54 +02001027static bool hdspm_is_raydat_or_aio(struct hdspm *hdspm)
1028{
1029 return ((AIO == hdspm->io_type) || (RayDAT == hdspm->io_type));
1030}
1031
1032
Adrian Knoth0dca1792011-01-26 19:32:14 +01001033/* Write/read to/from HDSPM with Adresses in Bytes
Takashi Iwai763f3562005-06-03 11:25:34 +02001034 not words but only 32Bit writes are allowed */
1035
Takashi Iwai98274f02005-11-17 14:52:34 +01001036static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
Takashi Iwai763f3562005-06-03 11:25:34 +02001037 unsigned int val)
1038{
1039 writel(val, hdspm->iobase + reg);
1040}
1041
Takashi Iwai98274f02005-11-17 14:52:34 +01001042static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
Takashi Iwai763f3562005-06-03 11:25:34 +02001043{
1044 return readl(hdspm->iobase + reg);
1045}
1046
Adrian Knoth0dca1792011-01-26 19:32:14 +01001047/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
1048 mixer is write only on hardware so we have to cache him for read
Takashi Iwai763f3562005-06-03 11:25:34 +02001049 each fader is a u32, but uses only the first 16 bit */
1050
Takashi Iwai98274f02005-11-17 14:52:34 +01001051static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001052 unsigned int in)
1053{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001054 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001055 return 0;
1056
1057 return hdspm->mixer->ch[chan].in[in];
1058}
1059
Takashi Iwai98274f02005-11-17 14:52:34 +01001060static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001061 unsigned int pb)
1062{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001063 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001064 return 0;
1065 return hdspm->mixer->ch[chan].pb[pb];
1066}
1067
Denys Vlasenko62cef822008-04-14 13:04:18 +02001068static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001069 unsigned int in, unsigned short data)
1070{
1071 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
1072 return -1;
1073
1074 hdspm_write(hdspm,
1075 HDSPM_MADI_mixerBase +
1076 ((in + 128 * chan) * sizeof(u32)),
1077 (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
1078 return 0;
1079}
1080
Denys Vlasenko62cef822008-04-14 13:04:18 +02001081static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001082 unsigned int pb, unsigned short data)
1083{
1084 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
1085 return -1;
1086
1087 hdspm_write(hdspm,
1088 HDSPM_MADI_mixerBase +
1089 ((64 + pb + 128 * chan) * sizeof(u32)),
1090 (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
1091 return 0;
1092}
1093
1094
1095/* enable DMA for specific channels, now available for DSP-MADI */
Takashi Iwai98274f02005-11-17 14:52:34 +01001096static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001097{
1098 hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
1099}
1100
Takashi Iwai98274f02005-11-17 14:52:34 +01001101static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001102{
1103 hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
1104}
1105
1106/* check if same process is writing and reading */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001107static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001108{
1109 unsigned long flags;
1110 int ret = 1;
1111
1112 spin_lock_irqsave(&hdspm->lock, flags);
1113 if ((hdspm->playback_pid != hdspm->capture_pid) &&
1114 (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
1115 ret = 0;
1116 }
1117 spin_unlock_irqrestore(&hdspm->lock, flags);
1118 return ret;
1119}
1120
Adrian Knothfcdc4ba2013-03-10 00:37:22 +01001121/* round arbitary sample rates to commonly known rates */
1122static int hdspm_round_frequency(int rate)
1123{
1124 if (rate < 38050)
1125 return 32000;
1126 if (rate < 46008)
1127 return 44100;
1128 else
1129 return 48000;
1130}
1131
Adrian Knotha8a729f2013-05-31 12:57:10 +02001132/* QS and DS rates normally can not be detected
1133 * automatically by the card. Only exception is MADI
1134 * in 96k frame mode.
1135 *
1136 * So if we read SS values (32 .. 48k), check for
1137 * user-provided DS/QS bits in the control register
1138 * and multiply the base frequency accordingly.
1139 */
1140static int hdspm_rate_multiplier(struct hdspm *hdspm, int rate)
1141{
1142 if (rate <= 48000) {
1143 if (hdspm->control_register & HDSPM_QuadSpeed)
1144 return rate * 4;
1145 else if (hdspm->control_register &
1146 HDSPM_DoubleSpeed)
1147 return rate * 2;
1148 };
1149 return rate;
1150}
1151
Adrian Knothfcdc4ba2013-03-10 00:37:22 +01001152static int hdspm_tco_sync_check(struct hdspm *hdspm);
1153static int hdspm_sync_in_sync_check(struct hdspm *hdspm);
1154
Takashi Iwai763f3562005-06-03 11:25:34 +02001155/* check for external sample rate */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001156static int hdspm_external_sample_rate(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001157{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001158 unsigned int status, status2, timecode;
1159 int syncref, rate = 0, rate_bits;
Takashi Iwai763f3562005-06-03 11:25:34 +02001160
Adrian Knoth0dca1792011-01-26 19:32:14 +01001161 switch (hdspm->io_type) {
1162 case AES32:
1163 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1164 status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01001165 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001166
1167 syncref = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001168
Remy Bruno3cee5a62006-10-16 12:46:32 +02001169 if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD &&
1170 status & HDSPM_AES32_wcLock)
Adrian Knoth0dca1792011-01-26 19:32:14 +01001171 return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF);
1172
Remy Bruno3cee5a62006-10-16 12:46:32 +02001173 if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001174 syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
1175 status2 & (HDSPM_LockAES >>
1176 (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1)))
1177 return HDSPM_bit2freq((timecode >> (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF);
Remy Bruno3cee5a62006-10-16 12:46:32 +02001178 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001179 break;
1180
1181 case MADIface:
1182 status = hdspm_read(hdspm, HDSPM_statusRegister);
1183
1184 if (!(status & HDSPM_madiLock)) {
1185 rate = 0; /* no lock */
1186 } else {
1187 switch (status & (HDSPM_status1_freqMask)) {
1188 case HDSPM_status1_F_0*1:
1189 rate = 32000; break;
1190 case HDSPM_status1_F_0*2:
1191 rate = 44100; break;
1192 case HDSPM_status1_F_0*3:
1193 rate = 48000; break;
1194 case HDSPM_status1_F_0*4:
1195 rate = 64000; break;
1196 case HDSPM_status1_F_0*5:
1197 rate = 88200; break;
1198 case HDSPM_status1_F_0*6:
1199 rate = 96000; break;
1200 case HDSPM_status1_F_0*7:
1201 rate = 128000; break;
1202 case HDSPM_status1_F_0*8:
1203 rate = 176400; break;
1204 case HDSPM_status1_F_0*9:
1205 rate = 192000; break;
1206 default:
1207 rate = 0; break;
1208 }
1209 }
1210
1211 break;
1212
1213 case MADI:
1214 case AIO:
1215 case RayDAT:
1216 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1217 status = hdspm_read(hdspm, HDSPM_statusRegister);
1218 rate = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02001219
Remy Bruno3cee5a62006-10-16 12:46:32 +02001220 /* if wordclock has synced freq and wordclock is valid */
1221 if ((status2 & HDSPM_wcLock) != 0 &&
Adrian Knothfedf1532011-06-12 17:26:18 +02001222 (status2 & HDSPM_SelSyncRef0) == 0) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02001223
1224 rate_bits = status2 & HDSPM_wcFreqMask;
1225
Adrian Knoth0dca1792011-01-26 19:32:14 +01001226
Remy Bruno3cee5a62006-10-16 12:46:32 +02001227 switch (rate_bits) {
1228 case HDSPM_wcFreq32:
1229 rate = 32000;
1230 break;
1231 case HDSPM_wcFreq44_1:
1232 rate = 44100;
1233 break;
1234 case HDSPM_wcFreq48:
1235 rate = 48000;
1236 break;
1237 case HDSPM_wcFreq64:
1238 rate = 64000;
1239 break;
1240 case HDSPM_wcFreq88_2:
1241 rate = 88200;
1242 break;
1243 case HDSPM_wcFreq96:
1244 rate = 96000;
1245 break;
Adrian Knotha8cd7142013-05-31 12:57:09 +02001246 case HDSPM_wcFreq128:
1247 rate = 128000;
1248 break;
1249 case HDSPM_wcFreq176_4:
1250 rate = 176400;
1251 break;
1252 case HDSPM_wcFreq192:
1253 rate = 192000;
1254 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001255 default:
1256 rate = 0;
1257 break;
1258 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001259 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001260
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001261 /* if rate detected and Syncref is Word than have it,
1262 * word has priority to MADI
1263 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001264 if (rate != 0 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001265 (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
Adrian Knoth7b559392013-05-31 12:57:11 +02001266 return hdspm_rate_multiplier(hdspm, rate);
Remy Bruno3cee5a62006-10-16 12:46:32 +02001267
Adrian Knoth0dca1792011-01-26 19:32:14 +01001268 /* maybe a madi input (which is taken if sel sync is madi) */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001269 if (status & HDSPM_madiLock) {
1270 rate_bits = status & HDSPM_madiFreqMask;
1271
1272 switch (rate_bits) {
1273 case HDSPM_madiFreq32:
1274 rate = 32000;
1275 break;
1276 case HDSPM_madiFreq44_1:
1277 rate = 44100;
1278 break;
1279 case HDSPM_madiFreq48:
1280 rate = 48000;
1281 break;
1282 case HDSPM_madiFreq64:
1283 rate = 64000;
1284 break;
1285 case HDSPM_madiFreq88_2:
1286 rate = 88200;
1287 break;
1288 case HDSPM_madiFreq96:
1289 rate = 96000;
1290 break;
1291 case HDSPM_madiFreq128:
1292 rate = 128000;
1293 break;
1294 case HDSPM_madiFreq176_4:
1295 rate = 176400;
1296 break;
1297 case HDSPM_madiFreq192:
1298 rate = 192000;
1299 break;
1300 default:
1301 rate = 0;
1302 break;
1303 }
Adrian Knothd12c51d2011-07-29 03:11:03 +02001304
Adrian Knothfcdc4ba2013-03-10 00:37:22 +01001305 } /* endif HDSPM_madiLock */
1306
1307 /* check sample rate from TCO or SYNC_IN */
1308 {
1309 bool is_valid_input = 0;
1310 bool has_sync = 0;
1311
1312 syncref = hdspm_autosync_ref(hdspm);
1313 if (HDSPM_AUTOSYNC_FROM_TCO == syncref) {
1314 is_valid_input = 1;
1315 has_sync = (HDSPM_SYNC_CHECK_SYNC ==
1316 hdspm_tco_sync_check(hdspm));
1317 } else if (HDSPM_AUTOSYNC_FROM_SYNC_IN == syncref) {
1318 is_valid_input = 1;
1319 has_sync = (HDSPM_SYNC_CHECK_SYNC ==
1320 hdspm_sync_in_sync_check(hdspm));
Adrian Knothd12c51d2011-07-29 03:11:03 +02001321 }
Adrian Knothfcdc4ba2013-03-10 00:37:22 +01001322
1323 if (is_valid_input && has_sync) {
1324 rate = hdspm_round_frequency(
1325 hdspm_get_pll_freq(hdspm));
1326 }
1327 }
1328
Adrian Knotha8a729f2013-05-31 12:57:10 +02001329 rate = hdspm_rate_multiplier(hdspm, rate);
1330
Adrian Knoth0dca1792011-01-26 19:32:14 +01001331 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001332 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001333
1334 return rate;
Takashi Iwai763f3562005-06-03 11:25:34 +02001335}
1336
Adrian Knoth7cb155f2011-08-15 00:22:53 +02001337/* return latency in samples per period */
1338static int hdspm_get_latency(struct hdspm *hdspm)
1339{
1340 int n;
1341
1342 n = hdspm_decode_latency(hdspm->control_register);
1343
1344 /* Special case for new RME cards with 32 samples period size.
1345 * The three latency bits in the control register
1346 * (HDSP_LatencyMask) encode latency values of 64 samples as
1347 * 0, 128 samples as 1 ... 4096 samples as 6. For old cards, 7
1348 * denotes 8192 samples, but on new cards like RayDAT or AIO,
1349 * it corresponds to 32 samples.
1350 */
1351 if ((7 == n) && (RayDAT == hdspm->io_type || AIO == hdspm->io_type))
1352 n = -1;
1353
1354 return 1 << (n + 6);
1355}
1356
Takashi Iwai763f3562005-06-03 11:25:34 +02001357/* Latency function */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001358static inline void hdspm_compute_period_size(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001359{
Adrian Knoth7cb155f2011-08-15 00:22:53 +02001360 hdspm->period_bytes = 4 * hdspm_get_latency(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001361}
1362
Adrian Knoth0dca1792011-01-26 19:32:14 +01001363
1364static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001365{
1366 int position;
1367
1368 position = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth483cee72011-02-23 11:43:09 +01001369
1370 switch (hdspm->io_type) {
1371 case RayDAT:
1372 case AIO:
1373 position &= HDSPM_BufferPositionMask;
1374 position /= 4; /* Bytes per sample */
1375 break;
1376 default:
1377 position = (position & HDSPM_BufferID) ?
1378 (hdspm->period_bytes / 4) : 0;
1379 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001380
1381 return position;
1382}
1383
1384
Takashi Iwai98274f02005-11-17 14:52:34 +01001385static inline void hdspm_start_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001386{
1387 s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
1388 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1389}
1390
Takashi Iwai98274f02005-11-17 14:52:34 +01001391static inline void hdspm_stop_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001392{
1393 s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
1394 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1395}
1396
1397/* should I silence all or only opened ones ? doit all for first even is 4MB*/
Denys Vlasenko62cef822008-04-14 13:04:18 +02001398static void hdspm_silence_playback(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001399{
1400 int i;
1401 int n = hdspm->period_bytes;
1402 void *buf = hdspm->playback_buffer;
1403
Remy Bruno3cee5a62006-10-16 12:46:32 +02001404 if (buf == NULL)
1405 return;
Takashi Iwai763f3562005-06-03 11:25:34 +02001406
1407 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
1408 memset(buf, 0, n);
1409 buf += HDSPM_CHANNEL_BUFFER_BYTES;
1410 }
1411}
1412
Adrian Knoth0dca1792011-01-26 19:32:14 +01001413static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames)
Takashi Iwai763f3562005-06-03 11:25:34 +02001414{
1415 int n;
1416
1417 spin_lock_irq(&s->lock);
1418
Adrian Knoth2e610272011-08-15 00:22:54 +02001419 if (32 == frames) {
1420 /* Special case for new RME cards like RayDAT/AIO which
1421 * support period sizes of 32 samples. Since latency is
1422 * encoded in the three bits of HDSP_LatencyMask, we can only
1423 * have values from 0 .. 7. While 0 still means 64 samples and
1424 * 6 represents 4096 samples on all cards, 7 represents 8192
1425 * on older cards and 32 samples on new cards.
1426 *
1427 * In other words, period size in samples is calculated by
1428 * 2^(n+6) with n ranging from 0 .. 7.
1429 */
1430 n = 7;
1431 } else {
1432 frames >>= 7;
1433 n = 0;
1434 while (frames) {
1435 n++;
1436 frames >>= 1;
1437 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001438 }
Adrian Knoth2e610272011-08-15 00:22:54 +02001439
Takashi Iwai763f3562005-06-03 11:25:34 +02001440 s->control_register &= ~HDSPM_LatencyMask;
1441 s->control_register |= hdspm_encode_latency(n);
1442
1443 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1444
1445 hdspm_compute_period_size(s);
1446
1447 spin_unlock_irq(&s->lock);
1448
1449 return 0;
1450}
1451
Adrian Knoth0dca1792011-01-26 19:32:14 +01001452static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period)
1453{
1454 u64 freq_const;
1455
1456 if (period == 0)
1457 return 0;
1458
1459 switch (hdspm->io_type) {
1460 case MADI:
1461 case AES32:
1462 freq_const = 110069313433624ULL;
1463 break;
1464 case RayDAT:
1465 case AIO:
1466 freq_const = 104857600000000ULL;
1467 break;
1468 case MADIface:
1469 freq_const = 131072000000000ULL;
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001470 break;
1471 default:
1472 snd_BUG();
1473 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001474 }
1475
1476 return div_u64(freq_const, period);
1477}
1478
1479
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001480static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
1481{
1482 u64 n;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001483
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001484 if (rate >= 112000)
1485 rate /= 4;
1486 else if (rate >= 56000)
1487 rate /= 2;
1488
Adrian Knoth0dca1792011-01-26 19:32:14 +01001489 switch (hdspm->io_type) {
1490 case MADIface:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001491 n = 131072000000000ULL; /* 125 MHz */
1492 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001493 case MADI:
1494 case AES32:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001495 n = 110069313433624ULL; /* 105 MHz */
1496 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001497 case RayDAT:
1498 case AIO:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001499 n = 104857600000000ULL; /* 100 MHz */
1500 break;
1501 default:
1502 snd_BUG();
1503 return;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001504 }
1505
Takashi Iwai3f7440a2009-06-05 17:40:04 +02001506 n = div_u64(n, rate);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001507 /* n should be less than 2^32 for being written to FREQ register */
Takashi Iwaida3cec32008-08-08 17:12:14 +02001508 snd_BUG_ON(n >> 32);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001509 hdspm_write(hdspm, HDSPM_freqReg, (u32)n);
1510}
Takashi Iwai763f3562005-06-03 11:25:34 +02001511
1512/* dummy set rate lets see what happens */
Takashi Iwai98274f02005-11-17 14:52:34 +01001513static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
Takashi Iwai763f3562005-06-03 11:25:34 +02001514{
Takashi Iwai763f3562005-06-03 11:25:34 +02001515 int current_rate;
1516 int rate_bits;
1517 int not_set = 0;
Remy Bruno65345992007-08-31 12:21:08 +02001518 int current_speed, target_speed;
Takashi Iwai763f3562005-06-03 11:25:34 +02001519
1520 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
1521 it (e.g. during module initialization).
1522 */
1523
1524 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
1525
Adrian Knoth0dca1792011-01-26 19:32:14 +01001526 /* SLAVE --- */
Takashi Iwai763f3562005-06-03 11:25:34 +02001527 if (called_internally) {
1528
Adrian Knoth0dca1792011-01-26 19:32:14 +01001529 /* request from ctl or card initialization
1530 just make a warning an remember setting
1531 for future master mode switching */
1532
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001533 snd_printk(KERN_WARNING "HDSPM: "
1534 "Warning: device is not running "
1535 "as a clock master.\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001536 not_set = 1;
1537 } else {
1538
1539 /* hw_param request while in AutoSync mode */
1540 int external_freq =
1541 hdspm_external_sample_rate(hdspm);
1542
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001543 if (hdspm_autosync_ref(hdspm) ==
1544 HDSPM_AUTOSYNC_FROM_NONE) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001545
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001546 snd_printk(KERN_WARNING "HDSPM: "
1547 "Detected no Externel Sync \n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001548 not_set = 1;
1549
1550 } else if (rate != external_freq) {
1551
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001552 snd_printk(KERN_WARNING "HDSPM: "
1553 "Warning: No AutoSync source for "
1554 "requested rate\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001555 not_set = 1;
1556 }
1557 }
1558 }
1559
1560 current_rate = hdspm->system_sample_rate;
1561
1562 /* Changing between Singe, Double and Quad speed is not
1563 allowed if any substreams are open. This is because such a change
1564 causes a shift in the location of the DMA buffers and a reduction
1565 in the number of available buffers.
1566
1567 Note that a similar but essentially insoluble problem exists for
1568 externally-driven rate changes. All we can do is to flag rate
Adrian Knoth0dca1792011-01-26 19:32:14 +01001569 changes in the read/write routines.
Takashi Iwai763f3562005-06-03 11:25:34 +02001570 */
1571
Remy Bruno65345992007-08-31 12:21:08 +02001572 if (current_rate <= 48000)
1573 current_speed = HDSPM_SPEED_SINGLE;
1574 else if (current_rate <= 96000)
1575 current_speed = HDSPM_SPEED_DOUBLE;
1576 else
1577 current_speed = HDSPM_SPEED_QUAD;
1578
1579 if (rate <= 48000)
1580 target_speed = HDSPM_SPEED_SINGLE;
1581 else if (rate <= 96000)
1582 target_speed = HDSPM_SPEED_DOUBLE;
1583 else
1584 target_speed = HDSPM_SPEED_QUAD;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001585
Takashi Iwai763f3562005-06-03 11:25:34 +02001586 switch (rate) {
1587 case 32000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001588 rate_bits = HDSPM_Frequency32KHz;
1589 break;
1590 case 44100:
Takashi Iwai763f3562005-06-03 11:25:34 +02001591 rate_bits = HDSPM_Frequency44_1KHz;
1592 break;
1593 case 48000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001594 rate_bits = HDSPM_Frequency48KHz;
1595 break;
1596 case 64000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001597 rate_bits = HDSPM_Frequency64KHz;
1598 break;
1599 case 88200:
Takashi Iwai763f3562005-06-03 11:25:34 +02001600 rate_bits = HDSPM_Frequency88_2KHz;
1601 break;
1602 case 96000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001603 rate_bits = HDSPM_Frequency96KHz;
1604 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001605 case 128000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001606 rate_bits = HDSPM_Frequency128KHz;
1607 break;
1608 case 176400:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001609 rate_bits = HDSPM_Frequency176_4KHz;
1610 break;
1611 case 192000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001612 rate_bits = HDSPM_Frequency192KHz;
1613 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001614 default:
1615 return -EINVAL;
1616 }
1617
Remy Bruno65345992007-08-31 12:21:08 +02001618 if (current_speed != target_speed
Takashi Iwai763f3562005-06-03 11:25:34 +02001619 && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
1620 snd_printk
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001621 (KERN_ERR "HDSPM: "
Remy Bruno65345992007-08-31 12:21:08 +02001622 "cannot change from %s speed to %s speed mode "
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001623 "(capture PID = %d, playback PID = %d)\n",
Remy Bruno65345992007-08-31 12:21:08 +02001624 hdspm_speed_names[current_speed],
1625 hdspm_speed_names[target_speed],
Takashi Iwai763f3562005-06-03 11:25:34 +02001626 hdspm->capture_pid, hdspm->playback_pid);
1627 return -EBUSY;
1628 }
1629
1630 hdspm->control_register &= ~HDSPM_FrequencyMask;
1631 hdspm->control_register |= rate_bits;
1632 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1633
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001634 /* For AES32, need to set DDS value in FREQ register
1635 For MADI, also apparently */
1636 hdspm_set_dds_value(hdspm, rate);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001637
1638 if (AES32 == hdspm->io_type && rate != current_rate)
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001639 hdspm_write(hdspm, HDSPM_eeprom_wr, 0);
Takashi Iwai763f3562005-06-03 11:25:34 +02001640
1641 hdspm->system_sample_rate = rate;
1642
Adrian Knoth0dca1792011-01-26 19:32:14 +01001643 if (rate <= 48000) {
1644 hdspm->channel_map_in = hdspm->channel_map_in_ss;
1645 hdspm->channel_map_out = hdspm->channel_map_out_ss;
1646 hdspm->max_channels_in = hdspm->ss_in_channels;
1647 hdspm->max_channels_out = hdspm->ss_out_channels;
1648 hdspm->port_names_in = hdspm->port_names_in_ss;
1649 hdspm->port_names_out = hdspm->port_names_out_ss;
1650 } else if (rate <= 96000) {
1651 hdspm->channel_map_in = hdspm->channel_map_in_ds;
1652 hdspm->channel_map_out = hdspm->channel_map_out_ds;
1653 hdspm->max_channels_in = hdspm->ds_in_channels;
1654 hdspm->max_channels_out = hdspm->ds_out_channels;
1655 hdspm->port_names_in = hdspm->port_names_in_ds;
1656 hdspm->port_names_out = hdspm->port_names_out_ds;
1657 } else {
1658 hdspm->channel_map_in = hdspm->channel_map_in_qs;
1659 hdspm->channel_map_out = hdspm->channel_map_out_qs;
1660 hdspm->max_channels_in = hdspm->qs_in_channels;
1661 hdspm->max_channels_out = hdspm->qs_out_channels;
1662 hdspm->port_names_in = hdspm->port_names_in_qs;
1663 hdspm->port_names_out = hdspm->port_names_out_qs;
1664 }
1665
Takashi Iwai763f3562005-06-03 11:25:34 +02001666 if (not_set != 0)
1667 return -1;
1668
1669 return 0;
1670}
1671
1672/* mainly for init to 0 on load */
Takashi Iwai98274f02005-11-17 14:52:34 +01001673static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
Takashi Iwai763f3562005-06-03 11:25:34 +02001674{
1675 int i, j;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001676 unsigned int gain;
1677
1678 if (sgain > UNITY_GAIN)
1679 gain = UNITY_GAIN;
1680 else if (sgain < 0)
1681 gain = 0;
1682 else
1683 gain = sgain;
Takashi Iwai763f3562005-06-03 11:25:34 +02001684
1685 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
1686 for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
1687 hdspm_write_in_gain(hdspm, i, j, gain);
1688 hdspm_write_pb_gain(hdspm, i, j, gain);
1689 }
1690}
1691
1692/*----------------------------------------------------------------------------
1693 MIDI
1694 ----------------------------------------------------------------------------*/
1695
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001696static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm,
1697 int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001698{
1699 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001700 return hdspm_read(hdspm, hdspm->midi[id].dataIn);
Takashi Iwai763f3562005-06-03 11:25:34 +02001701}
1702
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001703static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
1704 int val)
Takashi Iwai763f3562005-06-03 11:25:34 +02001705{
1706 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001707 return hdspm_write(hdspm, hdspm->midi[id].dataOut, val);
Takashi Iwai763f3562005-06-03 11:25:34 +02001708}
1709
Takashi Iwai98274f02005-11-17 14:52:34 +01001710static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001711{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001712 return hdspm_read(hdspm, hdspm->midi[id].statusIn) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001713}
1714
Takashi Iwai98274f02005-11-17 14:52:34 +01001715static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001716{
1717 int fifo_bytes_used;
1718
Adrian Knoth0dca1792011-01-26 19:32:14 +01001719 fifo_bytes_used = hdspm_read(hdspm, hdspm->midi[id].statusOut) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001720
1721 if (fifo_bytes_used < 128)
1722 return 128 - fifo_bytes_used;
1723 else
1724 return 0;
1725}
1726
Denys Vlasenko62cef822008-04-14 13:04:18 +02001727static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001728{
1729 while (snd_hdspm_midi_input_available (hdspm, id))
1730 snd_hdspm_midi_read_byte (hdspm, id);
1731}
1732
Takashi Iwai98274f02005-11-17 14:52:34 +01001733static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001734{
1735 unsigned long flags;
1736 int n_pending;
1737 int to_write;
1738 int i;
1739 unsigned char buf[128];
1740
1741 /* Output is not interrupt driven */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001742
Takashi Iwai763f3562005-06-03 11:25:34 +02001743 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001744 if (hmidi->output &&
1745 !snd_rawmidi_transmit_empty (hmidi->output)) {
1746 n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm,
1747 hmidi->id);
1748 if (n_pending > 0) {
1749 if (n_pending > (int)sizeof (buf))
1750 n_pending = sizeof (buf);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001751
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001752 to_write = snd_rawmidi_transmit (hmidi->output, buf,
1753 n_pending);
1754 if (to_write > 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001755 for (i = 0; i < to_write; ++i)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001756 snd_hdspm_midi_write_byte (hmidi->hdspm,
1757 hmidi->id,
1758 buf[i]);
Takashi Iwai763f3562005-06-03 11:25:34 +02001759 }
1760 }
1761 }
1762 spin_unlock_irqrestore (&hmidi->lock, flags);
1763 return 0;
1764}
1765
Takashi Iwai98274f02005-11-17 14:52:34 +01001766static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001767{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001768 unsigned char buf[128]; /* this buffer is designed to match the MIDI
1769 * input FIFO size
1770 */
Takashi Iwai763f3562005-06-03 11:25:34 +02001771 unsigned long flags;
1772 int n_pending;
1773 int i;
1774
1775 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001776 n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id);
1777 if (n_pending > 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001778 if (hmidi->input) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001779 if (n_pending > (int)sizeof (buf))
Takashi Iwai763f3562005-06-03 11:25:34 +02001780 n_pending = sizeof (buf);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001781 for (i = 0; i < n_pending; ++i)
1782 buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm,
1783 hmidi->id);
1784 if (n_pending)
1785 snd_rawmidi_receive (hmidi->input, buf,
1786 n_pending);
Takashi Iwai763f3562005-06-03 11:25:34 +02001787 } else {
1788 /* flush the MIDI input FIFO */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001789 while (n_pending--)
1790 snd_hdspm_midi_read_byte (hmidi->hdspm,
1791 hmidi->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02001792 }
1793 }
1794 hmidi->pending = 0;
Adrian Knothc0da0012011-06-12 17:26:17 +02001795 spin_unlock_irqrestore(&hmidi->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001796
Adrian Knothc0da0012011-06-12 17:26:17 +02001797 spin_lock_irqsave(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001798 hmidi->hdspm->control_register |= hmidi->ie;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001799 hdspm_write(hmidi->hdspm, HDSPM_controlRegister,
1800 hmidi->hdspm->control_register);
Adrian Knothc0da0012011-06-12 17:26:17 +02001801 spin_unlock_irqrestore(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001802
Takashi Iwai763f3562005-06-03 11:25:34 +02001803 return snd_hdspm_midi_output_write (hmidi);
1804}
1805
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001806static void
1807snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001808{
Takashi Iwai98274f02005-11-17 14:52:34 +01001809 struct hdspm *hdspm;
1810 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001811 unsigned long flags;
Takashi Iwai763f3562005-06-03 11:25:34 +02001812
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001813 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001814 hdspm = hmidi->hdspm;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001815
Takashi Iwai763f3562005-06-03 11:25:34 +02001816 spin_lock_irqsave (&hdspm->lock, flags);
1817 if (up) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001818 if (!(hdspm->control_register & hmidi->ie)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001819 snd_hdspm_flush_midi_input (hdspm, hmidi->id);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001820 hdspm->control_register |= hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001821 }
1822 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001823 hdspm->control_register &= ~hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001824 }
1825
1826 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1827 spin_unlock_irqrestore (&hdspm->lock, flags);
1828}
1829
1830static void snd_hdspm_midi_output_timer(unsigned long data)
1831{
Takashi Iwai98274f02005-11-17 14:52:34 +01001832 struct hdspm_midi *hmidi = (struct hdspm_midi *) data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001833 unsigned long flags;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001834
Takashi Iwai763f3562005-06-03 11:25:34 +02001835 snd_hdspm_midi_output_write(hmidi);
1836 spin_lock_irqsave (&hmidi->lock, flags);
1837
1838 /* this does not bump hmidi->istimer, because the
1839 kernel automatically removed the timer when it
1840 expired, and we are now adding it back, thus
Adrian Knoth0dca1792011-01-26 19:32:14 +01001841 leaving istimer wherever it was set before.
Takashi Iwai763f3562005-06-03 11:25:34 +02001842 */
1843
1844 if (hmidi->istimer) {
1845 hmidi->timer.expires = 1 + jiffies;
1846 add_timer(&hmidi->timer);
1847 }
1848
1849 spin_unlock_irqrestore (&hmidi->lock, flags);
1850}
1851
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001852static void
1853snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001854{
Takashi Iwai98274f02005-11-17 14:52:34 +01001855 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001856 unsigned long flags;
1857
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001858 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001859 spin_lock_irqsave (&hmidi->lock, flags);
1860 if (up) {
1861 if (!hmidi->istimer) {
1862 init_timer(&hmidi->timer);
1863 hmidi->timer.function = snd_hdspm_midi_output_timer;
1864 hmidi->timer.data = (unsigned long) hmidi;
1865 hmidi->timer.expires = 1 + jiffies;
1866 add_timer(&hmidi->timer);
1867 hmidi->istimer++;
1868 }
1869 } else {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001870 if (hmidi->istimer && --hmidi->istimer <= 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02001871 del_timer (&hmidi->timer);
Takashi Iwai763f3562005-06-03 11:25:34 +02001872 }
1873 spin_unlock_irqrestore (&hmidi->lock, flags);
1874 if (up)
1875 snd_hdspm_midi_output_write(hmidi);
1876}
1877
Takashi Iwai98274f02005-11-17 14:52:34 +01001878static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001879{
Takashi Iwai98274f02005-11-17 14:52:34 +01001880 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001881
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001882 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001883 spin_lock_irq (&hmidi->lock);
1884 snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
1885 hmidi->input = substream;
1886 spin_unlock_irq (&hmidi->lock);
1887
1888 return 0;
1889}
1890
Takashi Iwai98274f02005-11-17 14:52:34 +01001891static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001892{
Takashi Iwai98274f02005-11-17 14:52:34 +01001893 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001894
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001895 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001896 spin_lock_irq (&hmidi->lock);
1897 hmidi->output = substream;
1898 spin_unlock_irq (&hmidi->lock);
1899
1900 return 0;
1901}
1902
Takashi Iwai98274f02005-11-17 14:52:34 +01001903static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001904{
Takashi Iwai98274f02005-11-17 14:52:34 +01001905 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001906
1907 snd_hdspm_midi_input_trigger (substream, 0);
1908
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001909 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001910 spin_lock_irq (&hmidi->lock);
1911 hmidi->input = NULL;
1912 spin_unlock_irq (&hmidi->lock);
1913
1914 return 0;
1915}
1916
Takashi Iwai98274f02005-11-17 14:52:34 +01001917static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001918{
Takashi Iwai98274f02005-11-17 14:52:34 +01001919 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001920
1921 snd_hdspm_midi_output_trigger (substream, 0);
1922
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001923 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001924 spin_lock_irq (&hmidi->lock);
1925 hmidi->output = NULL;
1926 spin_unlock_irq (&hmidi->lock);
1927
1928 return 0;
1929}
1930
Takashi Iwai98274f02005-11-17 14:52:34 +01001931static struct snd_rawmidi_ops snd_hdspm_midi_output =
Takashi Iwai763f3562005-06-03 11:25:34 +02001932{
1933 .open = snd_hdspm_midi_output_open,
1934 .close = snd_hdspm_midi_output_close,
1935 .trigger = snd_hdspm_midi_output_trigger,
1936};
1937
Takashi Iwai98274f02005-11-17 14:52:34 +01001938static struct snd_rawmidi_ops snd_hdspm_midi_input =
Takashi Iwai763f3562005-06-03 11:25:34 +02001939{
1940 .open = snd_hdspm_midi_input_open,
1941 .close = snd_hdspm_midi_input_close,
1942 .trigger = snd_hdspm_midi_input_trigger,
1943};
1944
Bill Pembertone23e7a12012-12-06 12:35:10 -05001945static int snd_hdspm_create_midi(struct snd_card *card,
1946 struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001947{
1948 int err;
1949 char buf[32];
1950
1951 hdspm->midi[id].id = id;
Takashi Iwai763f3562005-06-03 11:25:34 +02001952 hdspm->midi[id].hdspm = hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +02001953 spin_lock_init (&hdspm->midi[id].lock);
1954
Adrian Knoth0dca1792011-01-26 19:32:14 +01001955 if (0 == id) {
1956 if (MADIface == hdspm->io_type) {
1957 /* MIDI-over-MADI on HDSPe MADIface */
1958 hdspm->midi[0].dataIn = HDSPM_midiDataIn2;
1959 hdspm->midi[0].statusIn = HDSPM_midiStatusIn2;
1960 hdspm->midi[0].dataOut = HDSPM_midiDataOut2;
1961 hdspm->midi[0].statusOut = HDSPM_midiStatusOut2;
1962 hdspm->midi[0].ie = HDSPM_Midi2InterruptEnable;
1963 hdspm->midi[0].irq = HDSPM_midi2IRQPending;
1964 } else {
1965 hdspm->midi[0].dataIn = HDSPM_midiDataIn0;
1966 hdspm->midi[0].statusIn = HDSPM_midiStatusIn0;
1967 hdspm->midi[0].dataOut = HDSPM_midiDataOut0;
1968 hdspm->midi[0].statusOut = HDSPM_midiStatusOut0;
1969 hdspm->midi[0].ie = HDSPM_Midi0InterruptEnable;
1970 hdspm->midi[0].irq = HDSPM_midi0IRQPending;
1971 }
1972 } else if (1 == id) {
1973 hdspm->midi[1].dataIn = HDSPM_midiDataIn1;
1974 hdspm->midi[1].statusIn = HDSPM_midiStatusIn1;
1975 hdspm->midi[1].dataOut = HDSPM_midiDataOut1;
1976 hdspm->midi[1].statusOut = HDSPM_midiStatusOut1;
1977 hdspm->midi[1].ie = HDSPM_Midi1InterruptEnable;
1978 hdspm->midi[1].irq = HDSPM_midi1IRQPending;
1979 } else if ((2 == id) && (MADI == hdspm->io_type)) {
1980 /* MIDI-over-MADI on HDSPe MADI */
1981 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1982 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1983 hdspm->midi[2].dataOut = HDSPM_midiDataOut2;
1984 hdspm->midi[2].statusOut = HDSPM_midiStatusOut2;
1985 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1986 hdspm->midi[2].irq = HDSPM_midi2IRQPending;
1987 } else if (2 == id) {
1988 /* TCO MTC, read only */
1989 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1990 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1991 hdspm->midi[2].dataOut = -1;
1992 hdspm->midi[2].statusOut = -1;
1993 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1994 hdspm->midi[2].irq = HDSPM_midi2IRQPendingAES;
1995 } else if (3 == id) {
1996 /* TCO MTC on HDSPe MADI */
1997 hdspm->midi[3].dataIn = HDSPM_midiDataIn3;
1998 hdspm->midi[3].statusIn = HDSPM_midiStatusIn3;
1999 hdspm->midi[3].dataOut = -1;
2000 hdspm->midi[3].statusOut = -1;
2001 hdspm->midi[3].ie = HDSPM_Midi3InterruptEnable;
2002 hdspm->midi[3].irq = HDSPM_midi3IRQPending;
2003 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002004
Adrian Knoth0dca1792011-01-26 19:32:14 +01002005 if ((id < 2) || ((2 == id) && ((MADI == hdspm->io_type) ||
2006 (MADIface == hdspm->io_type)))) {
2007 if ((id == 0) && (MADIface == hdspm->io_type)) {
2008 sprintf(buf, "%s MIDIoverMADI", card->shortname);
2009 } else if ((id == 2) && (MADI == hdspm->io_type)) {
2010 sprintf(buf, "%s MIDIoverMADI", card->shortname);
2011 } else {
2012 sprintf(buf, "%s MIDI %d", card->shortname, id+1);
2013 }
2014 err = snd_rawmidi_new(card, buf, id, 1, 1,
2015 &hdspm->midi[id].rmidi);
2016 if (err < 0)
2017 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02002018
Adrian Knoth0dca1792011-01-26 19:32:14 +01002019 sprintf(hdspm->midi[id].rmidi->name, "%s MIDI %d",
2020 card->id, id+1);
2021 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
Takashi Iwai763f3562005-06-03 11:25:34 +02002022
Adrian Knoth0dca1792011-01-26 19:32:14 +01002023 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
2024 SNDRV_RAWMIDI_STREAM_OUTPUT,
2025 &snd_hdspm_midi_output);
2026 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
2027 SNDRV_RAWMIDI_STREAM_INPUT,
2028 &snd_hdspm_midi_input);
2029
2030 hdspm->midi[id].rmidi->info_flags |=
2031 SNDRV_RAWMIDI_INFO_OUTPUT |
2032 SNDRV_RAWMIDI_INFO_INPUT |
2033 SNDRV_RAWMIDI_INFO_DUPLEX;
2034 } else {
2035 /* TCO MTC, read only */
2036 sprintf(buf, "%s MTC %d", card->shortname, id+1);
2037 err = snd_rawmidi_new(card, buf, id, 1, 1,
2038 &hdspm->midi[id].rmidi);
2039 if (err < 0)
2040 return err;
2041
2042 sprintf(hdspm->midi[id].rmidi->name,
2043 "%s MTC %d", card->id, id+1);
2044 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
2045
2046 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
2047 SNDRV_RAWMIDI_STREAM_INPUT,
2048 &snd_hdspm_midi_input);
2049
2050 hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
2051 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002052
2053 return 0;
2054}
2055
2056
2057static void hdspm_midi_tasklet(unsigned long arg)
2058{
Takashi Iwai98274f02005-11-17 14:52:34 +01002059 struct hdspm *hdspm = (struct hdspm *)arg;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002060 int i = 0;
2061
2062 while (i < hdspm->midiPorts) {
2063 if (hdspm->midi[i].pending)
2064 snd_hdspm_midi_input_read(&hdspm->midi[i]);
2065
2066 i++;
2067 }
2068}
Takashi Iwai763f3562005-06-03 11:25:34 +02002069
2070
2071/*-----------------------------------------------------------------------------
2072 Status Interface
2073 ----------------------------------------------------------------------------*/
2074
2075/* get the system sample rate which is set */
2076
Adrian Knoth0dca1792011-01-26 19:32:14 +01002077
Adrian Knoth3f7bf912013-03-10 00:37:21 +01002078static inline int hdspm_get_pll_freq(struct hdspm *hdspm)
2079{
2080 unsigned int period, rate;
2081
2082 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
2083 rate = hdspm_calc_dds_value(hdspm, period);
2084
2085 return rate;
2086}
2087
Adrian Knoth0dca1792011-01-26 19:32:14 +01002088/**
2089 * Calculate the real sample rate from the
2090 * current DDS value.
2091 **/
2092static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
2093{
Adrian Knoth3f7bf912013-03-10 00:37:21 +01002094 unsigned int rate;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002095
Adrian Knoth3f7bf912013-03-10 00:37:21 +01002096 rate = hdspm_get_pll_freq(hdspm);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002097
Adrian Knotha97bda72012-05-30 14:23:18 +02002098 if (rate > 207000) {
Adrian Knoth21a164d2012-10-19 17:42:23 +02002099 /* Unreasonable high sample rate as seen on PCI MADI cards. */
2100 if (0 == hdspm_system_clock_mode(hdspm)) {
2101 /* master mode, return internal sample rate */
2102 rate = hdspm->system_sample_rate;
2103 } else {
2104 /* slave mode, return external sample rate */
2105 rate = hdspm_external_sample_rate(hdspm);
2106 }
Adrian Knotha97bda72012-05-30 14:23:18 +02002107 }
2108
Adrian Knoth0dca1792011-01-26 19:32:14 +01002109 return rate;
2110}
2111
2112
Takashi Iwai763f3562005-06-03 11:25:34 +02002113#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02002114{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2115 .name = xname, \
2116 .index = xindex, \
2117 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2118 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2119 .info = snd_hdspm_info_system_sample_rate, \
2120 .put = snd_hdspm_put_system_sample_rate, \
2121 .get = snd_hdspm_get_system_sample_rate \
Takashi Iwai763f3562005-06-03 11:25:34 +02002122}
2123
Takashi Iwai98274f02005-11-17 14:52:34 +01002124static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
2125 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002126{
2127 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2128 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002129 uinfo->value.integer.min = 27000;
2130 uinfo->value.integer.max = 207000;
2131 uinfo->value.integer.step = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002132 return 0;
2133}
2134
Adrian Knoth0dca1792011-01-26 19:32:14 +01002135
Takashi Iwai98274f02005-11-17 14:52:34 +01002136static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
2137 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002138 ucontrol)
2139{
Takashi Iwai98274f02005-11-17 14:52:34 +01002140 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002141
Adrian Knoth0dca1792011-01-26 19:32:14 +01002142 ucontrol->value.integer.value[0] = hdspm_get_system_sample_rate(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002143 return 0;
2144}
2145
Adrian Knoth41285a92012-10-19 17:42:22 +02002146static int snd_hdspm_put_system_sample_rate(struct snd_kcontrol *kcontrol,
2147 struct snd_ctl_elem_value *
2148 ucontrol)
2149{
2150 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2151
2152 hdspm_set_dds_value(hdspm, ucontrol->value.enumerated.item[0]);
2153 return 0;
2154}
2155
Adrian Knoth0dca1792011-01-26 19:32:14 +01002156
2157/**
2158 * Returns the WordClock sample rate class for the given card.
2159 **/
2160static int hdspm_get_wc_sample_rate(struct hdspm *hdspm)
2161{
2162 int status;
2163
2164 switch (hdspm->io_type) {
2165 case RayDAT:
2166 case AIO:
2167 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2168 return (status >> 16) & 0xF;
2169 break;
2170 default:
2171 break;
2172 }
2173
2174
2175 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002176}
2177
Adrian Knoth0dca1792011-01-26 19:32:14 +01002178
2179/**
2180 * Returns the TCO sample rate class for the given card.
2181 **/
2182static int hdspm_get_tco_sample_rate(struct hdspm *hdspm)
2183{
2184 int status;
2185
2186 if (hdspm->tco) {
2187 switch (hdspm->io_type) {
2188 case RayDAT:
2189 case AIO:
2190 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2191 return (status >> 20) & 0xF;
2192 break;
2193 default:
2194 break;
2195 }
2196 }
2197
2198 return 0;
2199}
2200
2201
2202/**
2203 * Returns the SYNC_IN sample rate class for the given card.
2204 **/
2205static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm)
2206{
2207 int status;
2208
2209 if (hdspm->tco) {
2210 switch (hdspm->io_type) {
2211 case RayDAT:
2212 case AIO:
2213 status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2214 return (status >> 12) & 0xF;
2215 break;
2216 default:
2217 break;
2218 }
2219 }
2220
2221 return 0;
2222}
2223
2224
2225/**
2226 * Returns the sample rate class for input source <idx> for
2227 * 'new style' cards like the AIO and RayDAT.
2228 **/
2229static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
2230{
2231 int status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2232
2233 return (status >> (idx*4)) & 0xF;
2234}
2235
Adrian Knoth8cea5712013-07-05 11:27:59 +02002236static void snd_hdspm_set_infotext(struct snd_ctl_elem_info *uinfo,
2237 char **texts, const int count)
2238{
2239 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2240 uinfo->count = 1;
2241 uinfo->value.enumerated.items = count;
2242 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2243 uinfo->value.enumerated.item =
2244 uinfo->value.enumerated.items - 1;
2245 strcpy(uinfo->value.enumerated.name,
2246 texts[uinfo->value.enumerated.item]);
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01002247}
2248
Adrian Knoth8cea5712013-07-05 11:27:59 +02002249#define ENUMERATED_CTL_INFO(info, texts) \
2250 snd_hdspm_set_infotext(info, texts, ARRAY_SIZE(texts))
2251
Adrian Knoth0dca1792011-01-26 19:32:14 +01002252
2253
2254#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
2255{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2256 .name = xname, \
2257 .private_value = xindex, \
2258 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2259 .info = snd_hdspm_info_autosync_sample_rate, \
2260 .get = snd_hdspm_get_autosync_sample_rate \
2261}
2262
2263
Takashi Iwai98274f02005-11-17 14:52:34 +01002264static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2265 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002266{
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01002267 ENUMERATED_CTL_INFO(uinfo, texts_freq);
Takashi Iwai763f3562005-06-03 11:25:34 +02002268 return 0;
2269}
2270
Adrian Knoth0dca1792011-01-26 19:32:14 +01002271
Takashi Iwai98274f02005-11-17 14:52:34 +01002272static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2273 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002274 ucontrol)
2275{
Takashi Iwai98274f02005-11-17 14:52:34 +01002276 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002277
Adrian Knoth0dca1792011-01-26 19:32:14 +01002278 switch (hdspm->io_type) {
2279 case RayDAT:
2280 switch (kcontrol->private_value) {
2281 case 0:
2282 ucontrol->value.enumerated.item[0] =
2283 hdspm_get_wc_sample_rate(hdspm);
2284 break;
2285 case 7:
2286 ucontrol->value.enumerated.item[0] =
2287 hdspm_get_tco_sample_rate(hdspm);
2288 break;
2289 case 8:
2290 ucontrol->value.enumerated.item[0] =
2291 hdspm_get_sync_in_sample_rate(hdspm);
2292 break;
2293 default:
2294 ucontrol->value.enumerated.item[0] =
2295 hdspm_get_s1_sample_rate(hdspm,
2296 kcontrol->private_value-1);
2297 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002298 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002299
Adrian Knoth0dca1792011-01-26 19:32:14 +01002300 case AIO:
2301 switch (kcontrol->private_value) {
2302 case 0: /* WC */
2303 ucontrol->value.enumerated.item[0] =
2304 hdspm_get_wc_sample_rate(hdspm);
2305 break;
2306 case 4: /* TCO */
2307 ucontrol->value.enumerated.item[0] =
2308 hdspm_get_tco_sample_rate(hdspm);
2309 break;
2310 case 5: /* SYNC_IN */
2311 ucontrol->value.enumerated.item[0] =
2312 hdspm_get_sync_in_sample_rate(hdspm);
2313 break;
2314 default:
2315 ucontrol->value.enumerated.item[0] =
2316 hdspm_get_s1_sample_rate(hdspm,
Adrian Knoth1cb7dbf2013-07-05 11:28:03 +02002317 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002318 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002319 break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002320
2321 case AES32:
2322
2323 switch (kcontrol->private_value) {
2324 case 0: /* WC */
2325 ucontrol->value.enumerated.item[0] =
2326 hdspm_get_wc_sample_rate(hdspm);
2327 break;
2328 case 9: /* TCO */
2329 ucontrol->value.enumerated.item[0] =
2330 hdspm_get_tco_sample_rate(hdspm);
2331 break;
2332 case 10: /* SYNC_IN */
2333 ucontrol->value.enumerated.item[0] =
2334 hdspm_get_sync_in_sample_rate(hdspm);
2335 break;
2336 default: /* AES1 to AES8 */
2337 ucontrol->value.enumerated.item[0] =
2338 hdspm_get_s1_sample_rate(hdspm,
2339 kcontrol->private_value-1);
2340 break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002341 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002342 break;
Adrian Knothb8812c52012-10-19 17:42:26 +02002343
2344 case MADI:
2345 case MADIface:
2346 {
2347 int rate = hdspm_external_sample_rate(hdspm);
2348 int i, selected_rate = 0;
2349 for (i = 1; i < 10; i++)
2350 if (HDSPM_bit2freq(i) == rate) {
2351 selected_rate = i;
2352 break;
2353 }
2354 ucontrol->value.enumerated.item[0] = selected_rate;
2355 }
2356 break;
2357
Takashi Iwai763f3562005-06-03 11:25:34 +02002358 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002359 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002360 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002361
Takashi Iwai763f3562005-06-03 11:25:34 +02002362 return 0;
2363}
2364
Adrian Knoth0dca1792011-01-26 19:32:14 +01002365
Takashi Iwai763f3562005-06-03 11:25:34 +02002366#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002367{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2368 .name = xname, \
2369 .index = xindex, \
2370 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2371 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2372 .info = snd_hdspm_info_system_clock_mode, \
2373 .get = snd_hdspm_get_system_clock_mode, \
2374 .put = snd_hdspm_put_system_clock_mode, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002375}
2376
2377
Adrian Knoth0dca1792011-01-26 19:32:14 +01002378/**
2379 * Returns the system clock mode for the given card.
2380 * @returns 0 - master, 1 - slave
2381 **/
2382static int hdspm_system_clock_mode(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002383{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002384 switch (hdspm->io_type) {
2385 case AIO:
2386 case RayDAT:
2387 if (hdspm->settings_register & HDSPM_c0Master)
2388 return 0;
2389 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002390
Adrian Knoth0dca1792011-01-26 19:32:14 +01002391 default:
2392 if (hdspm->control_register & HDSPM_ClockModeMaster)
2393 return 0;
2394 }
2395
Takashi Iwai763f3562005-06-03 11:25:34 +02002396 return 1;
2397}
2398
Adrian Knoth0dca1792011-01-26 19:32:14 +01002399
2400/**
2401 * Sets the system clock mode.
2402 * @param mode 0 - master, 1 - slave
2403 **/
2404static void hdspm_set_system_clock_mode(struct hdspm *hdspm, int mode)
2405{
Adrian Knoth34be7eb2013-07-05 11:27:56 +02002406 hdspm_set_toggle_setting(hdspm,
2407 (hdspm_is_raydat_or_aio(hdspm)) ?
2408 HDSPM_c0Master : HDSPM_ClockModeMaster,
2409 (0 == mode));
Adrian Knoth0dca1792011-01-26 19:32:14 +01002410}
2411
2412
Takashi Iwai98274f02005-11-17 14:52:34 +01002413static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
2414 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002415{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002416 static char *texts[] = { "Master", "AutoSync" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01002417 ENUMERATED_CTL_INFO(uinfo, texts);
Takashi Iwai763f3562005-06-03 11:25:34 +02002418 return 0;
2419}
2420
Takashi Iwai98274f02005-11-17 14:52:34 +01002421static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
2422 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002423{
Takashi Iwai98274f02005-11-17 14:52:34 +01002424 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002425
Adrian Knoth0dca1792011-01-26 19:32:14 +01002426 ucontrol->value.enumerated.item[0] = hdspm_system_clock_mode(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002427 return 0;
2428}
2429
Adrian Knoth0dca1792011-01-26 19:32:14 +01002430static int snd_hdspm_put_system_clock_mode(struct snd_kcontrol *kcontrol,
2431 struct snd_ctl_elem_value *ucontrol)
2432{
2433 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2434 int val;
2435
2436 if (!snd_hdspm_use_is_exclusive(hdspm))
2437 return -EBUSY;
2438
2439 val = ucontrol->value.enumerated.item[0];
2440 if (val < 0)
2441 val = 0;
2442 else if (val > 1)
2443 val = 1;
2444
2445 hdspm_set_system_clock_mode(hdspm, val);
2446
2447 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002448}
2449
Adrian Knoth0dca1792011-01-26 19:32:14 +01002450
2451#define HDSPM_INTERNAL_CLOCK(xname, xindex) \
2452{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2453 .name = xname, \
2454 .index = xindex, \
2455 .info = snd_hdspm_info_clock_source, \
2456 .get = snd_hdspm_get_clock_source, \
2457 .put = snd_hdspm_put_clock_source \
2458}
2459
2460
Takashi Iwai98274f02005-11-17 14:52:34 +01002461static int hdspm_clock_source(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002462{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002463 switch (hdspm->system_sample_rate) {
2464 case 32000: return 0;
2465 case 44100: return 1;
2466 case 48000: return 2;
2467 case 64000: return 3;
2468 case 88200: return 4;
2469 case 96000: return 5;
2470 case 128000: return 6;
2471 case 176400: return 7;
2472 case 192000: return 8;
Takashi Iwai763f3562005-06-03 11:25:34 +02002473 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002474
2475 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002476}
2477
Takashi Iwai98274f02005-11-17 14:52:34 +01002478static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
Takashi Iwai763f3562005-06-03 11:25:34 +02002479{
2480 int rate;
2481 switch (mode) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002482 case 0:
2483 rate = 32000; break;
2484 case 1:
2485 rate = 44100; break;
2486 case 2:
2487 rate = 48000; break;
2488 case 3:
2489 rate = 64000; break;
2490 case 4:
2491 rate = 88200; break;
2492 case 5:
2493 rate = 96000; break;
2494 case 6:
2495 rate = 128000; break;
2496 case 7:
2497 rate = 176400; break;
2498 case 8:
2499 rate = 192000; break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002500 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002501 rate = 48000;
Takashi Iwai763f3562005-06-03 11:25:34 +02002502 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002503 hdspm_set_rate(hdspm, rate, 1);
2504 return 0;
2505}
2506
Takashi Iwai98274f02005-11-17 14:52:34 +01002507static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
2508 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002509{
Takashi Iwai763f3562005-06-03 11:25:34 +02002510 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2511 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002512 uinfo->value.enumerated.items = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002513
2514 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2515 uinfo->value.enumerated.item =
2516 uinfo->value.enumerated.items - 1;
2517
2518 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002519 texts_freq[uinfo->value.enumerated.item+1]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002520
2521 return 0;
2522}
2523
Takashi Iwai98274f02005-11-17 14:52:34 +01002524static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
2525 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002526{
Takashi Iwai98274f02005-11-17 14:52:34 +01002527 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002528
2529 ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
2530 return 0;
2531}
2532
Takashi Iwai98274f02005-11-17 14:52:34 +01002533static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
2534 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002535{
Takashi Iwai98274f02005-11-17 14:52:34 +01002536 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002537 int change;
2538 int val;
2539
2540 if (!snd_hdspm_use_is_exclusive(hdspm))
2541 return -EBUSY;
2542 val = ucontrol->value.enumerated.item[0];
2543 if (val < 0)
2544 val = 0;
Remy Bruno65345992007-08-31 12:21:08 +02002545 if (val > 9)
2546 val = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002547 spin_lock_irq(&hdspm->lock);
2548 if (val != hdspm_clock_source(hdspm))
2549 change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
2550 else
2551 change = 0;
2552 spin_unlock_irq(&hdspm->lock);
2553 return change;
2554}
2555
Adrian Knoth0dca1792011-01-26 19:32:14 +01002556
Takashi Iwai763f3562005-06-03 11:25:34 +02002557#define HDSPM_PREF_SYNC_REF(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02002558{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002559 .name = xname, \
2560 .index = xindex, \
2561 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2562 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2563 .info = snd_hdspm_info_pref_sync_ref, \
2564 .get = snd_hdspm_get_pref_sync_ref, \
2565 .put = snd_hdspm_put_pref_sync_ref \
Takashi Iwai763f3562005-06-03 11:25:34 +02002566}
2567
Adrian Knoth0dca1792011-01-26 19:32:14 +01002568
2569/**
2570 * Returns the current preferred sync reference setting.
2571 * The semantics of the return value are depending on the
2572 * card, please see the comments for clarification.
2573 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002574static int hdspm_pref_sync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002575{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002576 switch (hdspm->io_type) {
2577 case AES32:
Remy Bruno3cee5a62006-10-16 12:46:32 +02002578 switch (hdspm->control_register & HDSPM_SyncRefMask) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002579 case 0: return 0; /* WC */
2580 case HDSPM_SyncRef0: return 1; /* AES 1 */
2581 case HDSPM_SyncRef1: return 2; /* AES 2 */
2582 case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; /* AES 3 */
2583 case HDSPM_SyncRef2: return 4; /* AES 4 */
2584 case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; /* AES 5 */
2585 case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; /* AES 6 */
2586 case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0:
2587 return 7; /* AES 7 */
2588 case HDSPM_SyncRef3: return 8; /* AES 8 */
2589 case HDSPM_SyncRef3+HDSPM_SyncRef0: return 9; /* TCO */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002590 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002591 break;
2592
2593 case MADI:
2594 case MADIface:
2595 if (hdspm->tco) {
2596 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2597 case 0: return 0; /* WC */
2598 case HDSPM_SyncRef0: return 1; /* MADI */
2599 case HDSPM_SyncRef1: return 2; /* TCO */
2600 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2601 return 3; /* SYNC_IN */
2602 }
2603 } else {
2604 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2605 case 0: return 0; /* WC */
2606 case HDSPM_SyncRef0: return 1; /* MADI */
2607 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2608 return 2; /* SYNC_IN */
2609 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02002610 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002611 break;
2612
2613 case RayDAT:
2614 if (hdspm->tco) {
2615 switch ((hdspm->settings_register &
2616 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2617 case 0: return 0; /* WC */
2618 case 3: return 1; /* ADAT 1 */
2619 case 4: return 2; /* ADAT 2 */
2620 case 5: return 3; /* ADAT 3 */
2621 case 6: return 4; /* ADAT 4 */
2622 case 1: return 5; /* AES */
2623 case 2: return 6; /* SPDIF */
2624 case 9: return 7; /* TCO */
2625 case 10: return 8; /* SYNC_IN */
2626 }
2627 } else {
2628 switch ((hdspm->settings_register &
2629 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2630 case 0: return 0; /* WC */
2631 case 3: return 1; /* ADAT 1 */
2632 case 4: return 2; /* ADAT 2 */
2633 case 5: return 3; /* ADAT 3 */
2634 case 6: return 4; /* ADAT 4 */
2635 case 1: return 5; /* AES */
2636 case 2: return 6; /* SPDIF */
2637 case 10: return 7; /* SYNC_IN */
2638 }
2639 }
2640
2641 break;
2642
2643 case AIO:
2644 if (hdspm->tco) {
2645 switch ((hdspm->settings_register &
2646 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2647 case 0: return 0; /* WC */
2648 case 3: return 1; /* ADAT */
2649 case 1: return 2; /* AES */
2650 case 2: return 3; /* SPDIF */
2651 case 9: return 4; /* TCO */
2652 case 10: return 5; /* SYNC_IN */
2653 }
2654 } else {
2655 switch ((hdspm->settings_register &
2656 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2657 case 0: return 0; /* WC */
2658 case 3: return 1; /* ADAT */
2659 case 1: return 2; /* AES */
2660 case 2: return 3; /* SPDIF */
2661 case 10: return 4; /* SYNC_IN */
2662 }
2663 }
2664
2665 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002666 }
2667
Adrian Knoth0dca1792011-01-26 19:32:14 +01002668 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002669}
2670
Adrian Knoth0dca1792011-01-26 19:32:14 +01002671
2672/**
2673 * Set the preferred sync reference to <pref>. The semantics
2674 * of <pref> are depending on the card type, see the comments
2675 * for clarification.
2676 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002677static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
Takashi Iwai763f3562005-06-03 11:25:34 +02002678{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002679 int p = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002680
Adrian Knoth0dca1792011-01-26 19:32:14 +01002681 switch (hdspm->io_type) {
2682 case AES32:
2683 hdspm->control_register &= ~HDSPM_SyncRefMask;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002684 switch (pref) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002685 case 0: /* WC */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002686 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002687 case 1: /* AES 1 */
2688 hdspm->control_register |= HDSPM_SyncRef0;
2689 break;
2690 case 2: /* AES 2 */
2691 hdspm->control_register |= HDSPM_SyncRef1;
2692 break;
2693 case 3: /* AES 3 */
2694 hdspm->control_register |=
2695 HDSPM_SyncRef1+HDSPM_SyncRef0;
2696 break;
2697 case 4: /* AES 4 */
2698 hdspm->control_register |= HDSPM_SyncRef2;
2699 break;
2700 case 5: /* AES 5 */
2701 hdspm->control_register |=
2702 HDSPM_SyncRef2+HDSPM_SyncRef0;
2703 break;
2704 case 6: /* AES 6 */
2705 hdspm->control_register |=
2706 HDSPM_SyncRef2+HDSPM_SyncRef1;
2707 break;
2708 case 7: /* AES 7 */
2709 hdspm->control_register |=
2710 HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
2711 break;
2712 case 8: /* AES 8 */
2713 hdspm->control_register |= HDSPM_SyncRef3;
2714 break;
2715 case 9: /* TCO */
2716 hdspm->control_register |=
2717 HDSPM_SyncRef3+HDSPM_SyncRef0;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002718 break;
2719 default:
2720 return -1;
2721 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002722
2723 break;
2724
2725 case MADI:
2726 case MADIface:
2727 hdspm->control_register &= ~HDSPM_SyncRefMask;
2728 if (hdspm->tco) {
2729 switch (pref) {
2730 case 0: /* WC */
2731 break;
2732 case 1: /* MADI */
2733 hdspm->control_register |= HDSPM_SyncRef0;
2734 break;
2735 case 2: /* TCO */
2736 hdspm->control_register |= HDSPM_SyncRef1;
2737 break;
2738 case 3: /* SYNC_IN */
2739 hdspm->control_register |=
2740 HDSPM_SyncRef0+HDSPM_SyncRef1;
2741 break;
2742 default:
2743 return -1;
2744 }
2745 } else {
2746 switch (pref) {
2747 case 0: /* WC */
2748 break;
2749 case 1: /* MADI */
2750 hdspm->control_register |= HDSPM_SyncRef0;
2751 break;
2752 case 2: /* SYNC_IN */
2753 hdspm->control_register |=
2754 HDSPM_SyncRef0+HDSPM_SyncRef1;
2755 break;
2756 default:
2757 return -1;
2758 }
2759 }
2760
2761 break;
2762
2763 case RayDAT:
2764 if (hdspm->tco) {
2765 switch (pref) {
2766 case 0: p = 0; break; /* WC */
2767 case 1: p = 3; break; /* ADAT 1 */
2768 case 2: p = 4; break; /* ADAT 2 */
2769 case 3: p = 5; break; /* ADAT 3 */
2770 case 4: p = 6; break; /* ADAT 4 */
2771 case 5: p = 1; break; /* AES */
2772 case 6: p = 2; break; /* SPDIF */
2773 case 7: p = 9; break; /* TCO */
2774 case 8: p = 10; break; /* SYNC_IN */
2775 default: return -1;
2776 }
2777 } else {
2778 switch (pref) {
2779 case 0: p = 0; break; /* WC */
2780 case 1: p = 3; break; /* ADAT 1 */
2781 case 2: p = 4; break; /* ADAT 2 */
2782 case 3: p = 5; break; /* ADAT 3 */
2783 case 4: p = 6; break; /* ADAT 4 */
2784 case 5: p = 1; break; /* AES */
2785 case 6: p = 2; break; /* SPDIF */
2786 case 7: p = 10; break; /* SYNC_IN */
2787 default: return -1;
2788 }
2789 }
2790 break;
2791
2792 case AIO:
2793 if (hdspm->tco) {
2794 switch (pref) {
2795 case 0: p = 0; break; /* WC */
2796 case 1: p = 3; break; /* ADAT */
2797 case 2: p = 1; break; /* AES */
2798 case 3: p = 2; break; /* SPDIF */
2799 case 4: p = 9; break; /* TCO */
2800 case 5: p = 10; break; /* SYNC_IN */
2801 default: return -1;
2802 }
2803 } else {
2804 switch (pref) {
2805 case 0: p = 0; break; /* WC */
2806 case 1: p = 3; break; /* ADAT */
2807 case 2: p = 1; break; /* AES */
2808 case 3: p = 2; break; /* SPDIF */
2809 case 4: p = 10; break; /* SYNC_IN */
2810 default: return -1;
2811 }
2812 }
2813 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002814 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002815
2816 switch (hdspm->io_type) {
2817 case RayDAT:
2818 case AIO:
2819 hdspm->settings_register &= ~HDSPM_c0_SyncRefMask;
2820 hdspm->settings_register |= HDSPM_c0_SyncRef0 * p;
2821 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2822 break;
2823
2824 case MADI:
2825 case MADIface:
2826 case AES32:
2827 hdspm_write(hdspm, HDSPM_controlRegister,
2828 hdspm->control_register);
2829 }
2830
Takashi Iwai763f3562005-06-03 11:25:34 +02002831 return 0;
2832}
2833
Adrian Knoth0dca1792011-01-26 19:32:14 +01002834
Takashi Iwai98274f02005-11-17 14:52:34 +01002835static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
2836 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002837{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002838 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002839
Adrian Knoth0dca1792011-01-26 19:32:14 +01002840 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2841 uinfo->count = 1;
2842 uinfo->value.enumerated.items = hdspm->texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +02002843
Adrian Knoth0dca1792011-01-26 19:32:14 +01002844 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2845 uinfo->value.enumerated.item =
2846 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002847
Adrian Knoth0dca1792011-01-26 19:32:14 +01002848 strcpy(uinfo->value.enumerated.name,
2849 hdspm->texts_autosync[uinfo->value.enumerated.item]);
Remy Bruno3cee5a62006-10-16 12:46:32 +02002850
Takashi Iwai763f3562005-06-03 11:25:34 +02002851 return 0;
2852}
2853
Takashi Iwai98274f02005-11-17 14:52:34 +01002854static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
2855 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002856{
Takashi Iwai98274f02005-11-17 14:52:34 +01002857 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002858 int psf = hdspm_pref_sync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002859
Adrian Knoth0dca1792011-01-26 19:32:14 +01002860 if (psf >= 0) {
2861 ucontrol->value.enumerated.item[0] = psf;
2862 return 0;
2863 }
2864
2865 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002866}
2867
Takashi Iwai98274f02005-11-17 14:52:34 +01002868static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
2869 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002870{
Takashi Iwai98274f02005-11-17 14:52:34 +01002871 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002872 int val, change = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002873
2874 if (!snd_hdspm_use_is_exclusive(hdspm))
2875 return -EBUSY;
2876
Adrian Knoth0dca1792011-01-26 19:32:14 +01002877 val = ucontrol->value.enumerated.item[0];
2878
2879 if (val < 0)
2880 val = 0;
2881 else if (val >= hdspm->texts_autosync_items)
2882 val = hdspm->texts_autosync_items-1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002883
2884 spin_lock_irq(&hdspm->lock);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002885 if (val != hdspm_pref_sync_ref(hdspm))
2886 change = (0 == hdspm_set_pref_sync_ref(hdspm, val)) ? 1 : 0;
2887
Takashi Iwai763f3562005-06-03 11:25:34 +02002888 spin_unlock_irq(&hdspm->lock);
2889 return change;
2890}
2891
Adrian Knoth0dca1792011-01-26 19:32:14 +01002892
Takashi Iwai763f3562005-06-03 11:25:34 +02002893#define HDSPM_AUTOSYNC_REF(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02002894{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2895 .name = xname, \
2896 .index = xindex, \
2897 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2898 .info = snd_hdspm_info_autosync_ref, \
2899 .get = snd_hdspm_get_autosync_ref, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002900}
2901
Adrian Knoth0dca1792011-01-26 19:32:14 +01002902static int hdspm_autosync_ref(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002903{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002904 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002905 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002906 unsigned int syncref =
2907 (status >> HDSPM_AES32_syncref_bit) & 0xF;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002908 if (syncref == 0)
2909 return HDSPM_AES32_AUTOSYNC_FROM_WORD;
2910 if (syncref <= 8)
2911 return syncref;
2912 return HDSPM_AES32_AUTOSYNC_FROM_NONE;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002913 } else if (MADI == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002914 /* This looks at the autosync selected sync reference */
2915 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Takashi Iwai763f3562005-06-03 11:25:34 +02002916
Remy Bruno3cee5a62006-10-16 12:46:32 +02002917 switch (status2 & HDSPM_SelSyncRefMask) {
2918 case HDSPM_SelSyncRef_WORD:
2919 return HDSPM_AUTOSYNC_FROM_WORD;
2920 case HDSPM_SelSyncRef_MADI:
2921 return HDSPM_AUTOSYNC_FROM_MADI;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002922 case HDSPM_SelSyncRef_TCO:
2923 return HDSPM_AUTOSYNC_FROM_TCO;
2924 case HDSPM_SelSyncRef_SyncIn:
2925 return HDSPM_AUTOSYNC_FROM_SYNC_IN;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002926 case HDSPM_SelSyncRef_NVALID:
2927 return HDSPM_AUTOSYNC_FROM_NONE;
2928 default:
2929 return 0;
2930 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002931
Takashi Iwai763f3562005-06-03 11:25:34 +02002932 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002933 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002934}
2935
Adrian Knoth0dca1792011-01-26 19:32:14 +01002936
Takashi Iwai98274f02005-11-17 14:52:34 +01002937static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
2938 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002939{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002940 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002941
Adrian Knoth0dca1792011-01-26 19:32:14 +01002942 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002943 static char *texts[] = { "WordClock", "AES1", "AES2", "AES3",
2944 "AES4", "AES5", "AES6", "AES7", "AES8", "None"};
2945
2946 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2947 uinfo->count = 1;
2948 uinfo->value.enumerated.items = 10;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002949 if (uinfo->value.enumerated.item >=
2950 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002951 uinfo->value.enumerated.item =
2952 uinfo->value.enumerated.items - 1;
2953 strcpy(uinfo->value.enumerated.name,
2954 texts[uinfo->value.enumerated.item]);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002955 } else if (MADI == hdspm->io_type) {
2956 static char *texts[] = {"Word Clock", "MADI", "TCO",
2957 "Sync In", "None" };
Remy Bruno3cee5a62006-10-16 12:46:32 +02002958
2959 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2960 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002961 uinfo->value.enumerated.items = 5;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002962 if (uinfo->value.enumerated.item >=
Adrian Knoth0dca1792011-01-26 19:32:14 +01002963 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002964 uinfo->value.enumerated.item =
2965 uinfo->value.enumerated.items - 1;
2966 strcpy(uinfo->value.enumerated.name,
2967 texts[uinfo->value.enumerated.item]);
2968 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002969 return 0;
2970}
2971
Takashi Iwai98274f02005-11-17 14:52:34 +01002972static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
2973 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002974{
Takashi Iwai98274f02005-11-17 14:52:34 +01002975 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002976
Remy Bruno65345992007-08-31 12:21:08 +02002977 ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002978 return 0;
2979}
2980
Adrian Knothf99c7882013-03-10 00:37:26 +01002981
2982
2983#define HDSPM_TCO_VIDEO_INPUT_FORMAT(xname, xindex) \
2984{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2985 .name = xname, \
2986 .access = SNDRV_CTL_ELEM_ACCESS_READ |\
2987 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2988 .info = snd_hdspm_info_tco_video_input_format, \
2989 .get = snd_hdspm_get_tco_video_input_format, \
2990}
2991
2992static int snd_hdspm_info_tco_video_input_format(struct snd_kcontrol *kcontrol,
2993 struct snd_ctl_elem_info *uinfo)
2994{
2995 static char *texts[] = {"No video", "NTSC", "PAL"};
2996 ENUMERATED_CTL_INFO(uinfo, texts);
2997 return 0;
2998}
2999
3000static int snd_hdspm_get_tco_video_input_format(struct snd_kcontrol *kcontrol,
3001 struct snd_ctl_elem_value *ucontrol)
3002{
3003 u32 status;
3004 int ret = 0;
3005
3006 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3007 status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
3008 switch (status & (HDSPM_TCO1_Video_Input_Format_NTSC |
3009 HDSPM_TCO1_Video_Input_Format_PAL)) {
3010 case HDSPM_TCO1_Video_Input_Format_NTSC:
3011 /* ntsc */
3012 ret = 1;
3013 break;
3014 case HDSPM_TCO1_Video_Input_Format_PAL:
3015 /* pal */
3016 ret = 2;
3017 break;
3018 default:
3019 /* no video */
3020 ret = 0;
3021 break;
3022 }
3023 ucontrol->value.enumerated.item[0] = ret;
3024 return 0;
3025}
3026
3027
3028
3029#define HDSPM_TCO_LTC_FRAMES(xname, xindex) \
3030{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3031 .name = xname, \
3032 .access = SNDRV_CTL_ELEM_ACCESS_READ |\
3033 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3034 .info = snd_hdspm_info_tco_ltc_frames, \
3035 .get = snd_hdspm_get_tco_ltc_frames, \
3036}
3037
3038static int snd_hdspm_info_tco_ltc_frames(struct snd_kcontrol *kcontrol,
3039 struct snd_ctl_elem_info *uinfo)
3040{
3041 static char *texts[] = {"No lock", "24 fps", "25 fps", "29.97 fps",
3042 "30 fps"};
3043 ENUMERATED_CTL_INFO(uinfo, texts);
3044 return 0;
3045}
3046
3047static int hdspm_tco_ltc_frames(struct hdspm *hdspm)
3048{
3049 u32 status;
3050 int ret = 0;
3051
3052 status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
3053 if (status & HDSPM_TCO1_LTC_Input_valid) {
3054 switch (status & (HDSPM_TCO1_LTC_Format_LSB |
3055 HDSPM_TCO1_LTC_Format_MSB)) {
3056 case 0:
3057 /* 24 fps */
3058 ret = 1;
3059 break;
3060 case HDSPM_TCO1_LTC_Format_LSB:
3061 /* 25 fps */
3062 ret = 2;
3063 break;
3064 case HDSPM_TCO1_LTC_Format_MSB:
3065 /* 25 fps */
3066 ret = 3;
3067 break;
3068 default:
3069 /* 30 fps */
3070 ret = 4;
3071 break;
3072 }
3073 }
3074
3075 return ret;
3076}
3077
3078static int snd_hdspm_get_tco_ltc_frames(struct snd_kcontrol *kcontrol,
3079 struct snd_ctl_elem_value *ucontrol)
3080{
3081 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3082
3083 ucontrol->value.enumerated.item[0] = hdspm_tco_ltc_frames(hdspm);
3084 return 0;
3085}
3086
Adrian Knothbf0ff872012-12-03 14:55:49 +01003087#define HDSPM_TOGGLE_SETTING(xname, xindex) \
3088{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3089 .name = xname, \
3090 .private_value = xindex, \
3091 .info = snd_hdspm_info_toggle_setting, \
3092 .get = snd_hdspm_get_toggle_setting, \
3093 .put = snd_hdspm_put_toggle_setting \
3094}
3095
3096static int hdspm_toggle_setting(struct hdspm *hdspm, u32 regmask)
3097{
Adrian Knothce13f3f2013-07-05 11:27:55 +02003098 u32 reg;
3099
3100 if (hdspm_is_raydat_or_aio(hdspm))
3101 reg = hdspm->settings_register;
3102 else
3103 reg = hdspm->control_register;
3104
3105 return (reg & regmask) ? 1 : 0;
Adrian Knothbf0ff872012-12-03 14:55:49 +01003106}
3107
3108static int hdspm_set_toggle_setting(struct hdspm *hdspm, u32 regmask, int out)
3109{
Adrian Knothce13f3f2013-07-05 11:27:55 +02003110 u32 *reg;
3111 u32 target_reg;
3112
3113 if (hdspm_is_raydat_or_aio(hdspm)) {
3114 reg = &(hdspm->settings_register);
3115 target_reg = HDSPM_WR_SETTINGS;
3116 } else {
3117 reg = &(hdspm->control_register);
3118 target_reg = HDSPM_controlRegister;
3119 }
3120
Adrian Knothbf0ff872012-12-03 14:55:49 +01003121 if (out)
Adrian Knothce13f3f2013-07-05 11:27:55 +02003122 *reg |= regmask;
Adrian Knothbf0ff872012-12-03 14:55:49 +01003123 else
Adrian Knothce13f3f2013-07-05 11:27:55 +02003124 *reg &= ~regmask;
3125
3126 hdspm_write(hdspm, target_reg, *reg);
Adrian Knothbf0ff872012-12-03 14:55:49 +01003127
3128 return 0;
3129}
3130
3131#define snd_hdspm_info_toggle_setting snd_ctl_boolean_mono_info
3132
3133static int snd_hdspm_get_toggle_setting(struct snd_kcontrol *kcontrol,
3134 struct snd_ctl_elem_value *ucontrol)
3135{
3136 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3137 u32 regmask = kcontrol->private_value;
3138
3139 spin_lock_irq(&hdspm->lock);
3140 ucontrol->value.integer.value[0] = hdspm_toggle_setting(hdspm, regmask);
3141 spin_unlock_irq(&hdspm->lock);
3142 return 0;
3143}
3144
3145static int snd_hdspm_put_toggle_setting(struct snd_kcontrol *kcontrol,
3146 struct snd_ctl_elem_value *ucontrol)
3147{
3148 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3149 u32 regmask = kcontrol->private_value;
3150 int change;
3151 unsigned int val;
3152
3153 if (!snd_hdspm_use_is_exclusive(hdspm))
3154 return -EBUSY;
3155 val = ucontrol->value.integer.value[0] & 1;
3156 spin_lock_irq(&hdspm->lock);
3157 change = (int) val != hdspm_toggle_setting(hdspm, regmask);
3158 hdspm_set_toggle_setting(hdspm, regmask, val);
3159 spin_unlock_irq(&hdspm->lock);
3160 return change;
3161}
3162
Takashi Iwai763f3562005-06-03 11:25:34 +02003163#define HDSPM_INPUT_SELECT(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003164{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3165 .name = xname, \
3166 .index = xindex, \
3167 .info = snd_hdspm_info_input_select, \
3168 .get = snd_hdspm_get_input_select, \
3169 .put = snd_hdspm_put_input_select \
Takashi Iwai763f3562005-06-03 11:25:34 +02003170}
3171
Takashi Iwai98274f02005-11-17 14:52:34 +01003172static int hdspm_input_select(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003173{
3174 return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
3175}
3176
Takashi Iwai98274f02005-11-17 14:52:34 +01003177static int hdspm_set_input_select(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02003178{
3179 if (out)
3180 hdspm->control_register |= HDSPM_InputSelect0;
3181 else
3182 hdspm->control_register &= ~HDSPM_InputSelect0;
3183 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3184
3185 return 0;
3186}
3187
Takashi Iwai98274f02005-11-17 14:52:34 +01003188static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
3189 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003190{
3191 static char *texts[] = { "optical", "coaxial" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003192 ENUMERATED_CTL_INFO(uinfo, texts);
Takashi Iwai763f3562005-06-03 11:25:34 +02003193 return 0;
3194}
3195
Takashi Iwai98274f02005-11-17 14:52:34 +01003196static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
3197 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003198{
Takashi Iwai98274f02005-11-17 14:52:34 +01003199 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003200
3201 spin_lock_irq(&hdspm->lock);
3202 ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
3203 spin_unlock_irq(&hdspm->lock);
3204 return 0;
3205}
3206
Takashi Iwai98274f02005-11-17 14:52:34 +01003207static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
3208 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003209{
Takashi Iwai98274f02005-11-17 14:52:34 +01003210 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003211 int change;
3212 unsigned int val;
3213
3214 if (!snd_hdspm_use_is_exclusive(hdspm))
3215 return -EBUSY;
3216 val = ucontrol->value.integer.value[0] & 1;
3217 spin_lock_irq(&hdspm->lock);
3218 change = (int) val != hdspm_input_select(hdspm);
3219 hdspm_set_input_select(hdspm, val);
3220 spin_unlock_irq(&hdspm->lock);
3221 return change;
3222}
3223
Adrian Knoth0dca1792011-01-26 19:32:14 +01003224
Remy Bruno3cee5a62006-10-16 12:46:32 +02003225#define HDSPM_DS_WIRE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003226{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3227 .name = xname, \
3228 .index = xindex, \
3229 .info = snd_hdspm_info_ds_wire, \
3230 .get = snd_hdspm_get_ds_wire, \
3231 .put = snd_hdspm_put_ds_wire \
Remy Bruno3cee5a62006-10-16 12:46:32 +02003232}
3233
3234static int hdspm_ds_wire(struct hdspm * hdspm)
3235{
3236 return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
3237}
3238
3239static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
3240{
3241 if (ds)
3242 hdspm->control_register |= HDSPM_DS_DoubleWire;
3243 else
3244 hdspm->control_register &= ~HDSPM_DS_DoubleWire;
3245 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3246
3247 return 0;
3248}
3249
3250static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
3251 struct snd_ctl_elem_info *uinfo)
3252{
3253 static char *texts[] = { "Single", "Double" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003254 ENUMERATED_CTL_INFO(uinfo, texts);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003255 return 0;
3256}
3257
3258static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
3259 struct snd_ctl_elem_value *ucontrol)
3260{
3261 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3262
3263 spin_lock_irq(&hdspm->lock);
3264 ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
3265 spin_unlock_irq(&hdspm->lock);
3266 return 0;
3267}
3268
3269static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
3270 struct snd_ctl_elem_value *ucontrol)
3271{
3272 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3273 int change;
3274 unsigned int val;
3275
3276 if (!snd_hdspm_use_is_exclusive(hdspm))
3277 return -EBUSY;
3278 val = ucontrol->value.integer.value[0] & 1;
3279 spin_lock_irq(&hdspm->lock);
3280 change = (int) val != hdspm_ds_wire(hdspm);
3281 hdspm_set_ds_wire(hdspm, val);
3282 spin_unlock_irq(&hdspm->lock);
3283 return change;
3284}
3285
Adrian Knoth0dca1792011-01-26 19:32:14 +01003286
Remy Bruno3cee5a62006-10-16 12:46:32 +02003287#define HDSPM_QS_WIRE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003288{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3289 .name = xname, \
3290 .index = xindex, \
3291 .info = snd_hdspm_info_qs_wire, \
3292 .get = snd_hdspm_get_qs_wire, \
3293 .put = snd_hdspm_put_qs_wire \
Remy Bruno3cee5a62006-10-16 12:46:32 +02003294}
3295
3296static int hdspm_qs_wire(struct hdspm * hdspm)
3297{
3298 if (hdspm->control_register & HDSPM_QS_DoubleWire)
3299 return 1;
3300 if (hdspm->control_register & HDSPM_QS_QuadWire)
3301 return 2;
3302 return 0;
3303}
3304
3305static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
3306{
3307 hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
3308 switch (mode) {
3309 case 0:
3310 break;
3311 case 1:
3312 hdspm->control_register |= HDSPM_QS_DoubleWire;
3313 break;
3314 case 2:
3315 hdspm->control_register |= HDSPM_QS_QuadWire;
3316 break;
3317 }
3318 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3319
3320 return 0;
3321}
3322
3323static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
3324 struct snd_ctl_elem_info *uinfo)
3325{
3326 static char *texts[] = { "Single", "Double", "Quad" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003327 ENUMERATED_CTL_INFO(uinfo, texts);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003328 return 0;
3329}
3330
3331static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
3332 struct snd_ctl_elem_value *ucontrol)
3333{
3334 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3335
3336 spin_lock_irq(&hdspm->lock);
3337 ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
3338 spin_unlock_irq(&hdspm->lock);
3339 return 0;
3340}
3341
3342static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
3343 struct snd_ctl_elem_value *ucontrol)
3344{
3345 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3346 int change;
3347 int val;
3348
3349 if (!snd_hdspm_use_is_exclusive(hdspm))
3350 return -EBUSY;
3351 val = ucontrol->value.integer.value[0];
3352 if (val < 0)
3353 val = 0;
3354 if (val > 2)
3355 val = 2;
3356 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003357 change = val != hdspm_qs_wire(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003358 hdspm_set_qs_wire(hdspm, val);
3359 spin_unlock_irq(&hdspm->lock);
3360 return change;
3361}
3362
Adrian Knothacf14762013-07-05 11:28:00 +02003363#define HDSPM_CONTROL_TRISTATE(xname, xindex) \
3364{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3365 .name = xname, \
3366 .private_value = xindex, \
3367 .info = snd_hdspm_info_tristate, \
3368 .get = snd_hdspm_get_tristate, \
3369 .put = snd_hdspm_put_tristate \
3370}
3371
3372static int hdspm_tristate(struct hdspm *hdspm, u32 regmask)
3373{
3374 u32 reg = hdspm->settings_register & (regmask * 3);
3375 return reg / regmask;
3376}
3377
3378static int hdspm_set_tristate(struct hdspm *hdspm, int mode, u32 regmask)
3379{
3380 hdspm->settings_register &= ~(regmask * 3);
3381 hdspm->settings_register |= (regmask * mode);
3382 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
3383
3384 return 0;
3385}
3386
3387static int snd_hdspm_info_tristate(struct snd_kcontrol *kcontrol,
3388 struct snd_ctl_elem_info *uinfo)
3389{
3390 u32 regmask = kcontrol->private_value;
3391
3392 static char *texts_spdif[] = { "Optical", "Coaxial", "Internal" };
3393 static char *texts_levels[] = { "Hi Gain", "+4 dBu", "-10 dBV" };
3394
3395 switch (regmask) {
3396 case HDSPM_c0_Input0:
3397 ENUMERATED_CTL_INFO(uinfo, texts_spdif);
3398 break;
3399 default:
3400 ENUMERATED_CTL_INFO(uinfo, texts_levels);
3401 break;
3402 }
3403 return 0;
3404}
3405
3406static int snd_hdspm_get_tristate(struct snd_kcontrol *kcontrol,
3407 struct snd_ctl_elem_value *ucontrol)
3408{
3409 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3410 u32 regmask = kcontrol->private_value;
3411
3412 spin_lock_irq(&hdspm->lock);
3413 ucontrol->value.enumerated.item[0] = hdspm_tristate(hdspm, regmask);
3414 spin_unlock_irq(&hdspm->lock);
3415 return 0;
3416}
3417
3418static int snd_hdspm_put_tristate(struct snd_kcontrol *kcontrol,
3419 struct snd_ctl_elem_value *ucontrol)
3420{
3421 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3422 u32 regmask = kcontrol->private_value;
3423 int change;
3424 int val;
3425
3426 if (!snd_hdspm_use_is_exclusive(hdspm))
3427 return -EBUSY;
3428 val = ucontrol->value.integer.value[0];
3429 if (val < 0)
3430 val = 0;
3431 if (val > 2)
3432 val = 2;
3433
3434 spin_lock_irq(&hdspm->lock);
3435 change = val != hdspm_tristate(hdspm, regmask);
3436 hdspm_set_tristate(hdspm, val, regmask);
3437 spin_unlock_irq(&hdspm->lock);
3438 return change;
3439}
3440
Adrian Knoth700d1ef2011-07-29 03:11:02 +02003441#define HDSPM_MADI_SPEEDMODE(xname, xindex) \
3442{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3443 .name = xname, \
3444 .index = xindex, \
3445 .info = snd_hdspm_info_madi_speedmode, \
3446 .get = snd_hdspm_get_madi_speedmode, \
3447 .put = snd_hdspm_put_madi_speedmode \
3448}
3449
3450static int hdspm_madi_speedmode(struct hdspm *hdspm)
3451{
3452 if (hdspm->control_register & HDSPM_QuadSpeed)
3453 return 2;
3454 if (hdspm->control_register & HDSPM_DoubleSpeed)
3455 return 1;
3456 return 0;
3457}
3458
3459static int hdspm_set_madi_speedmode(struct hdspm *hdspm, int mode)
3460{
3461 hdspm->control_register &= ~(HDSPM_DoubleSpeed | HDSPM_QuadSpeed);
3462 switch (mode) {
3463 case 0:
3464 break;
3465 case 1:
3466 hdspm->control_register |= HDSPM_DoubleSpeed;
3467 break;
3468 case 2:
3469 hdspm->control_register |= HDSPM_QuadSpeed;
3470 break;
3471 }
3472 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3473
3474 return 0;
3475}
3476
3477static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol,
3478 struct snd_ctl_elem_info *uinfo)
3479{
3480 static char *texts[] = { "Single", "Double", "Quad" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003481 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth700d1ef2011-07-29 03:11:02 +02003482 return 0;
3483}
3484
3485static int snd_hdspm_get_madi_speedmode(struct snd_kcontrol *kcontrol,
3486 struct snd_ctl_elem_value *ucontrol)
3487{
3488 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3489
3490 spin_lock_irq(&hdspm->lock);
3491 ucontrol->value.enumerated.item[0] = hdspm_madi_speedmode(hdspm);
3492 spin_unlock_irq(&hdspm->lock);
3493 return 0;
3494}
3495
3496static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol,
3497 struct snd_ctl_elem_value *ucontrol)
3498{
3499 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3500 int change;
3501 int val;
3502
3503 if (!snd_hdspm_use_is_exclusive(hdspm))
3504 return -EBUSY;
3505 val = ucontrol->value.integer.value[0];
3506 if (val < 0)
3507 val = 0;
3508 if (val > 2)
3509 val = 2;
3510 spin_lock_irq(&hdspm->lock);
3511 change = val != hdspm_madi_speedmode(hdspm);
3512 hdspm_set_madi_speedmode(hdspm, val);
3513 spin_unlock_irq(&hdspm->lock);
3514 return change;
3515}
Takashi Iwai763f3562005-06-03 11:25:34 +02003516
3517#define HDSPM_MIXER(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003518{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
3519 .name = xname, \
3520 .index = xindex, \
3521 .device = 0, \
3522 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
3523 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3524 .info = snd_hdspm_info_mixer, \
3525 .get = snd_hdspm_get_mixer, \
3526 .put = snd_hdspm_put_mixer \
Takashi Iwai763f3562005-06-03 11:25:34 +02003527}
3528
Takashi Iwai98274f02005-11-17 14:52:34 +01003529static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
3530 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003531{
3532 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3533 uinfo->count = 3;
3534 uinfo->value.integer.min = 0;
3535 uinfo->value.integer.max = 65535;
3536 uinfo->value.integer.step = 1;
3537 return 0;
3538}
3539
Takashi Iwai98274f02005-11-17 14:52:34 +01003540static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
3541 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003542{
Takashi Iwai98274f02005-11-17 14:52:34 +01003543 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003544 int source;
3545 int destination;
3546
3547 source = ucontrol->value.integer.value[0];
3548 if (source < 0)
3549 source = 0;
3550 else if (source >= 2 * HDSPM_MAX_CHANNELS)
3551 source = 2 * HDSPM_MAX_CHANNELS - 1;
3552
3553 destination = ucontrol->value.integer.value[1];
3554 if (destination < 0)
3555 destination = 0;
3556 else if (destination >= HDSPM_MAX_CHANNELS)
3557 destination = HDSPM_MAX_CHANNELS - 1;
3558
3559 spin_lock_irq(&hdspm->lock);
3560 if (source >= HDSPM_MAX_CHANNELS)
3561 ucontrol->value.integer.value[2] =
3562 hdspm_read_pb_gain(hdspm, destination,
3563 source - HDSPM_MAX_CHANNELS);
3564 else
3565 ucontrol->value.integer.value[2] =
3566 hdspm_read_in_gain(hdspm, destination, source);
3567
3568 spin_unlock_irq(&hdspm->lock);
3569
3570 return 0;
3571}
3572
Takashi Iwai98274f02005-11-17 14:52:34 +01003573static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
3574 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003575{
Takashi Iwai98274f02005-11-17 14:52:34 +01003576 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003577 int change;
3578 int source;
3579 int destination;
3580 int gain;
3581
3582 if (!snd_hdspm_use_is_exclusive(hdspm))
3583 return -EBUSY;
3584
3585 source = ucontrol->value.integer.value[0];
3586 destination = ucontrol->value.integer.value[1];
3587
3588 if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
3589 return -1;
3590 if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
3591 return -1;
3592
3593 gain = ucontrol->value.integer.value[2];
3594
3595 spin_lock_irq(&hdspm->lock);
3596
3597 if (source >= HDSPM_MAX_CHANNELS)
3598 change = gain != hdspm_read_pb_gain(hdspm, destination,
3599 source -
3600 HDSPM_MAX_CHANNELS);
3601 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003602 change = gain != hdspm_read_in_gain(hdspm, destination,
3603 source);
Takashi Iwai763f3562005-06-03 11:25:34 +02003604
3605 if (change) {
3606 if (source >= HDSPM_MAX_CHANNELS)
3607 hdspm_write_pb_gain(hdspm, destination,
3608 source - HDSPM_MAX_CHANNELS,
3609 gain);
3610 else
3611 hdspm_write_in_gain(hdspm, destination, source,
3612 gain);
3613 }
3614 spin_unlock_irq(&hdspm->lock);
3615
3616 return change;
3617}
3618
3619/* The simple mixer control(s) provide gain control for the
3620 basic 1:1 mappings of playback streams to output
Adrian Knoth0dca1792011-01-26 19:32:14 +01003621 streams.
Takashi Iwai763f3562005-06-03 11:25:34 +02003622*/
3623
3624#define HDSPM_PLAYBACK_MIXER \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003625{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3626 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
3627 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3628 .info = snd_hdspm_info_playback_mixer, \
3629 .get = snd_hdspm_get_playback_mixer, \
3630 .put = snd_hdspm_put_playback_mixer \
Takashi Iwai763f3562005-06-03 11:25:34 +02003631}
3632
Takashi Iwai98274f02005-11-17 14:52:34 +01003633static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
3634 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003635{
3636 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3637 uinfo->count = 1;
3638 uinfo->value.integer.min = 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003639 uinfo->value.integer.max = 64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003640 uinfo->value.integer.step = 1;
3641 return 0;
3642}
3643
Takashi Iwai98274f02005-11-17 14:52:34 +01003644static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
3645 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003646{
Takashi Iwai98274f02005-11-17 14:52:34 +01003647 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003648 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003649
3650 channel = ucontrol->id.index - 1;
3651
Takashi Iwaida3cec32008-08-08 17:12:14 +02003652 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3653 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003654
Takashi Iwai763f3562005-06-03 11:25:34 +02003655 spin_lock_irq(&hdspm->lock);
3656 ucontrol->value.integer.value[0] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003657 (hdspm_read_pb_gain(hdspm, channel, channel)*64)/UNITY_GAIN;
Takashi Iwai763f3562005-06-03 11:25:34 +02003658 spin_unlock_irq(&hdspm->lock);
3659
Takashi Iwai763f3562005-06-03 11:25:34 +02003660 return 0;
3661}
3662
Takashi Iwai98274f02005-11-17 14:52:34 +01003663static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
3664 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003665{
Takashi Iwai98274f02005-11-17 14:52:34 +01003666 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003667 int change;
3668 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003669 int gain;
3670
3671 if (!snd_hdspm_use_is_exclusive(hdspm))
3672 return -EBUSY;
3673
3674 channel = ucontrol->id.index - 1;
3675
Takashi Iwaida3cec32008-08-08 17:12:14 +02003676 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3677 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003678
Adrian Knoth0dca1792011-01-26 19:32:14 +01003679 gain = ucontrol->value.integer.value[0]*UNITY_GAIN/64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003680
3681 spin_lock_irq(&hdspm->lock);
3682 change =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003683 gain != hdspm_read_pb_gain(hdspm, channel,
3684 channel);
Takashi Iwai763f3562005-06-03 11:25:34 +02003685 if (change)
Adrian Knoth0dca1792011-01-26 19:32:14 +01003686 hdspm_write_pb_gain(hdspm, channel, channel,
Takashi Iwai763f3562005-06-03 11:25:34 +02003687 gain);
3688 spin_unlock_irq(&hdspm->lock);
3689 return change;
3690}
3691
Adrian Knoth0dca1792011-01-26 19:32:14 +01003692#define HDSPM_SYNC_CHECK(xname, xindex) \
3693{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3694 .name = xname, \
3695 .private_value = xindex, \
3696 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3697 .info = snd_hdspm_info_sync_check, \
3698 .get = snd_hdspm_get_sync_check \
Takashi Iwai763f3562005-06-03 11:25:34 +02003699}
3700
Adrian Knoth34542212013-03-10 00:37:25 +01003701#define HDSPM_TCO_LOCK_CHECK(xname, xindex) \
3702{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3703 .name = xname, \
3704 .private_value = xindex, \
3705 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3706 .info = snd_hdspm_tco_info_lock_check, \
3707 .get = snd_hdspm_get_sync_check \
3708}
3709
3710
Adrian Knoth0dca1792011-01-26 19:32:14 +01003711
Takashi Iwai98274f02005-11-17 14:52:34 +01003712static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
3713 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003714{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003715 static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003716 ENUMERATED_CTL_INFO(uinfo, texts);
Takashi Iwai763f3562005-06-03 11:25:34 +02003717 return 0;
3718}
3719
Adrian Knoth34542212013-03-10 00:37:25 +01003720static int snd_hdspm_tco_info_lock_check(struct snd_kcontrol *kcontrol,
3721 struct snd_ctl_elem_info *uinfo)
3722{
3723 static char *texts[] = { "No Lock", "Lock" };
3724 ENUMERATED_CTL_INFO(uinfo, texts);
3725 return 0;
3726}
3727
Adrian Knoth0dca1792011-01-26 19:32:14 +01003728static int hdspm_wc_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003729{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003730 int status, status2;
3731
3732 switch (hdspm->io_type) {
3733 case AES32:
3734 status = hdspm_read(hdspm, HDSPM_statusRegister);
Andre Schramm56bde0f2013-01-09 14:40:18 +01003735 if (status & HDSPM_AES32_wcLock) {
3736 if (status & HDSPM_AES32_wcSync)
3737 return 2;
3738 else
3739 return 1;
3740 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02003741 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003742 break;
3743
3744 case MADI:
3745 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003746 if (status2 & HDSPM_wcLock) {
3747 if (status2 & HDSPM_wcSync)
3748 return 2;
3749 else
3750 return 1;
3751 }
3752 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003753 break;
3754
3755 case RayDAT:
3756 case AIO:
3757 status = hdspm_read(hdspm, HDSPM_statusRegister);
3758
3759 if (status & 0x2000000)
3760 return 2;
3761 else if (status & 0x1000000)
3762 return 1;
3763 return 0;
3764
3765 break;
3766
3767 case MADIface:
3768 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02003769 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003770
Takashi Iwai763f3562005-06-03 11:25:34 +02003771
Adrian Knoth0dca1792011-01-26 19:32:14 +01003772 return 3;
Takashi Iwai763f3562005-06-03 11:25:34 +02003773}
3774
3775
Adrian Knoth0dca1792011-01-26 19:32:14 +01003776static int hdspm_madi_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003777{
3778 int status = hdspm_read(hdspm, HDSPM_statusRegister);
3779 if (status & HDSPM_madiLock) {
3780 if (status & HDSPM_madiSync)
3781 return 2;
3782 else
3783 return 1;
3784 }
3785 return 0;
3786}
3787
Adrian Knoth0dca1792011-01-26 19:32:14 +01003788
3789static int hdspm_s1_sync_check(struct hdspm *hdspm, int idx)
3790{
3791 int status, lock, sync;
3792
3793 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3794
3795 lock = (status & (0x1<<idx)) ? 1 : 0;
3796 sync = (status & (0x100<<idx)) ? 1 : 0;
3797
3798 if (lock && sync)
3799 return 2;
3800 else if (lock)
3801 return 1;
3802 return 0;
3803}
3804
3805
3806static int hdspm_sync_in_sync_check(struct hdspm *hdspm)
3807{
3808 int status, lock = 0, sync = 0;
3809
3810 switch (hdspm->io_type) {
3811 case RayDAT:
3812 case AIO:
3813 status = hdspm_read(hdspm, HDSPM_RD_STATUS_3);
3814 lock = (status & 0x400) ? 1 : 0;
3815 sync = (status & 0x800) ? 1 : 0;
3816 break;
3817
3818 case MADI:
Adrian Knoth2e0452f2012-10-19 17:42:27 +02003819 status = hdspm_read(hdspm, HDSPM_statusRegister);
3820 lock = (status & HDSPM_syncInLock) ? 1 : 0;
3821 sync = (status & HDSPM_syncInSync) ? 1 : 0;
3822 break;
3823
Adrian Knoth0dca1792011-01-26 19:32:14 +01003824 case AES32:
3825 status = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth9a215f42012-10-19 17:42:28 +02003826 lock = (status & 0x100000) ? 1 : 0;
3827 sync = (status & 0x200000) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003828 break;
3829
3830 case MADIface:
3831 break;
3832 }
3833
3834 if (lock && sync)
3835 return 2;
3836 else if (lock)
3837 return 1;
3838
3839 return 0;
3840}
3841
3842static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx)
3843{
3844 int status2, lock, sync;
3845 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
3846
3847 lock = (status2 & (0x0080 >> idx)) ? 1 : 0;
3848 sync = (status2 & (0x8000 >> idx)) ? 1 : 0;
3849
3850 if (sync)
3851 return 2;
3852 else if (lock)
3853 return 1;
3854 return 0;
3855}
3856
Adrian Knoth34542212013-03-10 00:37:25 +01003857static int hdspm_tco_input_check(struct hdspm *hdspm, u32 mask)
3858{
3859 u32 status;
3860 status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
3861
3862 return (status & mask) ? 1 : 0;
3863}
3864
Adrian Knoth0dca1792011-01-26 19:32:14 +01003865
3866static int hdspm_tco_sync_check(struct hdspm *hdspm)
3867{
3868 int status;
3869
3870 if (hdspm->tco) {
3871 switch (hdspm->io_type) {
3872 case MADI:
Adrian Knothb0bf5502013-07-05 11:28:05 +02003873 status = hdspm_read(hdspm, HDSPM_statusRegister);
3874 if (status & HDSPM_tcoLockMadi) {
3875 if (status & HDSPM_tcoSync)
3876 return 2;
3877 else
3878 return 1;
3879 }
3880 return 0;
3881 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003882 case AES32:
3883 status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knothb0bf5502013-07-05 11:28:05 +02003884 if (status & HDSPM_tcoLockAes) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01003885 if (status & HDSPM_tcoSync)
3886 return 2;
3887 else
3888 return 1;
3889 }
3890 return 0;
3891
3892 break;
3893
3894 case RayDAT:
3895 case AIO:
3896 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3897
3898 if (status & 0x8000000)
3899 return 2; /* Sync */
3900 if (status & 0x4000000)
3901 return 1; /* Lock */
3902 return 0; /* No signal */
3903 break;
3904
3905 default:
3906 break;
3907 }
3908 }
3909
3910 return 3; /* N/A */
3911}
3912
3913
3914static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
3915 struct snd_ctl_elem_value *ucontrol)
3916{
3917 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3918 int val = -1;
3919
3920 switch (hdspm->io_type) {
3921 case RayDAT:
3922 switch (kcontrol->private_value) {
3923 case 0: /* WC */
3924 val = hdspm_wc_sync_check(hdspm); break;
3925 case 7: /* TCO */
3926 val = hdspm_tco_sync_check(hdspm); break;
3927 case 8: /* SYNC IN */
3928 val = hdspm_sync_in_sync_check(hdspm); break;
3929 default:
Adrian Knothd1a3c982012-11-07 18:00:09 +01003930 val = hdspm_s1_sync_check(hdspm,
3931 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003932 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02003933 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003934
3935 case AIO:
3936 switch (kcontrol->private_value) {
3937 case 0: /* WC */
3938 val = hdspm_wc_sync_check(hdspm); break;
3939 case 4: /* TCO */
3940 val = hdspm_tco_sync_check(hdspm); break;
3941 case 5: /* SYNC IN */
3942 val = hdspm_sync_in_sync_check(hdspm); break;
3943 default:
Adrian Knoth1cb7dbf2013-07-05 11:28:03 +02003944 val = hdspm_s1_sync_check(hdspm,
3945 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003946 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02003947 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003948
3949 case MADI:
3950 switch (kcontrol->private_value) {
3951 case 0: /* WC */
3952 val = hdspm_wc_sync_check(hdspm); break;
3953 case 1: /* MADI */
3954 val = hdspm_madi_sync_check(hdspm); break;
3955 case 2: /* TCO */
3956 val = hdspm_tco_sync_check(hdspm); break;
3957 case 3: /* SYNC_IN */
3958 val = hdspm_sync_in_sync_check(hdspm); break;
3959 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02003960 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003961
3962 case MADIface:
3963 val = hdspm_madi_sync_check(hdspm); /* MADI */
3964 break;
3965
3966 case AES32:
3967 switch (kcontrol->private_value) {
3968 case 0: /* WC */
3969 val = hdspm_wc_sync_check(hdspm); break;
3970 case 9: /* TCO */
3971 val = hdspm_tco_sync_check(hdspm); break;
3972 case 10 /* SYNC IN */:
3973 val = hdspm_sync_in_sync_check(hdspm); break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01003974 default: /* AES1 to AES8 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01003975 val = hdspm_aes_sync_check(hdspm,
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01003976 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003977 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02003978 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003979
3980 }
3981
Adrian Knoth34542212013-03-10 00:37:25 +01003982 if (hdspm->tco) {
3983 switch (kcontrol->private_value) {
3984 case 11:
3985 /* Check TCO for lock state of its current input */
3986 val = hdspm_tco_input_check(hdspm, HDSPM_TCO1_TCO_lock);
3987 break;
3988 case 12:
3989 /* Check TCO for valid time code on LTC input. */
3990 val = hdspm_tco_input_check(hdspm,
3991 HDSPM_TCO1_LTC_Input_valid);
3992 break;
3993 default:
3994 break;
3995 }
3996 }
3997
Adrian Knoth0dca1792011-01-26 19:32:14 +01003998 if (-1 == val)
3999 val = 3;
4000
4001 ucontrol->value.enumerated.item[0] = val;
4002 return 0;
4003}
4004
4005
4006
4007/**
4008 * TCO controls
4009 **/
4010static void hdspm_tco_write(struct hdspm *hdspm)
4011{
4012 unsigned int tc[4] = { 0, 0, 0, 0};
4013
4014 switch (hdspm->tco->input) {
4015 case 0:
4016 tc[2] |= HDSPM_TCO2_set_input_MSB;
4017 break;
4018 case 1:
4019 tc[2] |= HDSPM_TCO2_set_input_LSB;
4020 break;
4021 default:
4022 break;
4023 }
4024
4025 switch (hdspm->tco->framerate) {
4026 case 1:
4027 tc[1] |= HDSPM_TCO1_LTC_Format_LSB;
4028 break;
4029 case 2:
4030 tc[1] |= HDSPM_TCO1_LTC_Format_MSB;
4031 break;
4032 case 3:
4033 tc[1] |= HDSPM_TCO1_LTC_Format_MSB +
4034 HDSPM_TCO1_set_drop_frame_flag;
4035 break;
4036 case 4:
4037 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
4038 HDSPM_TCO1_LTC_Format_MSB;
4039 break;
4040 case 5:
4041 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
4042 HDSPM_TCO1_LTC_Format_MSB +
4043 HDSPM_TCO1_set_drop_frame_flag;
4044 break;
4045 default:
4046 break;
4047 }
4048
4049 switch (hdspm->tco->wordclock) {
4050 case 1:
4051 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_LSB;
4052 break;
4053 case 2:
4054 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_MSB;
4055 break;
4056 default:
4057 break;
4058 }
4059
4060 switch (hdspm->tco->samplerate) {
4061 case 1:
4062 tc[2] |= HDSPM_TCO2_set_freq;
4063 break;
4064 case 2:
4065 tc[2] |= HDSPM_TCO2_set_freq_from_app;
4066 break;
4067 default:
4068 break;
4069 }
4070
4071 switch (hdspm->tco->pull) {
4072 case 1:
4073 tc[2] |= HDSPM_TCO2_set_pull_up;
4074 break;
4075 case 2:
4076 tc[2] |= HDSPM_TCO2_set_pull_down;
4077 break;
4078 case 3:
4079 tc[2] |= HDSPM_TCO2_set_pull_up + HDSPM_TCO2_set_01_4;
4080 break;
4081 case 4:
4082 tc[2] |= HDSPM_TCO2_set_pull_down + HDSPM_TCO2_set_01_4;
4083 break;
4084 default:
4085 break;
4086 }
4087
4088 if (1 == hdspm->tco->term) {
4089 tc[2] |= HDSPM_TCO2_set_term_75R;
4090 }
4091
4092 hdspm_write(hdspm, HDSPM_WR_TCO, tc[0]);
4093 hdspm_write(hdspm, HDSPM_WR_TCO+4, tc[1]);
4094 hdspm_write(hdspm, HDSPM_WR_TCO+8, tc[2]);
4095 hdspm_write(hdspm, HDSPM_WR_TCO+12, tc[3]);
4096}
4097
4098
4099#define HDSPM_TCO_SAMPLE_RATE(xname, xindex) \
4100{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4101 .name = xname, \
4102 .index = xindex, \
4103 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4104 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4105 .info = snd_hdspm_info_tco_sample_rate, \
4106 .get = snd_hdspm_get_tco_sample_rate, \
4107 .put = snd_hdspm_put_tco_sample_rate \
4108}
4109
4110static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol,
4111 struct snd_ctl_elem_info *uinfo)
4112{
4113 static char *texts[] = { "44.1 kHz", "48 kHz" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004114 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004115 return 0;
4116}
4117
4118static int snd_hdspm_get_tco_sample_rate(struct snd_kcontrol *kcontrol,
4119 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02004120{
Takashi Iwai98274f02005-11-17 14:52:34 +01004121 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02004122
Adrian Knoth0dca1792011-01-26 19:32:14 +01004123 ucontrol->value.enumerated.item[0] = hdspm->tco->samplerate;
4124
Takashi Iwai763f3562005-06-03 11:25:34 +02004125 return 0;
4126}
4127
Adrian Knoth0dca1792011-01-26 19:32:14 +01004128static int snd_hdspm_put_tco_sample_rate(struct snd_kcontrol *kcontrol,
4129 struct snd_ctl_elem_value *ucontrol)
Remy Bruno3cee5a62006-10-16 12:46:32 +02004130{
Adrian Knoth0dca1792011-01-26 19:32:14 +01004131 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4132
4133 if (hdspm->tco->samplerate != ucontrol->value.enumerated.item[0]) {
4134 hdspm->tco->samplerate = ucontrol->value.enumerated.item[0];
4135
4136 hdspm_tco_write(hdspm);
4137
4138 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004139 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01004140
Remy Bruno3cee5a62006-10-16 12:46:32 +02004141 return 0;
4142}
4143
Adrian Knoth0dca1792011-01-26 19:32:14 +01004144
4145#define HDSPM_TCO_PULL(xname, xindex) \
4146{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4147 .name = xname, \
4148 .index = xindex, \
4149 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4150 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4151 .info = snd_hdspm_info_tco_pull, \
4152 .get = snd_hdspm_get_tco_pull, \
4153 .put = snd_hdspm_put_tco_pull \
4154}
4155
4156static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol,
4157 struct snd_ctl_elem_info *uinfo)
4158{
4159 static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004160 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004161 return 0;
4162}
4163
4164static int snd_hdspm_get_tco_pull(struct snd_kcontrol *kcontrol,
4165 struct snd_ctl_elem_value *ucontrol)
4166{
4167 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4168
4169 ucontrol->value.enumerated.item[0] = hdspm->tco->pull;
4170
4171 return 0;
4172}
4173
4174static int snd_hdspm_put_tco_pull(struct snd_kcontrol *kcontrol,
4175 struct snd_ctl_elem_value *ucontrol)
4176{
4177 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4178
4179 if (hdspm->tco->pull != ucontrol->value.enumerated.item[0]) {
4180 hdspm->tco->pull = ucontrol->value.enumerated.item[0];
4181
4182 hdspm_tco_write(hdspm);
4183
4184 return 1;
4185 }
4186
4187 return 0;
4188}
4189
4190#define HDSPM_TCO_WCK_CONVERSION(xname, xindex) \
4191{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4192 .name = xname, \
4193 .index = xindex, \
4194 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4195 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4196 .info = snd_hdspm_info_tco_wck_conversion, \
4197 .get = snd_hdspm_get_tco_wck_conversion, \
4198 .put = snd_hdspm_put_tco_wck_conversion \
4199}
4200
4201static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4202 struct snd_ctl_elem_info *uinfo)
4203{
4204 static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004205 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004206 return 0;
4207}
4208
4209static int snd_hdspm_get_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4210 struct snd_ctl_elem_value *ucontrol)
4211{
4212 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4213
4214 ucontrol->value.enumerated.item[0] = hdspm->tco->wordclock;
4215
4216 return 0;
4217}
4218
4219static int snd_hdspm_put_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4220 struct snd_ctl_elem_value *ucontrol)
4221{
4222 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4223
4224 if (hdspm->tco->wordclock != ucontrol->value.enumerated.item[0]) {
4225 hdspm->tco->wordclock = ucontrol->value.enumerated.item[0];
4226
4227 hdspm_tco_write(hdspm);
4228
4229 return 1;
4230 }
4231
4232 return 0;
4233}
4234
4235
4236#define HDSPM_TCO_FRAME_RATE(xname, xindex) \
4237{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4238 .name = xname, \
4239 .index = xindex, \
4240 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4241 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4242 .info = snd_hdspm_info_tco_frame_rate, \
4243 .get = snd_hdspm_get_tco_frame_rate, \
4244 .put = snd_hdspm_put_tco_frame_rate \
4245}
4246
4247static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol,
4248 struct snd_ctl_elem_info *uinfo)
4249{
4250 static char *texts[] = { "24 fps", "25 fps", "29.97fps",
4251 "29.97 dfps", "30 fps", "30 dfps" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004252 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004253 return 0;
4254}
4255
4256static int snd_hdspm_get_tco_frame_rate(struct snd_kcontrol *kcontrol,
Remy Bruno3cee5a62006-10-16 12:46:32 +02004257 struct snd_ctl_elem_value *ucontrol)
4258{
Remy Bruno3cee5a62006-10-16 12:46:32 +02004259 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4260
Adrian Knoth0dca1792011-01-26 19:32:14 +01004261 ucontrol->value.enumerated.item[0] = hdspm->tco->framerate;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004262
Remy Bruno3cee5a62006-10-16 12:46:32 +02004263 return 0;
4264}
Takashi Iwai763f3562005-06-03 11:25:34 +02004265
Adrian Knoth0dca1792011-01-26 19:32:14 +01004266static int snd_hdspm_put_tco_frame_rate(struct snd_kcontrol *kcontrol,
4267 struct snd_ctl_elem_value *ucontrol)
4268{
4269 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4270
4271 if (hdspm->tco->framerate != ucontrol->value.enumerated.item[0]) {
4272 hdspm->tco->framerate = ucontrol->value.enumerated.item[0];
4273
4274 hdspm_tco_write(hdspm);
4275
4276 return 1;
4277 }
4278
4279 return 0;
4280}
4281
4282
4283#define HDSPM_TCO_SYNC_SOURCE(xname, xindex) \
4284{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4285 .name = xname, \
4286 .index = xindex, \
4287 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4288 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4289 .info = snd_hdspm_info_tco_sync_source, \
4290 .get = snd_hdspm_get_tco_sync_source, \
4291 .put = snd_hdspm_put_tco_sync_source \
4292}
4293
4294static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol,
4295 struct snd_ctl_elem_info *uinfo)
4296{
4297 static char *texts[] = { "LTC", "Video", "WCK" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004298 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004299 return 0;
4300}
4301
4302static int snd_hdspm_get_tco_sync_source(struct snd_kcontrol *kcontrol,
4303 struct snd_ctl_elem_value *ucontrol)
4304{
4305 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4306
4307 ucontrol->value.enumerated.item[0] = hdspm->tco->input;
4308
4309 return 0;
4310}
4311
4312static int snd_hdspm_put_tco_sync_source(struct snd_kcontrol *kcontrol,
4313 struct snd_ctl_elem_value *ucontrol)
4314{
4315 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4316
4317 if (hdspm->tco->input != ucontrol->value.enumerated.item[0]) {
4318 hdspm->tco->input = ucontrol->value.enumerated.item[0];
4319
4320 hdspm_tco_write(hdspm);
4321
4322 return 1;
4323 }
4324
4325 return 0;
4326}
4327
4328
4329#define HDSPM_TCO_WORD_TERM(xname, xindex) \
4330{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4331 .name = xname, \
4332 .index = xindex, \
4333 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4334 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4335 .info = snd_hdspm_info_tco_word_term, \
4336 .get = snd_hdspm_get_tco_word_term, \
4337 .put = snd_hdspm_put_tco_word_term \
4338}
4339
4340static int snd_hdspm_info_tco_word_term(struct snd_kcontrol *kcontrol,
4341 struct snd_ctl_elem_info *uinfo)
4342{
4343 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
4344 uinfo->count = 1;
4345 uinfo->value.integer.min = 0;
4346 uinfo->value.integer.max = 1;
4347
4348 return 0;
4349}
4350
4351
4352static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol,
4353 struct snd_ctl_elem_value *ucontrol)
4354{
4355 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4356
4357 ucontrol->value.enumerated.item[0] = hdspm->tco->term;
4358
4359 return 0;
4360}
4361
4362
4363static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol,
4364 struct snd_ctl_elem_value *ucontrol)
4365{
4366 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4367
4368 if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) {
4369 hdspm->tco->term = ucontrol->value.enumerated.item[0];
4370
4371 hdspm_tco_write(hdspm);
4372
4373 return 1;
4374 }
4375
4376 return 0;
4377}
4378
4379
4380
Takashi Iwai763f3562005-06-03 11:25:34 +02004381
Remy Bruno3cee5a62006-10-16 12:46:32 +02004382static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004383 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004384 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Takashi Iwai763f3562005-06-03 11:25:34 +02004385 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4386 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4387 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4388 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Adrian Knothb8812c52012-10-19 17:42:26 +02004389 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004390 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4391 HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
Adrian Knoth930f4ff2012-10-19 17:42:29 +02004392 HDSPM_SYNC_CHECK("TCO SyncCheck", 2),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004393 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
Adrian Knothc9e16682012-12-03 14:55:50 +01004394 HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
4395 HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
Adrian Knoth696be0f2013-03-10 00:37:23 +01004396 HDSPM_TOGGLE_SETTING("Disable 96K frames", HDSPM_SMUX),
Adrian Knothc9e16682012-12-03 14:55:50 +01004397 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
4398 HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
Adrian Knoth700d1ef2011-07-29 03:11:02 +02004399 HDSPM_INPUT_SELECT("Input Select", 0),
4400 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004401};
4402
4403
4404static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
4405 HDSPM_MIXER("Mixer", 0),
4406 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4407 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4408 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4409 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4410 HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
Adrian Knothc9e16682012-12-03 14:55:50 +01004411 HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
4412 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
4413 HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
Adrian Knoth700d1ef2011-07-29 03:11:02 +02004414 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004415};
4416
Adrian Knoth0dca1792011-01-26 19:32:14 +01004417static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004418 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004419 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004420 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4421 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4422 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4423 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004424 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004425 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4426 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4427 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4428 HDSPM_SYNC_CHECK("ADAT SyncCheck", 3),
4429 HDSPM_SYNC_CHECK("TCO SyncCheck", 4),
4430 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 5),
4431 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4432 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4433 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4434 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT Frequency", 3),
4435 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 4),
Adrian Knothfb0f1212013-07-05 11:27:58 +02004436 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5),
Adrian Knoth42f4c122013-07-05 11:28:01 +02004437 HDSPM_CONTROL_TRISTATE("S/PDIF Input", HDSPM_c0_Input0),
Adrian Knothfb0f1212013-07-05 11:27:58 +02004438 HDSPM_TOGGLE_SETTING("S/PDIF Out Optical", HDSPM_c0_Spdif_Opt),
4439 HDSPM_TOGGLE_SETTING("S/PDIF Out Professional", HDSPM_c0_Pro),
4440 HDSPM_TOGGLE_SETTING("ADAT internal (AEB/TEB)", HDSPM_c0_AEB1),
4441 HDSPM_TOGGLE_SETTING("XLR Breakout Cable", HDSPM_c0_Sym6db),
Adrian Knoth42f4c122013-07-05 11:28:01 +02004442 HDSPM_TOGGLE_SETTING("Single Speed WordClock Out", HDSPM_c0_Wck48),
4443 HDSPM_CONTROL_TRISTATE("Input Level", HDSPM_c0_AD_GAIN0),
4444 HDSPM_CONTROL_TRISTATE("Output Level", HDSPM_c0_DA_GAIN0),
4445 HDSPM_CONTROL_TRISTATE("Phones Level", HDSPM_c0_PH_GAIN0)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004446
4447 /*
4448 HDSPM_INPUT_SELECT("Input Select", 0),
4449 HDSPM_SPDIF_OPTICAL("SPDIF Out Optical", 0),
4450 HDSPM_PROFESSIONAL("SPDIF Out Professional", 0);
4451 HDSPM_SPDIF_IN("SPDIF In", 0);
4452 HDSPM_BREAKOUT_CABLE("Breakout Cable", 0);
4453 HDSPM_INPUT_LEVEL("Input Level", 0);
4454 HDSPM_OUTPUT_LEVEL("Output Level", 0);
4455 HDSPM_PHONES("Phones", 0);
4456 */
4457};
4458
4459static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = {
4460 HDSPM_MIXER("Mixer", 0),
4461 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4462 HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0),
4463 HDSPM_PREF_SYNC_REF("Pref Sync Ref", 0),
4464 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4465 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4466 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4467 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4468 HDSPM_SYNC_CHECK("ADAT1 SyncCheck", 3),
4469 HDSPM_SYNC_CHECK("ADAT2 SyncCheck", 4),
4470 HDSPM_SYNC_CHECK("ADAT3 SyncCheck", 5),
4471 HDSPM_SYNC_CHECK("ADAT4 SyncCheck", 6),
4472 HDSPM_SYNC_CHECK("TCO SyncCheck", 7),
4473 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 8),
4474 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4475 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4476 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4477 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT1 Frequency", 3),
4478 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT2 Frequency", 4),
4479 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT3 Frequency", 5),
4480 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT4 Frequency", 6),
4481 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 7),
Adrian Knoth11a5cd32013-07-05 11:27:57 +02004482 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8),
4483 HDSPM_TOGGLE_SETTING("S/PDIF Out Professional", HDSPM_c0_Pro),
4484 HDSPM_TOGGLE_SETTING("Single Speed WordClock Out", HDSPM_c0_Wck48)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004485};
4486
4487static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
4488 HDSPM_MIXER("Mixer", 0),
4489 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4490 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4491 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4492 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4493 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4494 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4495 HDSPM_SYNC_CHECK("WC Sync Check", 0),
4496 HDSPM_SYNC_CHECK("AES1 Sync Check", 1),
4497 HDSPM_SYNC_CHECK("AES2 Sync Check", 2),
4498 HDSPM_SYNC_CHECK("AES3 Sync Check", 3),
4499 HDSPM_SYNC_CHECK("AES4 Sync Check", 4),
4500 HDSPM_SYNC_CHECK("AES5 Sync Check", 5),
4501 HDSPM_SYNC_CHECK("AES6 Sync Check", 6),
4502 HDSPM_SYNC_CHECK("AES7 Sync Check", 7),
4503 HDSPM_SYNC_CHECK("AES8 Sync Check", 8),
4504 HDSPM_SYNC_CHECK("TCO Sync Check", 9),
4505 HDSPM_SYNC_CHECK("SYNC IN Sync Check", 10),
4506 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4507 HDSPM_AUTOSYNC_SAMPLE_RATE("AES1 Frequency", 1),
4508 HDSPM_AUTOSYNC_SAMPLE_RATE("AES2 Frequency", 2),
4509 HDSPM_AUTOSYNC_SAMPLE_RATE("AES3 Frequency", 3),
4510 HDSPM_AUTOSYNC_SAMPLE_RATE("AES4 Frequency", 4),
4511 HDSPM_AUTOSYNC_SAMPLE_RATE("AES5 Frequency", 5),
4512 HDSPM_AUTOSYNC_SAMPLE_RATE("AES6 Frequency", 6),
4513 HDSPM_AUTOSYNC_SAMPLE_RATE("AES7 Frequency", 7),
4514 HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8),
4515 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9),
4516 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10),
Adrian Knothc9e16682012-12-03 14:55:50 +01004517 HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
4518 HDSPM_TOGGLE_SETTING("Emphasis", HDSPM_Emphasis),
4519 HDSPM_TOGGLE_SETTING("Non Audio", HDSPM_Dolby),
4520 HDSPM_TOGGLE_SETTING("Professional", HDSPM_Professional),
4521 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004522 HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
4523 HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
4524};
4525
Adrian Knoth0dca1792011-01-26 19:32:14 +01004526
4527
4528/* Control elements for the optional TCO module */
4529static struct snd_kcontrol_new snd_hdspm_controls_tco[] = {
4530 HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0),
4531 HDSPM_TCO_PULL("TCO Pull", 0),
4532 HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0),
4533 HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0),
4534 HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0),
Adrian Knotha8176502013-03-10 00:37:27 +01004535 HDSPM_TCO_WORD_TERM("TCO Word Term", 0),
4536 HDSPM_TCO_LOCK_CHECK("TCO Input Check", 11),
4537 HDSPM_TCO_LOCK_CHECK("TCO LTC Valid", 12),
4538 HDSPM_TCO_LTC_FRAMES("TCO Detected Frame Rate", 0),
4539 HDSPM_TCO_VIDEO_INPUT_FORMAT("Video Input Format", 0)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004540};
4541
4542
Takashi Iwai98274f02005-11-17 14:52:34 +01004543static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
Takashi Iwai763f3562005-06-03 11:25:34 +02004544
4545
Takashi Iwai98274f02005-11-17 14:52:34 +01004546static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004547{
4548 int i;
4549
Adrian Knoth0dca1792011-01-26 19:32:14 +01004550 for (i = hdspm->ds_out_channels; i < hdspm->ss_out_channels; ++i) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004551 if (hdspm->system_sample_rate > 48000) {
4552 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004553 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
4554 SNDRV_CTL_ELEM_ACCESS_READ |
4555 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004556 } else {
4557 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004558 SNDRV_CTL_ELEM_ACCESS_READWRITE |
4559 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004560 }
4561 snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
Adrian Knoth0dca1792011-01-26 19:32:14 +01004562 SNDRV_CTL_EVENT_MASK_INFO,
4563 &hdspm->playback_mixer_ctls[i]->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02004564 }
4565
4566 return 0;
4567}
4568
4569
Adrian Knoth0dca1792011-01-26 19:32:14 +01004570static int snd_hdspm_create_controls(struct snd_card *card,
4571 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004572{
4573 unsigned int idx, limit;
4574 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01004575 struct snd_kcontrol *kctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004576 struct snd_kcontrol_new *list = NULL;
Takashi Iwai763f3562005-06-03 11:25:34 +02004577
Adrian Knoth0dca1792011-01-26 19:32:14 +01004578 switch (hdspm->io_type) {
4579 case MADI:
4580 list = snd_hdspm_controls_madi;
4581 limit = ARRAY_SIZE(snd_hdspm_controls_madi);
4582 break;
4583 case MADIface:
4584 list = snd_hdspm_controls_madiface;
4585 limit = ARRAY_SIZE(snd_hdspm_controls_madiface);
4586 break;
4587 case AIO:
4588 list = snd_hdspm_controls_aio;
4589 limit = ARRAY_SIZE(snd_hdspm_controls_aio);
4590 break;
4591 case RayDAT:
4592 list = snd_hdspm_controls_raydat;
4593 limit = ARRAY_SIZE(snd_hdspm_controls_raydat);
4594 break;
4595 case AES32:
4596 list = snd_hdspm_controls_aes32;
4597 limit = ARRAY_SIZE(snd_hdspm_controls_aes32);
4598 break;
4599 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004600
Adrian Knoth0dca1792011-01-26 19:32:14 +01004601 if (NULL != list) {
4602 for (idx = 0; idx < limit; idx++) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004603 err = snd_ctl_add(card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004604 snd_ctl_new1(&list[idx], hdspm));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004605 if (err < 0)
4606 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004607 }
4608 }
4609
Takashi Iwai763f3562005-06-03 11:25:34 +02004610
Adrian Knoth0dca1792011-01-26 19:32:14 +01004611 /* create simple 1:1 playback mixer controls */
Takashi Iwai763f3562005-06-03 11:25:34 +02004612 snd_hdspm_playback_mixer.name = "Chn";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004613 if (hdspm->system_sample_rate >= 128000) {
4614 limit = hdspm->qs_out_channels;
4615 } else if (hdspm->system_sample_rate >= 64000) {
4616 limit = hdspm->ds_out_channels;
4617 } else {
4618 limit = hdspm->ss_out_channels;
4619 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004620 for (idx = 0; idx < limit; ++idx) {
4621 snd_hdspm_playback_mixer.index = idx + 1;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004622 kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm);
4623 err = snd_ctl_add(card, kctl);
4624 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004625 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004626 hdspm->playback_mixer_ctls[idx] = kctl;
4627 }
4628
Adrian Knoth0dca1792011-01-26 19:32:14 +01004629
4630 if (hdspm->tco) {
4631 /* add tco control elements */
4632 list = snd_hdspm_controls_tco;
4633 limit = ARRAY_SIZE(snd_hdspm_controls_tco);
4634 for (idx = 0; idx < limit; idx++) {
4635 err = snd_ctl_add(card,
4636 snd_ctl_new1(&list[idx], hdspm));
4637 if (err < 0)
4638 return err;
4639 }
4640 }
4641
Takashi Iwai763f3562005-06-03 11:25:34 +02004642 return 0;
4643}
4644
4645/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01004646 /proc interface
Takashi Iwai763f3562005-06-03 11:25:34 +02004647 ------------------------------------------------------------*/
4648
4649static void
Adrian Knoth57601072013-07-05 11:28:04 +02004650snd_hdspm_proc_read_tco(struct snd_info_entry *entry,
4651 struct snd_info_buffer *buffer)
Takashi Iwai763f3562005-06-03 11:25:34 +02004652{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004653 struct hdspm *hdspm = entry->private_data;
Adrian Knoth57601072013-07-05 11:28:04 +02004654 unsigned int status, control;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004655 int a, ltc, frames, seconds, minutes, hours;
4656 unsigned int period;
4657 u64 freq_const = 0;
4658 u32 rate;
4659
Adrian Knoth57601072013-07-05 11:28:04 +02004660 snd_iprintf(buffer, "--- TCO ---\n");
4661
Takashi Iwai763f3562005-06-03 11:25:34 +02004662 status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004663 control = hdspm->control_register;
Takashi Iwai763f3562005-06-03 11:25:34 +02004664
Adrian Knoth0dca1792011-01-26 19:32:14 +01004665
Adrian Knoth0dca1792011-01-26 19:32:14 +01004666 if (status & HDSPM_tco_detect) {
4667 snd_iprintf(buffer, "TCO module detected.\n");
4668 a = hdspm_read(hdspm, HDSPM_RD_TCO+4);
4669 if (a & HDSPM_TCO1_LTC_Input_valid) {
4670 snd_iprintf(buffer, " LTC valid, ");
4671 switch (a & (HDSPM_TCO1_LTC_Format_LSB |
4672 HDSPM_TCO1_LTC_Format_MSB)) {
4673 case 0:
4674 snd_iprintf(buffer, "24 fps, ");
4675 break;
4676 case HDSPM_TCO1_LTC_Format_LSB:
4677 snd_iprintf(buffer, "25 fps, ");
4678 break;
4679 case HDSPM_TCO1_LTC_Format_MSB:
4680 snd_iprintf(buffer, "29.97 fps, ");
4681 break;
4682 default:
4683 snd_iprintf(buffer, "30 fps, ");
4684 break;
4685 }
4686 if (a & HDSPM_TCO1_set_drop_frame_flag) {
4687 snd_iprintf(buffer, "drop frame\n");
4688 } else {
4689 snd_iprintf(buffer, "full frame\n");
4690 }
4691 } else {
4692 snd_iprintf(buffer, " no LTC\n");
4693 }
4694 if (a & HDSPM_TCO1_Video_Input_Format_NTSC) {
4695 snd_iprintf(buffer, " Video: NTSC\n");
4696 } else if (a & HDSPM_TCO1_Video_Input_Format_PAL) {
4697 snd_iprintf(buffer, " Video: PAL\n");
4698 } else {
4699 snd_iprintf(buffer, " No video\n");
4700 }
4701 if (a & HDSPM_TCO1_TCO_lock) {
4702 snd_iprintf(buffer, " Sync: lock\n");
4703 } else {
4704 snd_iprintf(buffer, " Sync: no lock\n");
4705 }
4706
4707 switch (hdspm->io_type) {
4708 case MADI:
4709 case AES32:
4710 freq_const = 110069313433624ULL;
4711 break;
4712 case RayDAT:
4713 case AIO:
4714 freq_const = 104857600000000ULL;
4715 break;
4716 case MADIface:
4717 break; /* no TCO possible */
4718 }
4719
4720 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
4721 snd_iprintf(buffer, " period: %u\n", period);
4722
4723
4724 /* rate = freq_const/period; */
4725 rate = div_u64(freq_const, period);
4726
4727 if (control & HDSPM_QuadSpeed) {
4728 rate *= 4;
4729 } else if (control & HDSPM_DoubleSpeed) {
4730 rate *= 2;
4731 }
4732
4733 snd_iprintf(buffer, " Frequency: %u Hz\n",
4734 (unsigned int) rate);
4735
4736 ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
4737 frames = ltc & 0xF;
4738 ltc >>= 4;
4739 frames += (ltc & 0x3) * 10;
4740 ltc >>= 4;
4741 seconds = ltc & 0xF;
4742 ltc >>= 4;
4743 seconds += (ltc & 0x7) * 10;
4744 ltc >>= 4;
4745 minutes = ltc & 0xF;
4746 ltc >>= 4;
4747 minutes += (ltc & 0x7) * 10;
4748 ltc >>= 4;
4749 hours = ltc & 0xF;
4750 ltc >>= 4;
4751 hours += (ltc & 0x3) * 10;
4752 snd_iprintf(buffer,
4753 " LTC In: %02d:%02d:%02d:%02d\n",
4754 hours, minutes, seconds, frames);
4755
4756 } else {
4757 snd_iprintf(buffer, "No TCO module detected.\n");
4758 }
Adrian Knoth57601072013-07-05 11:28:04 +02004759}
4760
4761static void
4762snd_hdspm_proc_read_madi(struct snd_info_entry *entry,
4763 struct snd_info_buffer *buffer)
4764{
4765 struct hdspm *hdspm = entry->private_data;
4766 unsigned int status, status2, control, freq;
4767
4768 char *pref_sync_ref;
4769 char *autosync_ref;
4770 char *system_clock_mode;
4771 char *insel;
4772 int x, x2;
4773
4774 status = hdspm_read(hdspm, HDSPM_statusRegister);
4775 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
4776 control = hdspm->control_register;
4777 freq = hdspm_read(hdspm, HDSPM_timecodeRegister);
4778
4779 snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
4780 hdspm->card_name, hdspm->card->number + 1,
4781 hdspm->firmware_rev,
4782 (status2 & HDSPM_version0) |
4783 (status2 & HDSPM_version1) | (status2 &
4784 HDSPM_version2));
4785
4786 snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n",
4787 (hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF,
4788 hdspm->serial);
4789
4790 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
4791 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
4792
4793 snd_iprintf(buffer, "--- System ---\n");
4794
4795 snd_iprintf(buffer,
4796 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4797 status & HDSPM_audioIRQPending,
4798 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4799 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4800 hdspm->irq_count);
4801 snd_iprintf(buffer,
4802 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4803 "estimated= %ld (bytes)\n",
4804 ((status & HDSPM_BufferID) ? 1 : 0),
4805 (status & HDSPM_BufferPositionMask),
4806 (status & HDSPM_BufferPositionMask) %
4807 (2 * (int)hdspm->period_bytes),
4808 ((status & HDSPM_BufferPositionMask) - 64) %
4809 (2 * (int)hdspm->period_bytes),
4810 (long) hdspm_hw_pointer(hdspm) * 4);
4811
4812 snd_iprintf(buffer,
4813 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4814 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4815 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4816 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4817 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
4818 snd_iprintf(buffer,
4819 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4820 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4821 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4822 snd_iprintf(buffer,
4823 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4824 "status2=0x%x\n",
4825 hdspm->control_register, hdspm->control2_register,
4826 status, status2);
4827
Takashi Iwai763f3562005-06-03 11:25:34 +02004828
4829 snd_iprintf(buffer, "--- Settings ---\n");
4830
Adrian Knoth7cb155f2011-08-15 00:22:53 +02004831 x = hdspm_get_latency(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02004832
4833 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004834 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4835 x, (unsigned long) hdspm->period_bytes);
Takashi Iwai763f3562005-06-03 11:25:34 +02004836
Adrian Knoth0dca1792011-01-26 19:32:14 +01004837 snd_iprintf(buffer, "Line out: %s\n",
4838 (hdspm->control_register & HDSPM_LineOut) ? "on " : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004839
4840 switch (hdspm->control_register & HDSPM_InputMask) {
4841 case HDSPM_InputOptical:
4842 insel = "Optical";
4843 break;
4844 case HDSPM_InputCoaxial:
4845 insel = "Coaxial";
4846 break;
4847 default:
Masanari Iidaec8f53f2012-11-02 00:28:50 +09004848 insel = "Unknown";
Takashi Iwai763f3562005-06-03 11:25:34 +02004849 }
4850
Takashi Iwai763f3562005-06-03 11:25:34 +02004851 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004852 "ClearTrackMarker = %s, Transmit in %s Channel Mode, "
4853 "Auto Input %s\n",
4854 (hdspm->control_register & HDSPM_clr_tms) ? "on" : "off",
4855 (hdspm->control_register & HDSPM_TX_64ch) ? "64" : "56",
4856 (hdspm->control_register & HDSPM_AutoInp) ? "on" : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004857
Adrian Knoth0dca1792011-01-26 19:32:14 +01004858
Remy Bruno3cee5a62006-10-16 12:46:32 +02004859 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
Adrian Knoth0dca1792011-01-26 19:32:14 +01004860 system_clock_mode = "AutoSync";
Remy Bruno3cee5a62006-10-16 12:46:32 +02004861 else
Takashi Iwai763f3562005-06-03 11:25:34 +02004862 system_clock_mode = "Master";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004863 snd_iprintf(buffer, "AutoSync Reference: %s\n", system_clock_mode);
Takashi Iwai763f3562005-06-03 11:25:34 +02004864
4865 switch (hdspm_pref_sync_ref(hdspm)) {
4866 case HDSPM_SYNC_FROM_WORD:
4867 pref_sync_ref = "Word Clock";
4868 break;
4869 case HDSPM_SYNC_FROM_MADI:
4870 pref_sync_ref = "MADI Sync";
4871 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004872 case HDSPM_SYNC_FROM_TCO:
4873 pref_sync_ref = "TCO";
4874 break;
4875 case HDSPM_SYNC_FROM_SYNC_IN:
4876 pref_sync_ref = "Sync In";
4877 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004878 default:
4879 pref_sync_ref = "XXXX Clock";
4880 break;
4881 }
4882 snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004883 pref_sync_ref);
Takashi Iwai763f3562005-06-03 11:25:34 +02004884
4885 snd_iprintf(buffer, "System Clock Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004886 hdspm->system_sample_rate);
Takashi Iwai763f3562005-06-03 11:25:34 +02004887
4888
4889 snd_iprintf(buffer, "--- Status:\n");
4890
4891 x = status & HDSPM_madiSync;
4892 x2 = status2 & HDSPM_wcSync;
4893
4894 snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004895 (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
4896 "NoLock",
4897 (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
4898 "NoLock");
Takashi Iwai763f3562005-06-03 11:25:34 +02004899
4900 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004901 case HDSPM_AUTOSYNC_FROM_SYNC_IN:
4902 autosync_ref = "Sync In";
4903 break;
4904 case HDSPM_AUTOSYNC_FROM_TCO:
4905 autosync_ref = "TCO";
4906 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004907 case HDSPM_AUTOSYNC_FROM_WORD:
4908 autosync_ref = "Word Clock";
4909 break;
4910 case HDSPM_AUTOSYNC_FROM_MADI:
4911 autosync_ref = "MADI Sync";
4912 break;
4913 case HDSPM_AUTOSYNC_FROM_NONE:
4914 autosync_ref = "Input not valid";
4915 break;
4916 default:
4917 autosync_ref = "---";
4918 break;
4919 }
4920 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004921 "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
4922 autosync_ref, hdspm_external_sample_rate(hdspm),
4923 (status & HDSPM_madiFreqMask) >> 22,
4924 (status2 & HDSPM_wcFreqMask) >> 5);
Takashi Iwai763f3562005-06-03 11:25:34 +02004925
4926 snd_iprintf(buffer, "Input: %s, Mode=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004927 (status & HDSPM_AB_int) ? "Coax" : "Optical",
4928 (status & HDSPM_RX_64ch) ? "64 channels" :
4929 "56 channels");
Takashi Iwai763f3562005-06-03 11:25:34 +02004930
Adrian Knoth57601072013-07-05 11:28:04 +02004931 /* call readout function for TCO specific status */
4932 snd_hdspm_proc_read_tco(entry, buffer);
4933
Takashi Iwai763f3562005-06-03 11:25:34 +02004934 snd_iprintf(buffer, "\n");
4935}
4936
Remy Bruno3cee5a62006-10-16 12:46:32 +02004937static void
4938snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
4939 struct snd_info_buffer *buffer)
4940{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004941 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004942 unsigned int status;
4943 unsigned int status2;
4944 unsigned int timecode;
Andre Schramm56bde0f2013-01-09 14:40:18 +01004945 unsigned int wcLock, wcSync;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004946 int pref_syncref;
4947 char *autosync_ref;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004948 int x;
4949
4950 status = hdspm_read(hdspm, HDSPM_statusRegister);
4951 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
4952 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
4953
4954 snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
4955 hdspm->card_name, hdspm->card->number + 1,
4956 hdspm->firmware_rev);
4957
4958 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
4959 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
4960
4961 snd_iprintf(buffer, "--- System ---\n");
4962
4963 snd_iprintf(buffer,
4964 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4965 status & HDSPM_audioIRQPending,
4966 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4967 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4968 hdspm->irq_count);
4969 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004970 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4971 "estimated= %ld (bytes)\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004972 ((status & HDSPM_BufferID) ? 1 : 0),
4973 (status & HDSPM_BufferPositionMask),
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004974 (status & HDSPM_BufferPositionMask) %
4975 (2 * (int)hdspm->period_bytes),
4976 ((status & HDSPM_BufferPositionMask) - 64) %
4977 (2 * (int)hdspm->period_bytes),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004978 (long) hdspm_hw_pointer(hdspm) * 4);
4979
4980 snd_iprintf(buffer,
4981 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4982 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4983 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4984 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4985 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
4986 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004987 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4988 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4989 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4990 snd_iprintf(buffer,
4991 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4992 "status2=0x%x\n",
4993 hdspm->control_register, hdspm->control2_register,
4994 status, status2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02004995
4996 snd_iprintf(buffer, "--- Settings ---\n");
4997
Adrian Knoth7cb155f2011-08-15 00:22:53 +02004998 x = hdspm_get_latency(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02004999
5000 snd_iprintf(buffer,
5001 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
5002 x, (unsigned long) hdspm->period_bytes);
5003
Adrian Knoth0dca1792011-01-26 19:32:14 +01005004 snd_iprintf(buffer, "Line out: %s\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005005 (hdspm->
Adrian Knoth0dca1792011-01-26 19:32:14 +01005006 control_register & HDSPM_LineOut) ? "on " : "off");
Remy Bruno3cee5a62006-10-16 12:46:32 +02005007
5008 snd_iprintf(buffer,
5009 "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
5010 (hdspm->
5011 control_register & HDSPM_clr_tms) ? "on" : "off",
5012 (hdspm->
5013 control_register & HDSPM_Emphasis) ? "on" : "off",
5014 (hdspm->
5015 control_register & HDSPM_Dolby) ? "on" : "off");
5016
Remy Bruno3cee5a62006-10-16 12:46:32 +02005017
5018 pref_syncref = hdspm_pref_sync_ref(hdspm);
5019 if (pref_syncref == 0)
5020 snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
5021 else
5022 snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
5023 pref_syncref);
5024
5025 snd_iprintf(buffer, "System Clock Frequency: %d\n",
5026 hdspm->system_sample_rate);
5027
5028 snd_iprintf(buffer, "Double speed: %s\n",
5029 hdspm->control_register & HDSPM_DS_DoubleWire?
5030 "Double wire" : "Single wire");
5031 snd_iprintf(buffer, "Quad speed: %s\n",
5032 hdspm->control_register & HDSPM_QS_DoubleWire?
5033 "Double wire" :
5034 hdspm->control_register & HDSPM_QS_QuadWire?
5035 "Quad wire" : "Single wire");
5036
5037 snd_iprintf(buffer, "--- Status:\n");
5038
Andre Schramm56bde0f2013-01-09 14:40:18 +01005039 wcLock = status & HDSPM_AES32_wcLock;
5040 wcSync = wcLock && (status & HDSPM_AES32_wcSync);
5041
Remy Bruno3cee5a62006-10-16 12:46:32 +02005042 snd_iprintf(buffer, "Word: %s Frequency: %d\n",
Andre Schramm56bde0f2013-01-09 14:40:18 +01005043 (wcLock) ? (wcSync ? "Sync " : "Lock ") : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005044 HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02005045
5046 for (x = 0; x < 8; x++) {
5047 snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005048 x+1,
5049 (status2 & (HDSPM_LockAES >> x)) ?
Adrian Knoth0dca1792011-01-26 19:32:14 +01005050 "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005051 HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02005052 }
5053
5054 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005055 case HDSPM_AES32_AUTOSYNC_FROM_NONE:
5056 autosync_ref = "None"; break;
5057 case HDSPM_AES32_AUTOSYNC_FROM_WORD:
5058 autosync_ref = "Word Clock"; break;
5059 case HDSPM_AES32_AUTOSYNC_FROM_AES1:
5060 autosync_ref = "AES1"; break;
5061 case HDSPM_AES32_AUTOSYNC_FROM_AES2:
5062 autosync_ref = "AES2"; break;
5063 case HDSPM_AES32_AUTOSYNC_FROM_AES3:
5064 autosync_ref = "AES3"; break;
5065 case HDSPM_AES32_AUTOSYNC_FROM_AES4:
5066 autosync_ref = "AES4"; break;
5067 case HDSPM_AES32_AUTOSYNC_FROM_AES5:
5068 autosync_ref = "AES5"; break;
5069 case HDSPM_AES32_AUTOSYNC_FROM_AES6:
5070 autosync_ref = "AES6"; break;
5071 case HDSPM_AES32_AUTOSYNC_FROM_AES7:
5072 autosync_ref = "AES7"; break;
5073 case HDSPM_AES32_AUTOSYNC_FROM_AES8:
5074 autosync_ref = "AES8"; break;
5075 default:
5076 autosync_ref = "---"; break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005077 }
5078 snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
5079
5080 snd_iprintf(buffer, "\n");
5081}
5082
Adrian Knoth0dca1792011-01-26 19:32:14 +01005083static void
5084snd_hdspm_proc_read_raydat(struct snd_info_entry *entry,
5085 struct snd_info_buffer *buffer)
5086{
5087 struct hdspm *hdspm = entry->private_data;
5088 unsigned int status1, status2, status3, control, i;
5089 unsigned int lock, sync;
5090
5091 status1 = hdspm_read(hdspm, HDSPM_RD_STATUS_1); /* s1 */
5092 status2 = hdspm_read(hdspm, HDSPM_RD_STATUS_2); /* freq */
5093 status3 = hdspm_read(hdspm, HDSPM_RD_STATUS_3); /* s2 */
5094
5095 control = hdspm->control_register;
5096
5097 snd_iprintf(buffer, "STATUS1: 0x%08x\n", status1);
5098 snd_iprintf(buffer, "STATUS2: 0x%08x\n", status2);
5099 snd_iprintf(buffer, "STATUS3: 0x%08x\n", status3);
5100
5101
5102 snd_iprintf(buffer, "\n*** CLOCK MODE\n\n");
5103
5104 snd_iprintf(buffer, "Clock mode : %s\n",
5105 (hdspm_system_clock_mode(hdspm) == 0) ? "master" : "slave");
5106 snd_iprintf(buffer, "System frequency: %d Hz\n",
5107 hdspm_get_system_sample_rate(hdspm));
5108
5109 snd_iprintf(buffer, "\n*** INPUT STATUS\n\n");
5110
5111 lock = 0x1;
5112 sync = 0x100;
5113
5114 for (i = 0; i < 8; i++) {
5115 snd_iprintf(buffer, "s1_input %d: Lock %d, Sync %d, Freq %s\n",
5116 i,
5117 (status1 & lock) ? 1 : 0,
5118 (status1 & sync) ? 1 : 0,
5119 texts_freq[(status2 >> (i * 4)) & 0xF]);
5120
5121 lock = lock<<1;
5122 sync = sync<<1;
5123 }
5124
5125 snd_iprintf(buffer, "WC input: Lock %d, Sync %d, Freq %s\n",
5126 (status1 & 0x1000000) ? 1 : 0,
5127 (status1 & 0x2000000) ? 1 : 0,
5128 texts_freq[(status1 >> 16) & 0xF]);
5129
5130 snd_iprintf(buffer, "TCO input: Lock %d, Sync %d, Freq %s\n",
5131 (status1 & 0x4000000) ? 1 : 0,
5132 (status1 & 0x8000000) ? 1 : 0,
5133 texts_freq[(status1 >> 20) & 0xF]);
5134
5135 snd_iprintf(buffer, "SYNC IN: Lock %d, Sync %d, Freq %s\n",
5136 (status3 & 0x400) ? 1 : 0,
5137 (status3 & 0x800) ? 1 : 0,
5138 texts_freq[(status2 >> 12) & 0xF]);
5139
5140}
5141
Remy Bruno3cee5a62006-10-16 12:46:32 +02005142#ifdef CONFIG_SND_DEBUG
5143static void
Adrian Knoth0dca1792011-01-26 19:32:14 +01005144snd_hdspm_proc_read_debug(struct snd_info_entry *entry,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005145 struct snd_info_buffer *buffer)
5146{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005147 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005148
5149 int j,i;
5150
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005151 for (i = 0; i < 256 /* 1024*64 */; i += j) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02005152 snd_iprintf(buffer, "0x%08X: ", i);
5153 for (j = 0; j < 16; j += 4)
5154 snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
5155 snd_iprintf(buffer, "\n");
5156 }
5157}
5158#endif
5159
5160
Adrian Knoth0dca1792011-01-26 19:32:14 +01005161static void snd_hdspm_proc_ports_in(struct snd_info_entry *entry,
5162 struct snd_info_buffer *buffer)
5163{
5164 struct hdspm *hdspm = entry->private_data;
5165 int i;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005166
Adrian Knoth0dca1792011-01-26 19:32:14 +01005167 snd_iprintf(buffer, "# generated by hdspm\n");
5168
5169 for (i = 0; i < hdspm->max_channels_in; i++) {
5170 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_in[i]);
5171 }
5172}
5173
5174static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry,
5175 struct snd_info_buffer *buffer)
5176{
5177 struct hdspm *hdspm = entry->private_data;
5178 int i;
5179
5180 snd_iprintf(buffer, "# generated by hdspm\n");
5181
5182 for (i = 0; i < hdspm->max_channels_out; i++) {
5183 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_out[i]);
5184 }
5185}
5186
5187
Bill Pembertone23e7a12012-12-06 12:35:10 -05005188static void snd_hdspm_proc_init(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005189{
Takashi Iwai98274f02005-11-17 14:52:34 +01005190 struct snd_info_entry *entry;
Takashi Iwai763f3562005-06-03 11:25:34 +02005191
Adrian Knoth0dca1792011-01-26 19:32:14 +01005192 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) {
5193 switch (hdspm->io_type) {
5194 case AES32:
5195 snd_info_set_text_ops(entry, hdspm,
5196 snd_hdspm_proc_read_aes32);
5197 break;
5198 case MADI:
5199 snd_info_set_text_ops(entry, hdspm,
5200 snd_hdspm_proc_read_madi);
5201 break;
5202 case MADIface:
5203 /* snd_info_set_text_ops(entry, hdspm,
5204 snd_hdspm_proc_read_madiface); */
5205 break;
5206 case RayDAT:
5207 snd_info_set_text_ops(entry, hdspm,
5208 snd_hdspm_proc_read_raydat);
5209 break;
5210 case AIO:
5211 break;
5212 }
5213 }
5214
5215 if (!snd_card_proc_new(hdspm->card, "ports.in", &entry)) {
5216 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_in);
5217 }
5218
5219 if (!snd_card_proc_new(hdspm->card, "ports.out", &entry)) {
5220 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_out);
5221 }
5222
Remy Bruno3cee5a62006-10-16 12:46:32 +02005223#ifdef CONFIG_SND_DEBUG
5224 /* debug file to read all hdspm registers */
5225 if (!snd_card_proc_new(hdspm->card, "debug", &entry))
5226 snd_info_set_text_ops(entry, hdspm,
5227 snd_hdspm_proc_read_debug);
5228#endif
Takashi Iwai763f3562005-06-03 11:25:34 +02005229}
5230
5231/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005232 hdspm intitialize
Takashi Iwai763f3562005-06-03 11:25:34 +02005233 ------------------------------------------------------------*/
5234
Takashi Iwai98274f02005-11-17 14:52:34 +01005235static int snd_hdspm_set_defaults(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005236{
Takashi Iwai763f3562005-06-03 11:25:34 +02005237 /* ASSUMPTION: hdspm->lock is either held, or there is no need to
Joe Perches561de312007-12-18 13:13:47 +01005238 hold it (e.g. during module initialization).
Adrian Knoth0dca1792011-01-26 19:32:14 +01005239 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005240
5241 /* set defaults: */
5242
Adrian Knoth0dca1792011-01-26 19:32:14 +01005243 hdspm->settings_register = 0;
5244
5245 switch (hdspm->io_type) {
5246 case MADI:
5247 case MADIface:
5248 hdspm->control_register =
5249 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5250 break;
5251
5252 case RayDAT:
5253 case AIO:
5254 hdspm->settings_register = 0x1 + 0x1000;
5255 /* Magic values are: LAT_0, LAT_2, Master, freq1, tx64ch, inp_0,
5256 * line_out */
5257 hdspm->control_register =
5258 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5259 break;
5260
5261 case AES32:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005262 hdspm->control_register =
5263 HDSPM_ClockModeMaster | /* Master Cloack Mode on */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005264 hdspm_encode_latency(7) | /* latency max=8192samples */
Remy Bruno3cee5a62006-10-16 12:46:32 +02005265 HDSPM_SyncRef0 | /* AES1 is syncclock */
5266 HDSPM_LineOut | /* Analog output in */
5267 HDSPM_Professional; /* Professional mode */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005268 break;
5269 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005270
5271 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5272
Adrian Knoth0dca1792011-01-26 19:32:14 +01005273 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005274 /* No control2 register for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005275#ifdef SNDRV_BIG_ENDIAN
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005276 hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
Takashi Iwai763f3562005-06-03 11:25:34 +02005277#else
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005278 hdspm->control2_register = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005279#endif
5280
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005281 hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
5282 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005283 hdspm_compute_period_size(hdspm);
5284
5285 /* silence everything */
5286
5287 all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
5288
Adrian Knothb2ed6322013-07-05 11:27:54 +02005289 if (hdspm_is_raydat_or_aio(hdspm))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005290 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
Takashi Iwai763f3562005-06-03 11:25:34 +02005291
5292 /* set a default rate so that the channel map is set up. */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005293 hdspm_set_rate(hdspm, 48000, 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02005294
5295 return 0;
5296}
5297
5298
5299/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005300 interrupt
Takashi Iwai763f3562005-06-03 11:25:34 +02005301 ------------------------------------------------------------*/
5302
David Howells7d12e782006-10-05 14:55:46 +01005303static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02005304{
Takashi Iwai98274f02005-11-17 14:52:34 +01005305 struct hdspm *hdspm = (struct hdspm *) dev_id;
Takashi Iwai763f3562005-06-03 11:25:34 +02005306 unsigned int status;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005307 int i, audio, midi, schedule = 0;
5308 /* cycles_t now; */
Takashi Iwai763f3562005-06-03 11:25:34 +02005309
5310 status = hdspm_read(hdspm, HDSPM_statusRegister);
5311
5312 audio = status & HDSPM_audioIRQPending;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005313 midi = status & (HDSPM_midi0IRQPending | HDSPM_midi1IRQPending |
5314 HDSPM_midi2IRQPending | HDSPM_midi3IRQPending);
Takashi Iwai763f3562005-06-03 11:25:34 +02005315
Adrian Knoth0dca1792011-01-26 19:32:14 +01005316 /* now = get_cycles(); */
5317 /**
5318 * LAT_2..LAT_0 period counter (win) counter (mac)
5319 * 6 4096 ~256053425 ~514672358
5320 * 5 2048 ~128024983 ~257373821
5321 * 4 1024 ~64023706 ~128718089
5322 * 3 512 ~32005945 ~64385999
5323 * 2 256 ~16003039 ~32260176
5324 * 1 128 ~7998738 ~16194507
5325 * 0 64 ~3998231 ~8191558
5326 **/
5327 /*
5328 snd_printk(KERN_INFO "snd_hdspm_interrupt %llu @ %llx\n",
5329 now-hdspm->last_interrupt, status & 0xFFC0);
5330 hdspm->last_interrupt = now;
5331 */
5332
5333 if (!audio && !midi)
Takashi Iwai763f3562005-06-03 11:25:34 +02005334 return IRQ_NONE;
5335
5336 hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
5337 hdspm->irq_count++;
5338
Takashi Iwai763f3562005-06-03 11:25:34 +02005339
5340 if (audio) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005341 if (hdspm->capture_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005342 snd_pcm_period_elapsed(hdspm->capture_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005343
5344 if (hdspm->playback_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005345 snd_pcm_period_elapsed(hdspm->playback_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005346 }
5347
Adrian Knoth0dca1792011-01-26 19:32:14 +01005348 if (midi) {
5349 i = 0;
5350 while (i < hdspm->midiPorts) {
5351 if ((hdspm_read(hdspm,
5352 hdspm->midi[i].statusIn) & 0xff) &&
5353 (status & hdspm->midi[i].irq)) {
5354 /* we disable interrupts for this input until
5355 * processing is done
5356 */
5357 hdspm->control_register &= ~hdspm->midi[i].ie;
5358 hdspm_write(hdspm, HDSPM_controlRegister,
5359 hdspm->control_register);
5360 hdspm->midi[i].pending = 1;
5361 schedule = 1;
5362 }
5363
5364 i++;
5365 }
5366
5367 if (schedule)
5368 tasklet_hi_schedule(&hdspm->midi_tasklet);
Takashi Iwai763f3562005-06-03 11:25:34 +02005369 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005370
Takashi Iwai763f3562005-06-03 11:25:34 +02005371 return IRQ_HANDLED;
5372}
5373
5374/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005375 pcm interface
Takashi Iwai763f3562005-06-03 11:25:34 +02005376 ------------------------------------------------------------*/
5377
5378
Adrian Knoth0dca1792011-01-26 19:32:14 +01005379static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream
5380 *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005381{
Takashi Iwai98274f02005-11-17 14:52:34 +01005382 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005383 return hdspm_hw_pointer(hdspm);
5384}
5385
Takashi Iwai763f3562005-06-03 11:25:34 +02005386
Takashi Iwai98274f02005-11-17 14:52:34 +01005387static int snd_hdspm_reset(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005388{
Takashi Iwai98274f02005-11-17 14:52:34 +01005389 struct snd_pcm_runtime *runtime = substream->runtime;
5390 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5391 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005392
5393 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5394 other = hdspm->capture_substream;
5395 else
5396 other = hdspm->playback_substream;
5397
5398 if (hdspm->running)
5399 runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
5400 else
5401 runtime->status->hw_ptr = 0;
5402 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005403 struct snd_pcm_substream *s;
5404 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01005405 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005406 if (s == other) {
5407 oruntime->status->hw_ptr =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005408 runtime->status->hw_ptr;
Takashi Iwai763f3562005-06-03 11:25:34 +02005409 break;
5410 }
5411 }
5412 }
5413 return 0;
5414}
5415
Takashi Iwai98274f02005-11-17 14:52:34 +01005416static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
5417 struct snd_pcm_hw_params *params)
Takashi Iwai763f3562005-06-03 11:25:34 +02005418{
Takashi Iwai98274f02005-11-17 14:52:34 +01005419 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005420 int err;
5421 int i;
5422 pid_t this_pid;
5423 pid_t other_pid;
Takashi Iwai763f3562005-06-03 11:25:34 +02005424
5425 spin_lock_irq(&hdspm->lock);
5426
5427 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5428 this_pid = hdspm->playback_pid;
5429 other_pid = hdspm->capture_pid;
5430 } else {
5431 this_pid = hdspm->capture_pid;
5432 other_pid = hdspm->playback_pid;
5433 }
5434
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005435 if (other_pid > 0 && this_pid != other_pid) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005436
5437 /* The other stream is open, and not by the same
5438 task as this one. Make sure that the parameters
5439 that matter are the same.
Adrian Knoth0dca1792011-01-26 19:32:14 +01005440 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005441
5442 if (params_rate(params) != hdspm->system_sample_rate) {
5443 spin_unlock_irq(&hdspm->lock);
5444 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005445 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005446 return -EBUSY;
5447 }
5448
5449 if (params_period_size(params) != hdspm->period_bytes / 4) {
5450 spin_unlock_irq(&hdspm->lock);
5451 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005452 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005453 return -EBUSY;
5454 }
5455
5456 }
5457 /* We're fine. */
5458 spin_unlock_irq(&hdspm->lock);
5459
5460 /* how to make sure that the rate matches an externally-set one ? */
5461
5462 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005463 err = hdspm_set_rate(hdspm, params_rate(params), 0);
5464 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005465 snd_printk(KERN_INFO "err on hdspm_set_rate: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005466 spin_unlock_irq(&hdspm->lock);
5467 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005468 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005469 return err;
5470 }
5471 spin_unlock_irq(&hdspm->lock);
5472
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005473 err = hdspm_set_interrupt_interval(hdspm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005474 params_period_size(params));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005475 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005476 snd_printk(KERN_INFO "err on hdspm_set_interrupt_interval: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005477 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005478 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005479 return err;
5480 }
5481
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005482 /* Memory allocation, takashi's method, dont know if we should
5483 * spinlock
5484 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005485 /* malloc all buffer even if not enabled to get sure */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005486 /* Update for MADI rev 204: we need to allocate for all channels,
5487 * otherwise it doesn't work at 96kHz */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005488
Takashi Iwai763f3562005-06-03 11:25:34 +02005489 err =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005490 snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
5491 if (err < 0) {
5492 snd_printk(KERN_INFO "err on snd_pcm_lib_malloc_pages: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005493 return err;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005494 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005495
Takashi Iwai763f3562005-06-03 11:25:34 +02005496 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5497
Takashi Iwai77a23f22008-08-21 13:00:13 +02005498 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferOut,
Takashi Iwai763f3562005-06-03 11:25:34 +02005499 params_channels(params));
5500
5501 for (i = 0; i < params_channels(params); ++i)
5502 snd_hdspm_enable_out(hdspm, i, 1);
5503
5504 hdspm->playback_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005505 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005506 snd_printdd("Allocated sample buffer for playback at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005507 hdspm->playback_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005508 } else {
Takashi Iwai77a23f22008-08-21 13:00:13 +02005509 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn,
Takashi Iwai763f3562005-06-03 11:25:34 +02005510 params_channels(params));
5511
5512 for (i = 0; i < params_channels(params); ++i)
5513 snd_hdspm_enable_in(hdspm, i, 1);
5514
5515 hdspm->capture_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005516 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005517 snd_printdd("Allocated sample buffer for capture at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005518 hdspm->capture_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005519 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005520
Remy Bruno3cee5a62006-10-16 12:46:32 +02005521 /*
5522 snd_printdd("Allocated sample buffer for %s at 0x%08X\n",
5523 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5524 "playback" : "capture",
Takashi Iwai77a23f22008-08-21 13:00:13 +02005525 snd_pcm_sgbuf_get_addr(substream, 0));
Adrian Knoth0dca1792011-01-26 19:32:14 +01005526 */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005527 /*
Adrian Knoth0dca1792011-01-26 19:32:14 +01005528 snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n",
5529 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5530 "playback" : "capture",
5531 params_rate(params), params_channels(params),
5532 params_buffer_size(params));
5533 */
5534
5535
5536 /* Switch to native float format if requested */
5537 if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) {
5538 if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT))
5539 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE float format.\n");
5540
5541 hdspm->control_register |= HDSPe_FLOAT_FORMAT;
5542 } else if (SNDRV_PCM_FORMAT_S32_LE == params_format(params)) {
5543 if (hdspm->control_register & HDSPe_FLOAT_FORMAT)
5544 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE integer format.\n");
5545
5546 hdspm->control_register &= ~HDSPe_FLOAT_FORMAT;
5547 }
5548 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5549
Takashi Iwai763f3562005-06-03 11:25:34 +02005550 return 0;
5551}
5552
Takashi Iwai98274f02005-11-17 14:52:34 +01005553static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005554{
5555 int i;
Takashi Iwai98274f02005-11-17 14:52:34 +01005556 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005557
5558 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5559
Adrian Knoth0dca1792011-01-26 19:32:14 +01005560 /* params_channels(params) should be enough,
Takashi Iwai763f3562005-06-03 11:25:34 +02005561 but to get sure in case of error */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005562 for (i = 0; i < hdspm->max_channels_out; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005563 snd_hdspm_enable_out(hdspm, i, 0);
5564
5565 hdspm->playback_buffer = NULL;
5566 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005567 for (i = 0; i < hdspm->max_channels_in; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005568 snd_hdspm_enable_in(hdspm, i, 0);
5569
5570 hdspm->capture_buffer = NULL;
5571
5572 }
5573
5574 snd_pcm_lib_free_pages(substream);
5575
5576 return 0;
5577}
5578
Adrian Knoth0dca1792011-01-26 19:32:14 +01005579
Takashi Iwai98274f02005-11-17 14:52:34 +01005580static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005581 struct snd_pcm_channel_info *info)
Takashi Iwai763f3562005-06-03 11:25:34 +02005582{
Takashi Iwai98274f02005-11-17 14:52:34 +01005583 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005584
Adrian Knoth0dca1792011-01-26 19:32:14 +01005585 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5586 if (snd_BUG_ON(info->channel >= hdspm->max_channels_out)) {
5587 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel out of range (%d)\n", info->channel);
5588 return -EINVAL;
5589 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005590
Adrian Knoth0dca1792011-01-26 19:32:14 +01005591 if (hdspm->channel_map_out[info->channel] < 0) {
5592 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel %d mapped out\n", info->channel);
5593 return -EINVAL;
5594 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005595
Adrian Knoth0dca1792011-01-26 19:32:14 +01005596 info->offset = hdspm->channel_map_out[info->channel] *
5597 HDSPM_CHANNEL_BUFFER_BYTES;
5598 } else {
5599 if (snd_BUG_ON(info->channel >= hdspm->max_channels_in)) {
5600 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel out of range (%d)\n", info->channel);
5601 return -EINVAL;
5602 }
5603
5604 if (hdspm->channel_map_in[info->channel] < 0) {
5605 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel %d mapped out\n", info->channel);
5606 return -EINVAL;
5607 }
5608
5609 info->offset = hdspm->channel_map_in[info->channel] *
5610 HDSPM_CHANNEL_BUFFER_BYTES;
5611 }
5612
Takashi Iwai763f3562005-06-03 11:25:34 +02005613 info->first = 0;
5614 info->step = 32;
5615 return 0;
5616}
5617
Adrian Knoth0dca1792011-01-26 19:32:14 +01005618
Takashi Iwai98274f02005-11-17 14:52:34 +01005619static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005620 unsigned int cmd, void *arg)
Takashi Iwai763f3562005-06-03 11:25:34 +02005621{
5622 switch (cmd) {
5623 case SNDRV_PCM_IOCTL1_RESET:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005624 return snd_hdspm_reset(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005625
5626 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Adrian Knoth0dca1792011-01-26 19:32:14 +01005627 {
5628 struct snd_pcm_channel_info *info = arg;
5629 return snd_hdspm_channel_info(substream, info);
5630 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005631 default:
5632 break;
5633 }
5634
5635 return snd_pcm_lib_ioctl(substream, cmd, arg);
5636}
5637
Takashi Iwai98274f02005-11-17 14:52:34 +01005638static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
Takashi Iwai763f3562005-06-03 11:25:34 +02005639{
Takashi Iwai98274f02005-11-17 14:52:34 +01005640 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5641 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005642 int running;
5643
5644 spin_lock(&hdspm->lock);
5645 running = hdspm->running;
5646 switch (cmd) {
5647 case SNDRV_PCM_TRIGGER_START:
5648 running |= 1 << substream->stream;
5649 break;
5650 case SNDRV_PCM_TRIGGER_STOP:
5651 running &= ~(1 << substream->stream);
5652 break;
5653 default:
5654 snd_BUG();
5655 spin_unlock(&hdspm->lock);
5656 return -EINVAL;
5657 }
5658 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5659 other = hdspm->capture_substream;
5660 else
5661 other = hdspm->playback_substream;
5662
5663 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005664 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01005665 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005666 if (s == other) {
5667 snd_pcm_trigger_done(s, substream);
5668 if (cmd == SNDRV_PCM_TRIGGER_START)
5669 running |= 1 << s->stream;
5670 else
5671 running &= ~(1 << s->stream);
5672 goto _ok;
5673 }
5674 }
5675 if (cmd == SNDRV_PCM_TRIGGER_START) {
5676 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005677 && substream->stream ==
5678 SNDRV_PCM_STREAM_CAPTURE)
Takashi Iwai763f3562005-06-03 11:25:34 +02005679 hdspm_silence_playback(hdspm);
5680 } else {
5681 if (running &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01005682 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Takashi Iwai763f3562005-06-03 11:25:34 +02005683 hdspm_silence_playback(hdspm);
5684 }
5685 } else {
5686 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
5687 hdspm_silence_playback(hdspm);
5688 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005689_ok:
Takashi Iwai763f3562005-06-03 11:25:34 +02005690 snd_pcm_trigger_done(substream, substream);
5691 if (!hdspm->running && running)
5692 hdspm_start_audio(hdspm);
5693 else if (hdspm->running && !running)
5694 hdspm_stop_audio(hdspm);
5695 hdspm->running = running;
5696 spin_unlock(&hdspm->lock);
5697
5698 return 0;
5699}
5700
Takashi Iwai98274f02005-11-17 14:52:34 +01005701static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005702{
5703 return 0;
5704}
5705
Takashi Iwai98274f02005-11-17 14:52:34 +01005706static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005707 .info = (SNDRV_PCM_INFO_MMAP |
5708 SNDRV_PCM_INFO_MMAP_VALID |
5709 SNDRV_PCM_INFO_NONINTERLEAVED |
5710 SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
5711 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5712 .rates = (SNDRV_PCM_RATE_32000 |
5713 SNDRV_PCM_RATE_44100 |
5714 SNDRV_PCM_RATE_48000 |
5715 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005716 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5717 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ),
Takashi Iwai763f3562005-06-03 11:25:34 +02005718 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005719 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005720 .channels_min = 1,
5721 .channels_max = HDSPM_MAX_CHANNELS,
5722 .buffer_bytes_max =
5723 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
Adrian Knoth1b6fa102011-08-15 00:22:51 +02005724 .period_bytes_min = (32 * 4),
Takashi Iwai52e6fb42011-08-15 10:40:59 +02005725 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005726 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005727 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005728 .fifo_size = 0
5729};
5730
Takashi Iwai98274f02005-11-17 14:52:34 +01005731static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005732 .info = (SNDRV_PCM_INFO_MMAP |
5733 SNDRV_PCM_INFO_MMAP_VALID |
5734 SNDRV_PCM_INFO_NONINTERLEAVED |
5735 SNDRV_PCM_INFO_SYNC_START),
5736 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5737 .rates = (SNDRV_PCM_RATE_32000 |
5738 SNDRV_PCM_RATE_44100 |
5739 SNDRV_PCM_RATE_48000 |
5740 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005741 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5742 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
Takashi Iwai763f3562005-06-03 11:25:34 +02005743 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005744 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005745 .channels_min = 1,
5746 .channels_max = HDSPM_MAX_CHANNELS,
5747 .buffer_bytes_max =
5748 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
Adrian Knoth1b6fa102011-08-15 00:22:51 +02005749 .period_bytes_min = (32 * 4),
Takashi Iwai52e6fb42011-08-15 10:40:59 +02005750 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005751 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005752 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005753 .fifo_size = 0
5754};
5755
Adrian Knoth0dca1792011-01-26 19:32:14 +01005756static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
5757 struct snd_pcm_hw_rule *rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005758{
Takashi Iwai98274f02005-11-17 14:52:34 +01005759 struct hdspm *hdspm = rule->private;
5760 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005761 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005762 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005763 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5764
Adrian Knoth0dca1792011-01-26 19:32:14 +01005765 if (r->min > 96000 && r->max <= 192000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005766 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005767 .min = hdspm->qs_in_channels,
5768 .max = hdspm->qs_in_channels,
5769 .integer = 1,
5770 };
5771 return snd_interval_refine(c, &t);
5772 } else if (r->min > 48000 && r->max <= 96000) {
5773 struct snd_interval t = {
5774 .min = hdspm->ds_in_channels,
5775 .max = hdspm->ds_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005776 .integer = 1,
5777 };
5778 return snd_interval_refine(c, &t);
5779 } else if (r->max < 64000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005780 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005781 .min = hdspm->ss_in_channels,
5782 .max = hdspm->ss_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005783 .integer = 1,
5784 };
5785 return snd_interval_refine(c, &t);
5786 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005787
Takashi Iwai763f3562005-06-03 11:25:34 +02005788 return 0;
5789}
5790
Adrian Knoth0dca1792011-01-26 19:32:14 +01005791static int snd_hdspm_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
Takashi Iwai98274f02005-11-17 14:52:34 +01005792 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005793{
Takashi Iwai98274f02005-11-17 14:52:34 +01005794 struct hdspm *hdspm = rule->private;
5795 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005796 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005797 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005798 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5799
Adrian Knoth0dca1792011-01-26 19:32:14 +01005800 if (r->min > 96000 && r->max <= 192000) {
5801 struct snd_interval t = {
5802 .min = hdspm->qs_out_channels,
5803 .max = hdspm->qs_out_channels,
5804 .integer = 1,
5805 };
5806 return snd_interval_refine(c, &t);
5807 } else if (r->min > 48000 && r->max <= 96000) {
5808 struct snd_interval t = {
5809 .min = hdspm->ds_out_channels,
5810 .max = hdspm->ds_out_channels,
5811 .integer = 1,
5812 };
5813 return snd_interval_refine(c, &t);
5814 } else if (r->max < 64000) {
5815 struct snd_interval t = {
5816 .min = hdspm->ss_out_channels,
5817 .max = hdspm->ss_out_channels,
5818 .integer = 1,
5819 };
5820 return snd_interval_refine(c, &t);
5821 } else {
5822 }
5823 return 0;
5824}
5825
5826static int snd_hdspm_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
5827 struct snd_pcm_hw_rule * rule)
5828{
5829 struct hdspm *hdspm = rule->private;
5830 struct snd_interval *c =
5831 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5832 struct snd_interval *r =
5833 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5834
5835 if (c->min >= hdspm->ss_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005836 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005837 .min = 32000,
5838 .max = 48000,
5839 .integer = 1,
5840 };
5841 return snd_interval_refine(r, &t);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005842 } else if (c->max <= hdspm->qs_in_channels) {
5843 struct snd_interval t = {
5844 .min = 128000,
5845 .max = 192000,
5846 .integer = 1,
5847 };
5848 return snd_interval_refine(r, &t);
5849 } else if (c->max <= hdspm->ds_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005850 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005851 .min = 64000,
5852 .max = 96000,
5853 .integer = 1,
5854 };
Takashi Iwai763f3562005-06-03 11:25:34 +02005855 return snd_interval_refine(r, &t);
5856 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005857
5858 return 0;
5859}
5860static int snd_hdspm_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
5861 struct snd_pcm_hw_rule *rule)
5862{
5863 struct hdspm *hdspm = rule->private;
5864 struct snd_interval *c =
5865 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5866 struct snd_interval *r =
5867 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5868
5869 if (c->min >= hdspm->ss_out_channels) {
5870 struct snd_interval t = {
5871 .min = 32000,
5872 .max = 48000,
5873 .integer = 1,
5874 };
5875 return snd_interval_refine(r, &t);
5876 } else if (c->max <= hdspm->qs_out_channels) {
5877 struct snd_interval t = {
5878 .min = 128000,
5879 .max = 192000,
5880 .integer = 1,
5881 };
5882 return snd_interval_refine(r, &t);
5883 } else if (c->max <= hdspm->ds_out_channels) {
5884 struct snd_interval t = {
5885 .min = 64000,
5886 .max = 96000,
5887 .integer = 1,
5888 };
5889 return snd_interval_refine(r, &t);
5890 }
5891
Takashi Iwai763f3562005-06-03 11:25:34 +02005892 return 0;
5893}
5894
Adrian Knoth0dca1792011-01-26 19:32:14 +01005895static int snd_hdspm_hw_rule_in_channels(struct snd_pcm_hw_params *params,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005896 struct snd_pcm_hw_rule *rule)
5897{
5898 unsigned int list[3];
5899 struct hdspm *hdspm = rule->private;
5900 struct snd_interval *c = hw_param_interval(params,
5901 SNDRV_PCM_HW_PARAM_CHANNELS);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005902
5903 list[0] = hdspm->qs_in_channels;
5904 list[1] = hdspm->ds_in_channels;
5905 list[2] = hdspm->ss_in_channels;
5906 return snd_interval_list(c, 3, list, 0);
5907}
5908
5909static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params,
5910 struct snd_pcm_hw_rule *rule)
5911{
5912 unsigned int list[3];
5913 struct hdspm *hdspm = rule->private;
5914 struct snd_interval *c = hw_param_interval(params,
5915 SNDRV_PCM_HW_PARAM_CHANNELS);
5916
5917 list[0] = hdspm->qs_out_channels;
5918 list[1] = hdspm->ds_out_channels;
5919 list[2] = hdspm->ss_out_channels;
5920 return snd_interval_list(c, 3, list, 0);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005921}
5922
5923
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005924static unsigned int hdspm_aes32_sample_rates[] = {
5925 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000
5926};
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005927
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005928static struct snd_pcm_hw_constraint_list
5929hdspm_hw_constraints_aes32_sample_rates = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005930 .count = ARRAY_SIZE(hdspm_aes32_sample_rates),
5931 .list = hdspm_aes32_sample_rates,
5932 .mask = 0
5933};
5934
Takashi Iwai98274f02005-11-17 14:52:34 +01005935static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005936{
Takashi Iwai98274f02005-11-17 14:52:34 +01005937 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5938 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02005939
Takashi Iwai763f3562005-06-03 11:25:34 +02005940 spin_lock_irq(&hdspm->lock);
5941
5942 snd_pcm_set_sync(substream);
5943
Adrian Knoth0dca1792011-01-26 19:32:14 +01005944
Takashi Iwai763f3562005-06-03 11:25:34 +02005945 runtime->hw = snd_hdspm_playback_subinfo;
5946
5947 if (hdspm->capture_substream == NULL)
5948 hdspm_stop_audio(hdspm);
5949
5950 hdspm->playback_pid = current->pid;
5951 hdspm->playback_substream = substream;
5952
5953 spin_unlock_irq(&hdspm->lock);
5954
5955 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Takashi Iwaid8776812011-08-15 10:45:42 +02005956 snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005957
Adrian Knoth0dca1792011-01-26 19:32:14 +01005958 switch (hdspm->io_type) {
5959 case AIO:
5960 case RayDAT:
Takashi Iwaid8776812011-08-15 10:45:42 +02005961 snd_pcm_hw_constraint_minmax(runtime,
5962 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5963 32, 4096);
5964 /* RayDAT & AIO have a fixed buffer of 16384 samples per channel */
5965 snd_pcm_hw_constraint_minmax(runtime,
5966 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
5967 16384, 16384);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005968 break;
5969
5970 default:
Takashi Iwaid8776812011-08-15 10:45:42 +02005971 snd_pcm_hw_constraint_minmax(runtime,
5972 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5973 64, 8192);
5974 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005975 }
5976
5977 if (AES32 == hdspm->io_type) {
Takashi Iwai3fa9e3d2011-08-15 10:42:23 +02005978 runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005979 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
5980 &hdspm_hw_constraints_aes32_sample_rates);
5981 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005982 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005983 snd_hdspm_hw_rule_rate_out_channels, hdspm,
5984 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005985 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01005986
5987 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5988 snd_hdspm_hw_rule_out_channels, hdspm,
5989 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
5990
5991 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5992 snd_hdspm_hw_rule_out_channels_rate, hdspm,
5993 SNDRV_PCM_HW_PARAM_RATE, -1);
5994
Takashi Iwai763f3562005-06-03 11:25:34 +02005995 return 0;
5996}
5997
Takashi Iwai98274f02005-11-17 14:52:34 +01005998static int snd_hdspm_playback_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005999{
Takashi Iwai98274f02005-11-17 14:52:34 +01006000 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02006001
6002 spin_lock_irq(&hdspm->lock);
6003
6004 hdspm->playback_pid = -1;
6005 hdspm->playback_substream = NULL;
6006
6007 spin_unlock_irq(&hdspm->lock);
6008
6009 return 0;
6010}
6011
6012
Takashi Iwai98274f02005-11-17 14:52:34 +01006013static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02006014{
Takashi Iwai98274f02005-11-17 14:52:34 +01006015 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
6016 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02006017
6018 spin_lock_irq(&hdspm->lock);
6019 snd_pcm_set_sync(substream);
6020 runtime->hw = snd_hdspm_capture_subinfo;
6021
6022 if (hdspm->playback_substream == NULL)
6023 hdspm_stop_audio(hdspm);
6024
6025 hdspm->capture_pid = current->pid;
6026 hdspm->capture_substream = substream;
6027
6028 spin_unlock_irq(&hdspm->lock);
6029
6030 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Takashi Iwaid8776812011-08-15 10:45:42 +02006031 snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
6032
Adrian Knoth0dca1792011-01-26 19:32:14 +01006033 switch (hdspm->io_type) {
6034 case AIO:
6035 case RayDAT:
Takashi Iwaid8776812011-08-15 10:45:42 +02006036 snd_pcm_hw_constraint_minmax(runtime,
6037 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
6038 32, 4096);
6039 snd_pcm_hw_constraint_minmax(runtime,
6040 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
6041 16384, 16384);
6042 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006043
6044 default:
Takashi Iwaid8776812011-08-15 10:45:42 +02006045 snd_pcm_hw_constraint_minmax(runtime,
6046 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
6047 64, 8192);
6048 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006049 }
6050
6051 if (AES32 == hdspm->io_type) {
Takashi Iwai3fa9e3d2011-08-15 10:42:23 +02006052 runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006053 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
6054 &hdspm_hw_constraints_aes32_sample_rates);
6055 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006056 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth88fabbf2011-02-23 11:43:10 +01006057 snd_hdspm_hw_rule_rate_in_channels, hdspm,
6058 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006059 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01006060
6061 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
6062 snd_hdspm_hw_rule_in_channels, hdspm,
6063 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
6064
6065 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
6066 snd_hdspm_hw_rule_in_channels_rate, hdspm,
6067 SNDRV_PCM_HW_PARAM_RATE, -1);
6068
Takashi Iwai763f3562005-06-03 11:25:34 +02006069 return 0;
6070}
6071
Takashi Iwai98274f02005-11-17 14:52:34 +01006072static int snd_hdspm_capture_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02006073{
Takashi Iwai98274f02005-11-17 14:52:34 +01006074 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02006075
6076 spin_lock_irq(&hdspm->lock);
6077
6078 hdspm->capture_pid = -1;
6079 hdspm->capture_substream = NULL;
6080
6081 spin_unlock_irq(&hdspm->lock);
6082 return 0;
6083}
6084
Adrian Knoth0dca1792011-01-26 19:32:14 +01006085static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
Takashi Iwai763f3562005-06-03 11:25:34 +02006086{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006087 /* we have nothing to initialize but the call is required */
6088 return 0;
6089}
6090
6091static inline int copy_u32_le(void __user *dest, void __iomem *src)
6092{
6093 u32 val = readl(src);
6094 return copy_to_user(dest, &val, 4);
6095}
6096
6097static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006098 unsigned int cmd, unsigned long arg)
Adrian Knoth0dca1792011-01-26 19:32:14 +01006099{
6100 void __user *argp = (void __user *)arg;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006101 struct hdspm *hdspm = hw->private_data;
Takashi Iwai98274f02005-11-17 14:52:34 +01006102 struct hdspm_mixer_ioctl mixer;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006103 struct hdspm_config info;
6104 struct hdspm_status status;
Takashi Iwai98274f02005-11-17 14:52:34 +01006105 struct hdspm_version hdspm_version;
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006106 struct hdspm_peak_rms *levels;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006107 struct hdspm_ltc ltc;
6108 unsigned int statusregister;
6109 long unsigned int s;
6110 int i = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02006111
6112 switch (cmd) {
6113
Takashi Iwai763f3562005-06-03 11:25:34 +02006114 case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006115 levels = &hdspm->peak_rms;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006116 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006117 levels->input_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006118 readl(hdspm->iobase +
6119 HDSPM_MADI_INPUT_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006120 levels->playback_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006121 readl(hdspm->iobase +
6122 HDSPM_MADI_PLAYBACK_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006123 levels->output_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006124 readl(hdspm->iobase +
6125 HDSPM_MADI_OUTPUT_PEAK + i*4);
6126
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006127 levels->input_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006128 ((uint64_t) readl(hdspm->iobase +
6129 HDSPM_MADI_INPUT_RMS_H + i*4) << 32) |
6130 (uint64_t) readl(hdspm->iobase +
6131 HDSPM_MADI_INPUT_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006132 levels->playback_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006133 ((uint64_t)readl(hdspm->iobase +
6134 HDSPM_MADI_PLAYBACK_RMS_H+i*4) << 32) |
6135 (uint64_t)readl(hdspm->iobase +
6136 HDSPM_MADI_PLAYBACK_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006137 levels->output_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006138 ((uint64_t)readl(hdspm->iobase +
6139 HDSPM_MADI_OUTPUT_RMS_H + i*4) << 32) |
6140 (uint64_t)readl(hdspm->iobase +
6141 HDSPM_MADI_OUTPUT_RMS_L + i*4);
6142 }
6143
6144 if (hdspm->system_sample_rate > 96000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006145 levels->speed = qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006146 } else if (hdspm->system_sample_rate > 48000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006147 levels->speed = ds;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006148 } else {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006149 levels->speed = ss;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006150 }
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006151 levels->status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006152
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006153 s = copy_to_user(argp, levels, sizeof(struct hdspm_peak_rms));
Adrian Knoth0dca1792011-01-26 19:32:14 +01006154 if (0 != s) {
6155 /* snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu
6156 [Levels]\n", sizeof(struct hdspm_peak_rms), s);
6157 */
Takashi Iwai763f3562005-06-03 11:25:34 +02006158 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006159 }
6160 break;
6161
6162 case SNDRV_HDSPM_IOCTL_GET_LTC:
6163 ltc.ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
6164 i = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
6165 if (i & HDSPM_TCO1_LTC_Input_valid) {
6166 switch (i & (HDSPM_TCO1_LTC_Format_LSB |
6167 HDSPM_TCO1_LTC_Format_MSB)) {
6168 case 0:
6169 ltc.format = fps_24;
6170 break;
6171 case HDSPM_TCO1_LTC_Format_LSB:
6172 ltc.format = fps_25;
6173 break;
6174 case HDSPM_TCO1_LTC_Format_MSB:
6175 ltc.format = fps_2997;
6176 break;
6177 default:
6178 ltc.format = 30;
6179 break;
6180 }
6181 if (i & HDSPM_TCO1_set_drop_frame_flag) {
6182 ltc.frame = drop_frame;
6183 } else {
6184 ltc.frame = full_frame;
6185 }
6186 } else {
6187 ltc.format = format_invalid;
6188 ltc.frame = frame_invalid;
6189 }
6190 if (i & HDSPM_TCO1_Video_Input_Format_NTSC) {
6191 ltc.input_format = ntsc;
6192 } else if (i & HDSPM_TCO1_Video_Input_Format_PAL) {
6193 ltc.input_format = pal;
6194 } else {
6195 ltc.input_format = no_video;
6196 }
6197
6198 s = copy_to_user(argp, &ltc, sizeof(struct hdspm_ltc));
6199 if (0 != s) {
6200 /*
6201 snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */
Takashi Iwai763f3562005-06-03 11:25:34 +02006202 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006203 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006204
6205 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02006206
Adrian Knoth0dca1792011-01-26 19:32:14 +01006207 case SNDRV_HDSPM_IOCTL_GET_CONFIG:
Takashi Iwai763f3562005-06-03 11:25:34 +02006208
Adrian Knoth4ab69a22011-02-23 11:43:14 +01006209 memset(&info, 0, sizeof(info));
Takashi Iwai763f3562005-06-03 11:25:34 +02006210 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006211 info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
6212 info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006213
6214 info.system_sample_rate = hdspm->system_sample_rate;
6215 info.autosync_sample_rate =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006216 hdspm_external_sample_rate(hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006217 info.system_clock_mode = hdspm_system_clock_mode(hdspm);
6218 info.clock_source = hdspm_clock_source(hdspm);
6219 info.autosync_ref = hdspm_autosync_ref(hdspm);
Adrian Knothc9e16682012-12-03 14:55:50 +01006220 info.line_out = hdspm_toggle_setting(hdspm, HDSPM_LineOut);
Takashi Iwai763f3562005-06-03 11:25:34 +02006221 info.passthru = 0;
6222 spin_unlock_irq(&hdspm->lock);
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006223 if (copy_to_user(argp, &info, sizeof(info)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006224 return -EFAULT;
6225 break;
6226
Adrian Knoth0dca1792011-01-26 19:32:14 +01006227 case SNDRV_HDSPM_IOCTL_GET_STATUS:
Dan Carpenter643d6bb2011-09-23 09:24:21 +03006228 memset(&status, 0, sizeof(status));
6229
Adrian Knoth0dca1792011-01-26 19:32:14 +01006230 status.card_type = hdspm->io_type;
6231
6232 status.autosync_source = hdspm_autosync_ref(hdspm);
6233
6234 status.card_clock = 110069313433624ULL;
6235 status.master_period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
6236
6237 switch (hdspm->io_type) {
6238 case MADI:
6239 case MADIface:
6240 status.card_specific.madi.sync_wc =
6241 hdspm_wc_sync_check(hdspm);
6242 status.card_specific.madi.sync_madi =
6243 hdspm_madi_sync_check(hdspm);
6244 status.card_specific.madi.sync_tco =
6245 hdspm_tco_sync_check(hdspm);
6246 status.card_specific.madi.sync_in =
6247 hdspm_sync_in_sync_check(hdspm);
6248
6249 statusregister =
6250 hdspm_read(hdspm, HDSPM_statusRegister);
6251 status.card_specific.madi.madi_input =
6252 (statusregister & HDSPM_AB_int) ? 1 : 0;
6253 status.card_specific.madi.channel_format =
Adrian Knoth9e6ff522011-10-27 21:57:52 +02006254 (statusregister & HDSPM_RX_64ch) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006255 /* TODO: Mac driver sets it when f_s>48kHz */
6256 status.card_specific.madi.frame_format = 0;
6257
6258 default:
6259 break;
6260 }
6261
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006262 if (copy_to_user(argp, &status, sizeof(status)))
Adrian Knoth0dca1792011-01-26 19:32:14 +01006263 return -EFAULT;
6264
6265
6266 break;
6267
Takashi Iwai763f3562005-06-03 11:25:34 +02006268 case SNDRV_HDSPM_IOCTL_GET_VERSION:
Dan Carpenter643d6bb2011-09-23 09:24:21 +03006269 memset(&hdspm_version, 0, sizeof(hdspm_version));
6270
Adrian Knoth0dca1792011-01-26 19:32:14 +01006271 hdspm_version.card_type = hdspm->io_type;
6272 strncpy(hdspm_version.cardname, hdspm->card_name,
6273 sizeof(hdspm_version.cardname));
Adrian Knoth7d53a632012-01-04 14:31:16 +01006274 hdspm_version.serial = hdspm->serial;
Takashi Iwai763f3562005-06-03 11:25:34 +02006275 hdspm_version.firmware_rev = hdspm->firmware_rev;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006276 hdspm_version.addons = 0;
6277 if (hdspm->tco)
6278 hdspm_version.addons |= HDSPM_ADDON_TCO;
6279
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006280 if (copy_to_user(argp, &hdspm_version,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006281 sizeof(hdspm_version)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006282 return -EFAULT;
6283 break;
6284
6285 case SNDRV_HDSPM_IOCTL_GET_MIXER:
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006286 if (copy_from_user(&mixer, argp, sizeof(mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006287 return -EFAULT;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006288 if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006289 sizeof(struct hdspm_mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006290 return -EFAULT;
6291 break;
6292
6293 default:
6294 return -EINVAL;
6295 }
6296 return 0;
6297}
6298
Takashi Iwai98274f02005-11-17 14:52:34 +01006299static struct snd_pcm_ops snd_hdspm_playback_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006300 .open = snd_hdspm_playback_open,
6301 .close = snd_hdspm_playback_release,
6302 .ioctl = snd_hdspm_ioctl,
6303 .hw_params = snd_hdspm_hw_params,
6304 .hw_free = snd_hdspm_hw_free,
6305 .prepare = snd_hdspm_prepare,
6306 .trigger = snd_hdspm_trigger,
6307 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006308 .page = snd_pcm_sgbuf_ops_page,
6309};
6310
Takashi Iwai98274f02005-11-17 14:52:34 +01006311static struct snd_pcm_ops snd_hdspm_capture_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006312 .open = snd_hdspm_capture_open,
6313 .close = snd_hdspm_capture_release,
6314 .ioctl = snd_hdspm_ioctl,
6315 .hw_params = snd_hdspm_hw_params,
6316 .hw_free = snd_hdspm_hw_free,
6317 .prepare = snd_hdspm_prepare,
6318 .trigger = snd_hdspm_trigger,
6319 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006320 .page = snd_pcm_sgbuf_ops_page,
6321};
6322
Bill Pembertone23e7a12012-12-06 12:35:10 -05006323static int snd_hdspm_create_hwdep(struct snd_card *card,
6324 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006325{
Takashi Iwai98274f02005-11-17 14:52:34 +01006326 struct snd_hwdep *hw;
Takashi Iwai763f3562005-06-03 11:25:34 +02006327 int err;
6328
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006329 err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw);
6330 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006331 return err;
6332
6333 hdspm->hwdep = hw;
6334 hw->private_data = hdspm;
6335 strcpy(hw->name, "HDSPM hwdep interface");
6336
Adrian Knoth0dca1792011-01-26 19:32:14 +01006337 hw->ops.open = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006338 hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
Adrian Knoth8de5d6f2012-03-08 15:38:04 +01006339 hw->ops.ioctl_compat = snd_hdspm_hwdep_ioctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006340 hw->ops.release = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006341
6342 return 0;
6343}
6344
6345
6346/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01006347 memory interface
Takashi Iwai763f3562005-06-03 11:25:34 +02006348 ------------------------------------------------------------*/
Bill Pembertone23e7a12012-12-06 12:35:10 -05006349static int snd_hdspm_preallocate_memory(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006350{
6351 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01006352 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006353 size_t wanted;
6354
6355 pcm = hdspm->pcm;
6356
Remy Bruno3cee5a62006-10-16 12:46:32 +02006357 wanted = HDSPM_DMA_AREA_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02006358
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006359 err =
Takashi Iwai763f3562005-06-03 11:25:34 +02006360 snd_pcm_lib_preallocate_pages_for_all(pcm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006361 SNDRV_DMA_TYPE_DEV_SG,
Takashi Iwai763f3562005-06-03 11:25:34 +02006362 snd_dma_pci_data(hdspm->pci),
6363 wanted,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006364 wanted);
6365 if (err < 0) {
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006366 snd_printdd("Could not preallocate %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006367
6368 return err;
6369 } else
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006370 snd_printdd(" Preallocated %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006371
6372 return 0;
6373}
6374
Adrian Knoth0dca1792011-01-26 19:32:14 +01006375
6376static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +02006377 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02006378 unsigned int reg, int channels)
6379{
6380 int i;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006381
6382 /* continuous memory segment */
Takashi Iwai763f3562005-06-03 11:25:34 +02006383 for (i = 0; i < (channels * 16); i++)
6384 hdspm_write(hdspm, reg + 4 * i,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006385 snd_pcm_sgbuf_get_addr(substream, 4096 * i));
Takashi Iwai763f3562005-06-03 11:25:34 +02006386}
6387
Adrian Knoth0dca1792011-01-26 19:32:14 +01006388
Takashi Iwai763f3562005-06-03 11:25:34 +02006389/* ------------- ALSA Devices ---------------------------- */
Bill Pembertone23e7a12012-12-06 12:35:10 -05006390static int snd_hdspm_create_pcm(struct snd_card *card,
6391 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006392{
Takashi Iwai98274f02005-11-17 14:52:34 +01006393 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006394 int err;
6395
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006396 err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm);
6397 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006398 return err;
6399
6400 hdspm->pcm = pcm;
6401 pcm->private_data = hdspm;
6402 strcpy(pcm->name, hdspm->card_name);
6403
6404 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
6405 &snd_hdspm_playback_ops);
6406 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
6407 &snd_hdspm_capture_ops);
6408
6409 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
6410
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006411 err = snd_hdspm_preallocate_memory(hdspm);
6412 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006413 return err;
6414
6415 return 0;
6416}
6417
Takashi Iwai98274f02005-11-17 14:52:34 +01006418static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006419{
Adrian Knoth7c7102b2011-02-28 15:14:50 +01006420 int i;
6421
6422 for (i = 0; i < hdspm->midiPorts; i++)
6423 snd_hdspm_flush_midi_input(hdspm, i);
Takashi Iwai763f3562005-06-03 11:25:34 +02006424}
6425
Bill Pembertone23e7a12012-12-06 12:35:10 -05006426static int snd_hdspm_create_alsa_devices(struct snd_card *card,
6427 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006428{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006429 int err, i;
Takashi Iwai763f3562005-06-03 11:25:34 +02006430
6431 snd_printdd("Create card...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006432 err = snd_hdspm_create_pcm(card, hdspm);
6433 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006434 return err;
6435
Adrian Knoth0dca1792011-01-26 19:32:14 +01006436 i = 0;
6437 while (i < hdspm->midiPorts) {
6438 err = snd_hdspm_create_midi(card, hdspm, i);
6439 if (err < 0) {
6440 return err;
6441 }
6442 i++;
6443 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006444
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006445 err = snd_hdspm_create_controls(card, hdspm);
6446 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006447 return err;
6448
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006449 err = snd_hdspm_create_hwdep(card, hdspm);
6450 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006451 return err;
6452
6453 snd_printdd("proc init...\n");
6454 snd_hdspm_proc_init(hdspm);
6455
6456 hdspm->system_sample_rate = -1;
6457 hdspm->last_external_sample_rate = -1;
6458 hdspm->last_internal_sample_rate = -1;
6459 hdspm->playback_pid = -1;
6460 hdspm->capture_pid = -1;
6461 hdspm->capture_substream = NULL;
6462 hdspm->playback_substream = NULL;
6463
6464 snd_printdd("Set defaults...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006465 err = snd_hdspm_set_defaults(hdspm);
6466 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006467 return err;
6468
6469 snd_printdd("Update mixer controls...\n");
6470 hdspm_update_simple_mixer_controls(hdspm);
6471
6472 snd_printdd("Initializeing complete ???\n");
6473
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006474 err = snd_card_register(card);
6475 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006476 snd_printk(KERN_ERR "HDSPM: error registering card\n");
6477 return err;
6478 }
6479
6480 snd_printdd("... yes now\n");
6481
6482 return 0;
6483}
6484
Bill Pembertone23e7a12012-12-06 12:35:10 -05006485static int snd_hdspm_create(struct snd_card *card,
6486 struct hdspm *hdspm)
6487{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006488
Takashi Iwai763f3562005-06-03 11:25:34 +02006489 struct pci_dev *pci = hdspm->pci;
6490 int err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006491 unsigned long io_extent;
6492
6493 hdspm->irq = -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02006494 hdspm->card = card;
6495
6496 spin_lock_init(&hdspm->lock);
6497
Takashi Iwai763f3562005-06-03 11:25:34 +02006498 pci_read_config_word(hdspm->pci,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006499 PCI_CLASS_REVISION, &hdspm->firmware_rev);
Remy Bruno3cee5a62006-10-16 12:46:32 +02006500
Takashi Iwai763f3562005-06-03 11:25:34 +02006501 strcpy(card->mixername, "Xilinx FPGA");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006502 strcpy(card->driver, "HDSPM");
6503
6504 switch (hdspm->firmware_rev) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01006505 case HDSPM_RAYDAT_REV:
6506 hdspm->io_type = RayDAT;
6507 hdspm->card_name = "RME RayDAT";
6508 hdspm->midiPorts = 2;
6509 break;
6510 case HDSPM_AIO_REV:
6511 hdspm->io_type = AIO;
6512 hdspm->card_name = "RME AIO";
6513 hdspm->midiPorts = 1;
6514 break;
6515 case HDSPM_MADIFACE_REV:
6516 hdspm->io_type = MADIface;
6517 hdspm->card_name = "RME MADIface";
6518 hdspm->midiPorts = 1;
6519 break;
Adrian Knoth5027f342011-02-28 15:14:49 +01006520 default:
Adrian Knothc09403d2011-10-27 21:57:54 +02006521 if ((hdspm->firmware_rev == 0xf0) ||
6522 ((hdspm->firmware_rev >= 0xe6) &&
6523 (hdspm->firmware_rev <= 0xea))) {
6524 hdspm->io_type = AES32;
6525 hdspm->card_name = "RME AES32";
6526 hdspm->midiPorts = 2;
Adrian Knoth05c7cc92011-11-21 16:15:36 +01006527 } else if ((hdspm->firmware_rev == 0xd2) ||
Adrian Knothc09403d2011-10-27 21:57:54 +02006528 ((hdspm->firmware_rev >= 0xc8) &&
6529 (hdspm->firmware_rev <= 0xcf))) {
6530 hdspm->io_type = MADI;
6531 hdspm->card_name = "RME MADI";
6532 hdspm->midiPorts = 3;
6533 } else {
6534 snd_printk(KERN_ERR
6535 "HDSPM: unknown firmware revision %x\n",
Adrian Knoth5027f342011-02-28 15:14:49 +01006536 hdspm->firmware_rev);
Adrian Knothc09403d2011-10-27 21:57:54 +02006537 return -ENODEV;
6538 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02006539 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006540
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006541 err = pci_enable_device(pci);
6542 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006543 return err;
6544
6545 pci_set_master(hdspm->pci);
6546
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006547 err = pci_request_regions(pci, "hdspm");
6548 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006549 return err;
6550
6551 hdspm->port = pci_resource_start(pci, 0);
6552 io_extent = pci_resource_len(pci, 0);
6553
6554 snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006555 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006556
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006557 hdspm->iobase = ioremap_nocache(hdspm->port, io_extent);
6558 if (!hdspm->iobase) {
6559 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006560 "unable to remap region 0x%lx-0x%lx\n",
6561 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006562 return -EBUSY;
6563 }
6564 snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006565 (unsigned long)hdspm->iobase, hdspm->port,
6566 hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006567
6568 if (request_irq(pci->irq, snd_hdspm_interrupt,
Takashi Iwai934c2b62011-06-10 16:36:37 +02006569 IRQF_SHARED, KBUILD_MODNAME, hdspm)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006570 snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
6571 return -EBUSY;
6572 }
6573
6574 snd_printdd("use IRQ %d\n", pci->irq);
6575
6576 hdspm->irq = pci->irq;
Takashi Iwai763f3562005-06-03 11:25:34 +02006577
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006578 snd_printdd("kmalloc Mixer memory of %zd Bytes\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006579 sizeof(struct hdspm_mixer));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006580 hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL);
6581 if (!hdspm->mixer) {
6582 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006583 "unable to kmalloc Mixer memory of %d Bytes\n",
6584 (int)sizeof(struct hdspm_mixer));
Julia Lawallb17cbdd2012-08-19 09:02:54 +02006585 return -ENOMEM;
Takashi Iwai763f3562005-06-03 11:25:34 +02006586 }
6587
Adrian Knoth0dca1792011-01-26 19:32:14 +01006588 hdspm->port_names_in = NULL;
6589 hdspm->port_names_out = NULL;
6590
6591 switch (hdspm->io_type) {
6592 case AES32:
Adrian Knothd2d10a22011-02-28 15:14:47 +01006593 hdspm->ss_in_channels = hdspm->ss_out_channels = AES32_CHANNELS;
6594 hdspm->ds_in_channels = hdspm->ds_out_channels = AES32_CHANNELS;
6595 hdspm->qs_in_channels = hdspm->qs_out_channels = AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006596
6597 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6598 channel_map_aes32;
6599 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6600 channel_map_aes32;
6601 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6602 channel_map_aes32;
6603 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6604 texts_ports_aes32;
6605 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6606 texts_ports_aes32;
6607 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6608 texts_ports_aes32;
6609
Adrian Knothd2d10a22011-02-28 15:14:47 +01006610 hdspm->max_channels_out = hdspm->max_channels_in =
6611 AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006612 hdspm->port_names_in = hdspm->port_names_out =
6613 texts_ports_aes32;
6614 hdspm->channel_map_in = hdspm->channel_map_out =
6615 channel_map_aes32;
6616
Adrian Knoth0dca1792011-01-26 19:32:14 +01006617 break;
6618
6619 case MADI:
6620 case MADIface:
6621 hdspm->ss_in_channels = hdspm->ss_out_channels =
6622 MADI_SS_CHANNELS;
6623 hdspm->ds_in_channels = hdspm->ds_out_channels =
6624 MADI_DS_CHANNELS;
6625 hdspm->qs_in_channels = hdspm->qs_out_channels =
6626 MADI_QS_CHANNELS;
6627
6628 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6629 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006630 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006631 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006632 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006633 channel_map_unity_ss;
6634
6635 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6636 texts_ports_madi;
6637 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6638 texts_ports_madi;
6639 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6640 texts_ports_madi;
6641 break;
6642
6643 case AIO:
Adrian Knoth0dca1792011-01-26 19:32:14 +01006644 hdspm->ss_in_channels = AIO_IN_SS_CHANNELS;
6645 hdspm->ds_in_channels = AIO_IN_DS_CHANNELS;
6646 hdspm->qs_in_channels = AIO_IN_QS_CHANNELS;
6647 hdspm->ss_out_channels = AIO_OUT_SS_CHANNELS;
6648 hdspm->ds_out_channels = AIO_OUT_DS_CHANNELS;
6649 hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS;
6650
Adrian Knoth3de9db22013-07-05 11:28:02 +02006651 if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) {
6652 snd_printk(KERN_INFO "HDSPM: AEB input board found\n");
6653 hdspm->ss_in_channels += 4;
6654 hdspm->ds_in_channels += 4;
6655 hdspm->qs_in_channels += 4;
6656 }
6657
6658 if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBO_D)) {
6659 snd_printk(KERN_INFO "HDSPM: AEB output board found\n");
6660 hdspm->ss_out_channels += 4;
6661 hdspm->ds_out_channels += 4;
6662 hdspm->qs_out_channels += 4;
6663 }
6664
Adrian Knoth0dca1792011-01-26 19:32:14 +01006665 hdspm->channel_map_out_ss = channel_map_aio_out_ss;
6666 hdspm->channel_map_out_ds = channel_map_aio_out_ds;
6667 hdspm->channel_map_out_qs = channel_map_aio_out_qs;
6668
6669 hdspm->channel_map_in_ss = channel_map_aio_in_ss;
6670 hdspm->channel_map_in_ds = channel_map_aio_in_ds;
6671 hdspm->channel_map_in_qs = channel_map_aio_in_qs;
6672
6673 hdspm->port_names_in_ss = texts_ports_aio_in_ss;
6674 hdspm->port_names_out_ss = texts_ports_aio_out_ss;
6675 hdspm->port_names_in_ds = texts_ports_aio_in_ds;
6676 hdspm->port_names_out_ds = texts_ports_aio_out_ds;
6677 hdspm->port_names_in_qs = texts_ports_aio_in_qs;
6678 hdspm->port_names_out_qs = texts_ports_aio_out_qs;
6679
6680 break;
6681
6682 case RayDAT:
6683 hdspm->ss_in_channels = hdspm->ss_out_channels =
6684 RAYDAT_SS_CHANNELS;
6685 hdspm->ds_in_channels = hdspm->ds_out_channels =
6686 RAYDAT_DS_CHANNELS;
6687 hdspm->qs_in_channels = hdspm->qs_out_channels =
6688 RAYDAT_QS_CHANNELS;
6689
6690 hdspm->max_channels_in = RAYDAT_SS_CHANNELS;
6691 hdspm->max_channels_out = RAYDAT_SS_CHANNELS;
6692
6693 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6694 channel_map_raydat_ss;
6695 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6696 channel_map_raydat_ds;
6697 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6698 channel_map_raydat_qs;
6699 hdspm->channel_map_in = hdspm->channel_map_out =
6700 channel_map_raydat_ss;
6701
6702 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6703 texts_ports_raydat_ss;
6704 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6705 texts_ports_raydat_ds;
6706 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6707 texts_ports_raydat_qs;
6708
6709
6710 break;
6711
6712 }
6713
6714 /* TCO detection */
6715 switch (hdspm->io_type) {
6716 case AIO:
6717 case RayDAT:
6718 if (hdspm_read(hdspm, HDSPM_statusRegister2) &
6719 HDSPM_s2_tco_detect) {
6720 hdspm->midiPorts++;
6721 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6722 GFP_KERNEL);
6723 if (NULL != hdspm->tco) {
6724 hdspm_tco_write(hdspm);
6725 }
6726 snd_printk(KERN_INFO "HDSPM: AIO/RayDAT TCO module found\n");
6727 } else {
6728 hdspm->tco = NULL;
6729 }
6730 break;
6731
6732 case MADI:
6733 if (hdspm_read(hdspm, HDSPM_statusRegister) & HDSPM_tco_detect) {
6734 hdspm->midiPorts++;
6735 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6736 GFP_KERNEL);
6737 if (NULL != hdspm->tco) {
6738 hdspm_tco_write(hdspm);
6739 }
6740 snd_printk(KERN_INFO "HDSPM: MADI TCO module found\n");
6741 } else {
6742 hdspm->tco = NULL;
6743 }
6744 break;
6745
6746 default:
6747 hdspm->tco = NULL;
6748 }
6749
6750 /* texts */
6751 switch (hdspm->io_type) {
6752 case AES32:
6753 if (hdspm->tco) {
6754 hdspm->texts_autosync = texts_autosync_aes_tco;
6755 hdspm->texts_autosync_items = 10;
6756 } else {
6757 hdspm->texts_autosync = texts_autosync_aes;
6758 hdspm->texts_autosync_items = 9;
6759 }
6760 break;
6761
6762 case MADI:
6763 if (hdspm->tco) {
6764 hdspm->texts_autosync = texts_autosync_madi_tco;
6765 hdspm->texts_autosync_items = 4;
6766 } else {
6767 hdspm->texts_autosync = texts_autosync_madi;
6768 hdspm->texts_autosync_items = 3;
6769 }
6770 break;
6771
6772 case MADIface:
6773
6774 break;
6775
6776 case RayDAT:
6777 if (hdspm->tco) {
6778 hdspm->texts_autosync = texts_autosync_raydat_tco;
6779 hdspm->texts_autosync_items = 9;
6780 } else {
6781 hdspm->texts_autosync = texts_autosync_raydat;
6782 hdspm->texts_autosync_items = 8;
6783 }
6784 break;
6785
6786 case AIO:
6787 if (hdspm->tco) {
6788 hdspm->texts_autosync = texts_autosync_aio_tco;
6789 hdspm->texts_autosync_items = 6;
6790 } else {
6791 hdspm->texts_autosync = texts_autosync_aio;
6792 hdspm->texts_autosync_items = 5;
6793 }
6794 break;
6795
6796 }
6797
6798 tasklet_init(&hdspm->midi_tasklet,
6799 hdspm_midi_tasklet, (unsigned long) hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006800
Adrian Knothf7de8ba2012-01-10 20:58:40 +01006801
6802 if (hdspm->io_type != MADIface) {
6803 hdspm->serial = (hdspm_read(hdspm,
6804 HDSPM_midiStatusIn0)>>8) & 0xFFFFFF;
6805 /* id contains either a user-provided value or the default
6806 * NULL. If it's the default, we're safe to
6807 * fill card->id with the serial number.
6808 *
6809 * If the serial number is 0xFFFFFF, then we're dealing with
6810 * an old PCI revision that comes without a sane number. In
6811 * this case, we don't set card->id to avoid collisions
6812 * when running with multiple cards.
6813 */
6814 if (NULL == id[hdspm->dev] && hdspm->serial != 0xFFFFFF) {
6815 sprintf(card->id, "HDSPMx%06x", hdspm->serial);
6816 snd_card_set_id(card, card->id);
6817 }
6818 }
6819
Takashi Iwai763f3562005-06-03 11:25:34 +02006820 snd_printdd("create alsa devices.\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006821 err = snd_hdspm_create_alsa_devices(card, hdspm);
6822 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006823 return err;
6824
6825 snd_hdspm_initialize_midi_flush(hdspm);
6826
6827 return 0;
6828}
6829
Adrian Knoth0dca1792011-01-26 19:32:14 +01006830
Takashi Iwai98274f02005-11-17 14:52:34 +01006831static int snd_hdspm_free(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006832{
6833
6834 if (hdspm->port) {
6835
6836 /* stop th audio, and cancel all interrupts */
6837 hdspm->control_register &=
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006838 ~(HDSPM_Start | HDSPM_AudioInterruptEnable |
Adrian Knoth0dca1792011-01-26 19:32:14 +01006839 HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable |
6840 HDSPM_Midi2InterruptEnable | HDSPM_Midi3InterruptEnable);
Takashi Iwai763f3562005-06-03 11:25:34 +02006841 hdspm_write(hdspm, HDSPM_controlRegister,
6842 hdspm->control_register);
6843 }
6844
6845 if (hdspm->irq >= 0)
6846 free_irq(hdspm->irq, (void *) hdspm);
6847
Jesper Juhlfc584222005-10-24 15:11:28 +02006848 kfree(hdspm->mixer);
Takashi Iwai763f3562005-06-03 11:25:34 +02006849
6850 if (hdspm->iobase)
6851 iounmap(hdspm->iobase);
6852
Takashi Iwai763f3562005-06-03 11:25:34 +02006853 if (hdspm->port)
6854 pci_release_regions(hdspm->pci);
6855
6856 pci_disable_device(hdspm->pci);
6857 return 0;
6858}
6859
Adrian Knoth0dca1792011-01-26 19:32:14 +01006860
Takashi Iwai98274f02005-11-17 14:52:34 +01006861static void snd_hdspm_card_free(struct snd_card *card)
Takashi Iwai763f3562005-06-03 11:25:34 +02006862{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006863 struct hdspm *hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006864
6865 if (hdspm)
6866 snd_hdspm_free(hdspm);
6867}
6868
Adrian Knoth0dca1792011-01-26 19:32:14 +01006869
Bill Pembertone23e7a12012-12-06 12:35:10 -05006870static int snd_hdspm_probe(struct pci_dev *pci,
6871 const struct pci_device_id *pci_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02006872{
6873 static int dev;
Takashi Iwai98274f02005-11-17 14:52:34 +01006874 struct hdspm *hdspm;
6875 struct snd_card *card;
Takashi Iwai763f3562005-06-03 11:25:34 +02006876 int err;
6877
6878 if (dev >= SNDRV_CARDS)
6879 return -ENODEV;
6880 if (!enable[dev]) {
6881 dev++;
6882 return -ENOENT;
6883 }
6884
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006885 err = snd_card_create(index[dev], id[dev],
Adrian Knoth0dca1792011-01-26 19:32:14 +01006886 THIS_MODULE, sizeof(struct hdspm), &card);
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006887 if (err < 0)
6888 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006889
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006890 hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006891 card->private_free = snd_hdspm_card_free;
6892 hdspm->dev = dev;
6893 hdspm->pci = pci;
6894
Takashi Iwaic187c042007-02-19 15:27:33 +01006895 snd_card_set_dev(card, &pci->dev);
6896
Adrian Knoth0dca1792011-01-26 19:32:14 +01006897 err = snd_hdspm_create(card, hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006898 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006899 snd_card_free(card);
6900 return err;
6901 }
6902
Adrian Knoth0dca1792011-01-26 19:32:14 +01006903 if (hdspm->io_type != MADIface) {
6904 sprintf(card->shortname, "%s_%x",
6905 hdspm->card_name,
Adrian Knoth7d53a632012-01-04 14:31:16 +01006906 hdspm->serial);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006907 sprintf(card->longname, "%s S/N 0x%x at 0x%lx, irq %d",
6908 hdspm->card_name,
Adrian Knoth7d53a632012-01-04 14:31:16 +01006909 hdspm->serial,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006910 hdspm->port, hdspm->irq);
6911 } else {
6912 sprintf(card->shortname, "%s", hdspm->card_name);
6913 sprintf(card->longname, "%s at 0x%lx, irq %d",
6914 hdspm->card_name, hdspm->port, hdspm->irq);
6915 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006916
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006917 err = snd_card_register(card);
6918 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006919 snd_card_free(card);
6920 return err;
6921 }
6922
6923 pci_set_drvdata(pci, card);
6924
6925 dev++;
6926 return 0;
6927}
6928
Bill Pembertone23e7a12012-12-06 12:35:10 -05006929static void snd_hdspm_remove(struct pci_dev *pci)
Takashi Iwai763f3562005-06-03 11:25:34 +02006930{
6931 snd_card_free(pci_get_drvdata(pci));
Takashi Iwai763f3562005-06-03 11:25:34 +02006932}
6933
Takashi Iwaie9f66d92012-04-24 12:25:00 +02006934static struct pci_driver hdspm_driver = {
Takashi Iwai3733e422011-06-10 16:20:20 +02006935 .name = KBUILD_MODNAME,
Takashi Iwai763f3562005-06-03 11:25:34 +02006936 .id_table = snd_hdspm_ids,
6937 .probe = snd_hdspm_probe,
Bill Pembertone23e7a12012-12-06 12:35:10 -05006938 .remove = snd_hdspm_remove,
Takashi Iwai763f3562005-06-03 11:25:34 +02006939};
6940
Takashi Iwaie9f66d92012-04-24 12:25:00 +02006941module_pci_driver(hdspm_driver);