blob: 9899ef4c7efa74676feab4d3eb393fd6e2ac7c64 [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 */
Martin Dausel69358fc2013-07-05 11:28:23 +020041
42/* ************* Register Documentation *******************************************************
43 *
44 * Work in progress! Documentation is based on the code in this file.
45 *
46 * --------- HDSPM_controlRegister ---------
47 * :7654.3210:7654.3210:7654.3210:7654.3210: bit number per byte
48 * :||||.||||:||||.||||:||||.||||:||||.||||:
49 * :3322.2222:2222.1111:1111.1100:0000.0000: bit number
50 * :1098.7654:3210.9876:5432.1098:7654.3210: 0..31
51 * :||||.||||:||||.||||:||||.||||:||||.||||:
52 * :8421.8421:8421.8421:8421.8421:8421.8421: hex digit
53 * : . : . : . : x . : HDSPM_AudioInterruptEnable \_ setting both bits
54 * : . : . : . : . x: HDSPM_Start / enables audio IO
55 * : . : . : . : x. : HDSPM_ClockModeMaster - 1: Master, 0: Slave
56 * : . : . : . : .210 : HDSPM_LatencyMask - 3 Bit value for latency
57 * : . : . : . : . : 0:64, 1:128, 2:256, 3:512,
58 * : . : . : . : . : 4:1024, 5:2048, 6:4096, 7:8192
59 * :x . : . : . x:xx . : HDSPM_FrequencyMask
60 * : . : . : . :10 . : HDSPM_Frequency1|HDSPM_Frequency0: 1=32K,2=44.1K,3=48K,0=??
61 * : . : . : . x: . : <MADI> HDSPM_DoubleSpeed
62 * :x . : . : . : . : <MADI> HDSPM_QuadSpeed
63 * : . 3 : . 10: 2 . : . : HDSPM_SyncRefMask :
64 * : . : . x: . : . : HDSPM_SyncRef0
65 * : . : . x : . : . : HDSPM_SyncRef1
66 * : . : . : x . : . : <AES32> HDSPM_SyncRef2
67 * : . x : . : . : . : <AES32> HDSPM_SyncRef3
68 * : . : . 10: . : . : <MADI> sync ref: 0:WC, 1:Madi, 2:TCO, 3:SyncIn
69 * : . 3 : . 10: 2 . : . : <AES32> 0:WC, 1:AES1 ... 8:AES8, 9: TCO, 10:SyncIn?
70 * : . x : . : . : . : <MADIe> HDSPe_FLOAT_FORMAT
71 * : . : . : x . : . : <MADI> HDSPM_InputSelect0 : 0=optical,1=coax
72 * : . : . :x . : . : <MADI> HDSPM_InputSelect1
73 * : . : .x : . : . : <MADI> HDSPM_clr_tms
74 * : . : . : . x : . : <MADI> HDSPM_TX_64ch
75 * : . : . : . x : . : <AES32> HDSPM_Emphasis
76 * : . : . : .x : . : <MADI> HDSPM_AutoInp
77 * : . : . x : . : . : <MADI> HDSPM_SMUX
78 * : . : .x : . : . : <MADI> HDSPM_clr_tms
79 * : . : x. : . : . : <MADI> HDSPM_taxi_reset
80 * : . x: . : . : . : <MADI> HDSPM_LineOut
81 * : . x: . : . : . : <AES32> ??????????????????
82 * : . : x. : . : . : <AES32> HDSPM_WCK48
83 * : . : . : .x : . : <AES32> HDSPM_Dolby
84 * : . : x . : . : . : HDSPM_Midi0InterruptEnable
85 * : . :x . : . : . : HDSPM_Midi1InterruptEnable
86 * : . : x . : . : . : HDSPM_Midi2InterruptEnable
87 * : . x : . : . : . : <MADI> HDSPM_Midi3InterruptEnable
88 * : . x : . : . : . : <AES32> HDSPM_DS_DoubleWire
89 * : .x : . : . : . : <AES32> HDSPM_QS_DoubleWire
90 * : x. : . : . : . : <AES32> HDSPM_QS_QuadWire
91 * : . : . : . x : . : <AES32> HDSPM_Professional
92 * : x . : . : . : . : HDSPM_wclk_sel
93 * : . : . : . : . :
94 * :7654.3210:7654.3210:7654.3210:7654.3210: bit number per byte
95 * :||||.||||:||||.||||:||||.||||:||||.||||:
96 * :3322.2222:2222.1111:1111.1100:0000.0000: bit number
97 * :1098.7654:3210.9876:5432.1098:7654.3210: 0..31
98 * :||||.||||:||||.||||:||||.||||:||||.||||:
99 * :8421.8421:8421.8421:8421.8421:8421.8421:hex digit
100 *
101 *
102 *
103 * AIO / RayDAT only
104 *
105 * ------------ HDSPM_WR_SETTINGS ----------
106 * :3322.2222:2222.1111:1111.1100:0000.0000: bit number per byte
107 * :1098.7654:3210.9876:5432.1098:7654.3210:
108 * :||||.||||:||||.||||:||||.||||:||||.||||: bit number
109 * :7654.3210:7654.3210:7654.3210:7654.3210: 0..31
110 * :||||.||||:||||.||||:||||.||||:||||.||||:
111 * :8421.8421:8421.8421:8421.8421:8421.8421: hex digit
112 * : . : . : . : . x: HDSPM_c0Master 1: Master, 0: Slave
113 * : . : . : . : . x : HDSPM_c0_SyncRef0
114 * : . : . : . : . x : HDSPM_c0_SyncRef1
115 * : . : . : . : .x : HDSPM_c0_SyncRef2
116 * : . : . : . : x. : HDSPM_c0_SyncRef3
117 * : . : . : . : 3.210 : HDSPM_c0_SyncRefMask:
118 * : . : . : . : . : RayDat: 0:WC, 1:AES, 2:SPDIF, 3..6: ADAT1..4,
119 * : . : . : . : . : 9:TCO, 10:SyncIn
120 * : . : . : . : . : AIO: 0:WC, 1:AES, 2: SPDIF, 3: ATAT,
121 * : . : . : . : . : 9:TCO, 10:SyncIn
122 * : . : . : . : . :
123 * : . : . : . : . :
124 * :3322.2222:2222.1111:1111.1100:0000.0000: bit number per byte
125 * :1098.7654:3210.9876:5432.1098:7654.3210:
126 * :||||.||||:||||.||||:||||.||||:||||.||||: bit number
127 * :7654.3210:7654.3210:7654.3210:7654.3210: 0..31
128 * :||||.||||:||||.||||:||||.||||:||||.||||:
129 * :8421.8421:8421.8421:8421.8421:8421.8421: hex digit
130 *
131 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200132#include <linux/init.h>
133#include <linux/delay.h>
134#include <linux/interrupt.h>
Paul Gortmaker65a77212011-07-15 13:13:37 -0400135#include <linux/module.h>
Takashi Iwai763f3562005-06-03 11:25:34 +0200136#include <linux/slab.h>
137#include <linux/pci.h>
Takashi Iwai3f7440a2009-06-05 17:40:04 +0200138#include <linux/math64.h>
Takashi Iwai6cbbfe12015-01-28 16:49:33 +0100139#include <linux/io.h>
Takashi Iwai44bb2652018-04-24 08:03:14 +0200140#include <linux/nospec.h>
Takashi Iwai763f3562005-06-03 11:25:34 +0200141
142#include <sound/core.h>
143#include <sound/control.h>
144#include <sound/pcm.h>
Adrian Knoth0dca1792011-01-26 19:32:14 +0100145#include <sound/pcm_params.h>
Takashi Iwai763f3562005-06-03 11:25:34 +0200146#include <sound/info.h>
147#include <sound/asoundef.h>
148#include <sound/rawmidi.h>
149#include <sound/hwdep.h>
150#include <sound/initval.h>
151
152#include <sound/hdspm.h>
153
154static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
155static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
Rusty Russella67ff6a2011-12-15 13:49:36 +1030156static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
Takashi Iwai763f3562005-06-03 11:25:34 +0200157
Takashi Iwai763f3562005-06-03 11:25:34 +0200158module_param_array(index, int, NULL, 0444);
159MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");
160
161module_param_array(id, charp, NULL, 0444);
162MODULE_PARM_DESC(id, "ID string for RME HDSPM interface.");
163
164module_param_array(enable, bool, NULL, 0444);
165MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");
166
Takashi Iwai763f3562005-06-03 11:25:34 +0200167
168MODULE_AUTHOR
Adrian Knoth0dca1792011-01-26 19:32:14 +0100169(
170 "Winfried Ritsch <ritsch_AT_iem.at>, "
171 "Paul Davis <paul@linuxaudiosystems.com>, "
172 "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, "
173 "Remy Bruno <remy.bruno@trinnov.com>, "
174 "Florian Faber <faberman@linuxproaudio.org>, "
175 "Adrian Knoth <adi@drcomp.erfurt.thur.de>"
176);
Takashi Iwai763f3562005-06-03 11:25:34 +0200177MODULE_DESCRIPTION("RME HDSPM");
178MODULE_LICENSE("GPL");
179MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
180
Adrian Knoth0dca1792011-01-26 19:32:14 +0100181/* --- Write registers. ---
Takashi Iwai763f3562005-06-03 11:25:34 +0200182 These are defined as byte-offsets from the iobase value. */
183
Adrian Knoth0dca1792011-01-26 19:32:14 +0100184#define HDSPM_WR_SETTINGS 0
185#define HDSPM_outputBufferAddress 32
186#define HDSPM_inputBufferAddress 36
Takashi Iwai763f3562005-06-03 11:25:34 +0200187#define HDSPM_controlRegister 64
188#define HDSPM_interruptConfirmation 96
189#define HDSPM_control2Reg 256 /* not in specs ???????? */
Martin Dausel69358fc2013-07-05 11:28:23 +0200190#define HDSPM_freqReg 256 /* for setting arbitrary clock values (DDS feature) */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100191#define HDSPM_midiDataOut0 352 /* just believe in old code */
192#define HDSPM_midiDataOut1 356
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100193#define HDSPM_eeprom_wr 384 /* for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200194
195/* DMA enable for 64 channels, only Bit 0 is relevant */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100196#define HDSPM_outputEnableBase 512 /* 512-767 input DMA */
Takashi Iwai763f3562005-06-03 11:25:34 +0200197#define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */
198
Adrian Knoth0dca1792011-01-26 19:32:14 +0100199/* 16 page addresses for each of the 64 channels DMA buffer in and out
Takashi Iwai763f3562005-06-03 11:25:34 +0200200 (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */
201#define HDSPM_pageAddressBufferOut 8192
202#define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4)
203
204#define HDSPM_MADI_mixerBase 32768 /* 32768-65535 for 2x64x64 Fader */
205
206#define HDSPM_MATRIX_MIXER_SIZE 8192 /* = 2*64*64 * 4 Byte => 32kB */
207
208/* --- Read registers. ---
209 These are defined as byte-offsets from the iobase value */
210#define HDSPM_statusRegister 0
Remy Bruno3cee5a62006-10-16 12:46:32 +0200211/*#define HDSPM_statusRegister2 96 */
212/* after RME Windows driver sources, status2 is 4-byte word # 48 = word at
213 * offset 192, for AES32 *and* MADI
214 * => need to check that offset 192 is working on MADI */
215#define HDSPM_statusRegister2 192
216#define HDSPM_timecodeRegister 128
Takashi Iwai763f3562005-06-03 11:25:34 +0200217
Adrian Knoth0dca1792011-01-26 19:32:14 +0100218/* AIO, RayDAT */
219#define HDSPM_RD_STATUS_0 0
220#define HDSPM_RD_STATUS_1 64
221#define HDSPM_RD_STATUS_2 128
222#define HDSPM_RD_STATUS_3 192
223
224#define HDSPM_RD_TCO 256
225#define HDSPM_RD_PLL_FREQ 512
226#define HDSPM_WR_TCO 128
227
228#define HDSPM_TCO1_TCO_lock 0x00000001
229#define HDSPM_TCO1_WCK_Input_Range_LSB 0x00000002
230#define HDSPM_TCO1_WCK_Input_Range_MSB 0x00000004
231#define HDSPM_TCO1_LTC_Input_valid 0x00000008
232#define HDSPM_TCO1_WCK_Input_valid 0x00000010
233#define HDSPM_TCO1_Video_Input_Format_NTSC 0x00000020
234#define HDSPM_TCO1_Video_Input_Format_PAL 0x00000040
235
236#define HDSPM_TCO1_set_TC 0x00000100
237#define HDSPM_TCO1_set_drop_frame_flag 0x00000200
238#define HDSPM_TCO1_LTC_Format_LSB 0x00000400
239#define HDSPM_TCO1_LTC_Format_MSB 0x00000800
240
241#define HDSPM_TCO2_TC_run 0x00010000
242#define HDSPM_TCO2_WCK_IO_ratio_LSB 0x00020000
243#define HDSPM_TCO2_WCK_IO_ratio_MSB 0x00040000
244#define HDSPM_TCO2_set_num_drop_frames_LSB 0x00080000
245#define HDSPM_TCO2_set_num_drop_frames_MSB 0x00100000
246#define HDSPM_TCO2_set_jam_sync 0x00200000
247#define HDSPM_TCO2_set_flywheel 0x00400000
248
249#define HDSPM_TCO2_set_01_4 0x01000000
250#define HDSPM_TCO2_set_pull_down 0x02000000
251#define HDSPM_TCO2_set_pull_up 0x04000000
252#define HDSPM_TCO2_set_freq 0x08000000
253#define HDSPM_TCO2_set_term_75R 0x10000000
254#define HDSPM_TCO2_set_input_LSB 0x20000000
255#define HDSPM_TCO2_set_input_MSB 0x40000000
256#define HDSPM_TCO2_set_freq_from_app 0x80000000
257
258
259#define HDSPM_midiDataOut0 352
260#define HDSPM_midiDataOut1 356
261#define HDSPM_midiDataOut2 368
262
Takashi Iwai763f3562005-06-03 11:25:34 +0200263#define HDSPM_midiDataIn0 360
264#define HDSPM_midiDataIn1 364
Adrian Knoth0dca1792011-01-26 19:32:14 +0100265#define HDSPM_midiDataIn2 372
266#define HDSPM_midiDataIn3 376
Takashi Iwai763f3562005-06-03 11:25:34 +0200267
268/* status is data bytes in MIDI-FIFO (0-128) */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100269#define HDSPM_midiStatusOut0 384
270#define HDSPM_midiStatusOut1 388
271#define HDSPM_midiStatusOut2 400
272
273#define HDSPM_midiStatusIn0 392
274#define HDSPM_midiStatusIn1 396
275#define HDSPM_midiStatusIn2 404
276#define HDSPM_midiStatusIn3 408
Takashi Iwai763f3562005-06-03 11:25:34 +0200277
278
279/* the meters are regular i/o-mapped registers, but offset
280 considerably from the rest. the peak registers are reset
Adrian Knoth0dca1792011-01-26 19:32:14 +0100281 when read; the least-significant 4 bits are full-scale counters;
Takashi Iwai763f3562005-06-03 11:25:34 +0200282 the actual peak value is in the most-significant 24 bits.
283*/
Adrian Knoth0dca1792011-01-26 19:32:14 +0100284
285#define HDSPM_MADI_INPUT_PEAK 4096
286#define HDSPM_MADI_PLAYBACK_PEAK 4352
287#define HDSPM_MADI_OUTPUT_PEAK 4608
288
289#define HDSPM_MADI_INPUT_RMS_L 6144
290#define HDSPM_MADI_PLAYBACK_RMS_L 6400
291#define HDSPM_MADI_OUTPUT_RMS_L 6656
292
293#define HDSPM_MADI_INPUT_RMS_H 7168
294#define HDSPM_MADI_PLAYBACK_RMS_H 7424
295#define HDSPM_MADI_OUTPUT_RMS_H 7680
Takashi Iwai763f3562005-06-03 11:25:34 +0200296
297/* --- Control Register bits --------- */
298#define HDSPM_Start (1<<0) /* start engine */
299
300#define HDSPM_Latency0 (1<<1) /* buffer size = 2^n */
301#define HDSPM_Latency1 (1<<2) /* where n is defined */
302#define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */
303
Adrian Knoth0dca1792011-01-26 19:32:14 +0100304#define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Autosync */
305#define HDSPM_c0Master 0x1 /* Master clock bit in settings
306 register [RayDAT, AIO] */
Takashi Iwai763f3562005-06-03 11:25:34 +0200307
308#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */
309
310#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */
311#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */
312#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200313#define HDSPM_QuadSpeed (1<<31) /* quad speed bit */
Takashi Iwai763f3562005-06-03 11:25:34 +0200314
Remy Bruno3cee5a62006-10-16 12:46:32 +0200315#define HDSPM_Professional (1<<9) /* Professional */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200316#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200317 56channelMODE=0 */ /* MADI ONLY*/
318#define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200319
Adrian Knoth0dca1792011-01-26 19:32:14 +0100320#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200321 0=off, 1=on */ /* MADI ONLY */
322#define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200323
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200324#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax
325 * -- MADI ONLY
326 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200327#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
328
Remy Bruno3cee5a62006-10-16 12:46:32 +0200329#define HDSPM_SyncRef2 (1<<13)
330#define HDSPM_SyncRef3 (1<<25)
Takashi Iwai763f3562005-06-03 11:25:34 +0200331
Remy Bruno3cee5a62006-10-16 12:46:32 +0200332#define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100333#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use
Takashi Iwai763f3562005-06-03 11:25:34 +0200334 AES additional bits in
335 lower 5 Audiodatabits ??? */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200336#define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */
337#define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200338
Adrian Knoth0dca1792011-01-26 19:32:14 +0100339#define HDSPM_Midi0InterruptEnable 0x0400000
340#define HDSPM_Midi1InterruptEnable 0x0800000
341#define HDSPM_Midi2InterruptEnable 0x0200000
342#define HDSPM_Midi3InterruptEnable 0x4000000
Takashi Iwai763f3562005-06-03 11:25:34 +0200343
344#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100345#define HDSPe_FLOAT_FORMAT 0x2000000
Takashi Iwai763f3562005-06-03 11:25:34 +0200346
Remy Bruno3cee5a62006-10-16 12:46:32 +0200347#define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */
348#define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */
349#define HDSPM_QS_QuadWire (1<<28) /* AES32 ONLY */
350
351#define HDSPM_wclk_sel (1<<30)
Takashi Iwai763f3562005-06-03 11:25:34 +0200352
Adrian Knoth384f7782013-07-05 11:27:53 +0200353/* additional control register bits for AIO*/
354#define HDSPM_c0_Wck48 0x20 /* also RayDAT */
355#define HDSPM_c0_Input0 0x1000
356#define HDSPM_c0_Input1 0x2000
357#define HDSPM_c0_Spdif_Opt 0x4000
358#define HDSPM_c0_Pro 0x8000
359#define HDSPM_c0_clr_tms 0x10000
360#define HDSPM_c0_AEB1 0x20000
361#define HDSPM_c0_AEB2 0x40000
362#define HDSPM_c0_LineOut 0x80000
363#define HDSPM_c0_AD_GAIN0 0x100000
364#define HDSPM_c0_AD_GAIN1 0x200000
365#define HDSPM_c0_DA_GAIN0 0x400000
366#define HDSPM_c0_DA_GAIN1 0x800000
367#define HDSPM_c0_PH_GAIN0 0x1000000
368#define HDSPM_c0_PH_GAIN1 0x2000000
369#define HDSPM_c0_Sym6db 0x4000000
370
371
Takashi Iwai763f3562005-06-03 11:25:34 +0200372/* --- bit helper defines */
373#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200374#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|\
375 HDSPM_DoubleSpeed|HDSPM_QuadSpeed)
Takashi Iwai763f3562005-06-03 11:25:34 +0200376#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1)
377#define HDSPM_InputOptical 0
378#define HDSPM_InputCoaxial (HDSPM_InputSelect0)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200379#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\
380 HDSPM_SyncRef2|HDSPM_SyncRef3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200381
Adrian Knoth0dca1792011-01-26 19:32:14 +0100382#define HDSPM_c0_SyncRef0 0x2
383#define HDSPM_c0_SyncRef1 0x4
384#define HDSPM_c0_SyncRef2 0x8
385#define HDSPM_c0_SyncRef3 0x10
386#define HDSPM_c0_SyncRefMask (HDSPM_c0_SyncRef0 | HDSPM_c0_SyncRef1 |\
387 HDSPM_c0_SyncRef2 | HDSPM_c0_SyncRef3)
388
389#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */
390#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */
391#define HDSPM_SYNC_FROM_TCO 2
392#define HDSPM_SYNC_FROM_SYNC_IN 3
Takashi Iwai763f3562005-06-03 11:25:34 +0200393
394#define HDSPM_Frequency32KHz HDSPM_Frequency0
395#define HDSPM_Frequency44_1KHz HDSPM_Frequency1
396#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0)
397#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0)
398#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200399#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|\
400 HDSPM_Frequency0)
Remy Bruno3cee5a62006-10-16 12:46:32 +0200401#define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0)
402#define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200403#define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\
404 HDSPM_Frequency0)
Takashi Iwai763f3562005-06-03 11:25:34 +0200405
Takashi Iwai763f3562005-06-03 11:25:34 +0200406
407/* Synccheck Status */
408#define HDSPM_SYNC_CHECK_NO_LOCK 0
409#define HDSPM_SYNC_CHECK_LOCK 1
410#define HDSPM_SYNC_CHECK_SYNC 2
411
412/* AutoSync References - used by "autosync_ref" control switch */
413#define HDSPM_AUTOSYNC_FROM_WORD 0
414#define HDSPM_AUTOSYNC_FROM_MADI 1
Adrian Knoth0dca1792011-01-26 19:32:14 +0100415#define HDSPM_AUTOSYNC_FROM_TCO 2
416#define HDSPM_AUTOSYNC_FROM_SYNC_IN 3
417#define HDSPM_AUTOSYNC_FROM_NONE 4
Takashi Iwai763f3562005-06-03 11:25:34 +0200418
419/* Possible sources of MADI input */
420#define HDSPM_OPTICAL 0 /* optical */
421#define HDSPM_COAXIAL 1 /* BNC */
422
423#define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask)
Adrian Knoth0dca1792011-01-26 19:32:14 +0100424#define hdspm_decode_latency(x) ((((x) & HDSPM_LatencyMask)>>1))
Takashi Iwai763f3562005-06-03 11:25:34 +0200425
426#define hdspm_encode_in(x) (((x)&0x3)<<14)
427#define hdspm_decode_in(x) (((x)>>14)&0x3)
428
429/* --- control2 register bits --- */
430#define HDSPM_TMS (1<<0)
431#define HDSPM_TCK (1<<1)
432#define HDSPM_TDI (1<<2)
433#define HDSPM_JTAG (1<<3)
434#define HDSPM_PWDN (1<<4)
435#define HDSPM_PROGRAM (1<<5)
436#define HDSPM_CONFIG_MODE_0 (1<<6)
437#define HDSPM_CONFIG_MODE_1 (1<<7)
438/*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/
439#define HDSPM_BIGENDIAN_MODE (1<<9)
440#define HDSPM_RD_MULTIPLE (1<<10)
441
Remy Bruno3cee5a62006-10-16 12:46:32 +0200442/* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200443 that do not conflict with specific bits for AES32 seem to be valid also
444 for the AES32
445 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200446#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200447#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn MODE=0 */
448#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1
449 * (like inp0)
450 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100451
Takashi Iwai763f3562005-06-03 11:25:34 +0200452#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100453#define HDSPM_madiSync (1<<18) /* MADI is in sync */
454
Adrian Knothb0bf5502013-07-05 11:28:05 +0200455#define HDSPM_tcoLockMadi 0x00000020 /* Optional TCO locked status for HDSPe MADI*/
456#define HDSPM_tcoSync 0x10000000 /* Optional TCO sync status for HDSPe MADI and AES32!*/
Adrian Knoth0dca1792011-01-26 19:32:14 +0100457
Adrian Knothb0bf5502013-07-05 11:28:05 +0200458#define HDSPM_syncInLock 0x00010000 /* Sync In lock status for HDSPe MADI! */
459#define HDSPM_syncInSync 0x00020000 /* Sync In sync status for HDSPe MADI! */
Takashi Iwai763f3562005-06-03 11:25:34 +0200460
461#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100462 /* since 64byte accurate, last 6 bits are not used */
Takashi Iwai763f3562005-06-03 11:25:34 +0200463
Adrian Knoth0dca1792011-01-26 19:32:14 +0100464
465
Takashi Iwai763f3562005-06-03 11:25:34 +0200466#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */
467
468#define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */
469#define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */
470#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */
471#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */
472
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200473#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with
474 * Interrupt
475 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100476#define HDSPM_tco_detect 0x08000000
Adrian Knothb0bf5502013-07-05 11:28:05 +0200477#define HDSPM_tcoLockAes 0x20000000 /* Optional TCO locked status for HDSPe AES */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100478
479#define HDSPM_s2_tco_detect 0x00000040
480#define HDSPM_s2_AEBO_D 0x00000080
481#define HDSPM_s2_AEBI_D 0x00000100
482
483
484#define HDSPM_midi0IRQPending 0x40000000
485#define HDSPM_midi1IRQPending 0x80000000
486#define HDSPM_midi2IRQPending 0x20000000
487#define HDSPM_midi2IRQPendingAES 0x00000020
488#define HDSPM_midi3IRQPending 0x00200000
Takashi Iwai763f3562005-06-03 11:25:34 +0200489
490/* --- status bit helpers */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200491#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\
492 HDSPM_madiFreq2|HDSPM_madiFreq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200493#define HDSPM_madiFreq32 (HDSPM_madiFreq0)
494#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1)
495#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1)
496#define HDSPM_madiFreq64 (HDSPM_madiFreq2)
497#define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2)
498#define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2)
499#define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2)
500#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
501#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0)
502
Remy Bruno3cee5a62006-10-16 12:46:32 +0200503/* Status2 Register bits */ /* MADI ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200504
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300505#define HDSPM_version0 (1<<0) /* not really defined but I guess */
Takashi Iwai763f3562005-06-03 11:25:34 +0200506#define HDSPM_version1 (1<<1) /* in former cards it was ??? */
507#define HDSPM_version2 (1<<2)
508
509#define HDSPM_wcLock (1<<3) /* Wordclock is detected and locked */
510#define HDSPM_wcSync (1<<4) /* Wordclock is in sync with systemclock */
511
512#define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */
513#define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */
Adrian Knotha8cd7142013-05-31 12:57:09 +0200514#define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, 111=128 */
515#define HDSPM_wc_freq3 0x800 /* 1000=176.4, 1001=192 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200516
Adrian Knoth0dca1792011-01-26 19:32:14 +0100517#define HDSPM_SyncRef0 0x10000 /* Sync Reference */
518#define HDSPM_SyncRef1 0x20000
519
520#define HDSPM_SelSyncRef0 (1<<8) /* AutoSync Source */
Takashi Iwai763f3562005-06-03 11:25:34 +0200521#define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */
522#define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */
523
524#define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync)
525
Adrian Knotha8cd7142013-05-31 12:57:09 +0200526#define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2|\
527 HDSPM_wc_freq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200528#define HDSPM_wcFreq32 (HDSPM_wc_freq0)
529#define HDSPM_wcFreq44_1 (HDSPM_wc_freq1)
530#define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1)
531#define HDSPM_wcFreq64 (HDSPM_wc_freq2)
532#define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2)
533#define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2)
Adrian Knotha8cd7142013-05-31 12:57:09 +0200534#define HDSPM_wcFreq128 (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2)
535#define HDSPM_wcFreq176_4 (HDSPM_wc_freq3)
536#define HDSPM_wcFreq192 (HDSPM_wc_freq0|HDSPM_wc_freq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200537
Adrian Knoth0dca1792011-01-26 19:32:14 +0100538#define HDSPM_status1_F_0 0x0400000
539#define HDSPM_status1_F_1 0x0800000
540#define HDSPM_status1_F_2 0x1000000
541#define HDSPM_status1_F_3 0x2000000
542#define HDSPM_status1_freqMask (HDSPM_status1_F_0|HDSPM_status1_F_1|HDSPM_status1_F_2|HDSPM_status1_F_3)
543
Takashi Iwai763f3562005-06-03 11:25:34 +0200544
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200545#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
546 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200547#define HDSPM_SelSyncRef_WORD 0
548#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0)
Adrian Knoth0dca1792011-01-26 19:32:14 +0100549#define HDSPM_SelSyncRef_TCO (HDSPM_SelSyncRef1)
550#define HDSPM_SelSyncRef_SyncIn (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200551#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
552 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200553
Remy Bruno3cee5a62006-10-16 12:46:32 +0200554/*
555 For AES32, bits for status, status2 and timecode are different
556*/
557/* status */
558#define HDSPM_AES32_wcLock 0x0200000
Andre Schramm56bde0f2013-01-09 14:40:18 +0100559#define HDSPM_AES32_wcSync 0x0100000
Remy Bruno3cee5a62006-10-16 12:46:32 +0200560#define HDSPM_AES32_wcFreq_bit 22
Adrian Knoth0dca1792011-01-26 19:32:14 +0100561/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function
Remy Bruno3cee5a62006-10-16 12:46:32 +0200562 HDSPM_bit2freq */
563#define HDSPM_AES32_syncref_bit 16
564/* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */
565
566#define HDSPM_AES32_AUTOSYNC_FROM_WORD 0
567#define HDSPM_AES32_AUTOSYNC_FROM_AES1 1
568#define HDSPM_AES32_AUTOSYNC_FROM_AES2 2
569#define HDSPM_AES32_AUTOSYNC_FROM_AES3 3
570#define HDSPM_AES32_AUTOSYNC_FROM_AES4 4
571#define HDSPM_AES32_AUTOSYNC_FROM_AES5 5
572#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6
573#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7
574#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8
Adrian Knothb0bf5502013-07-05 11:28:05 +0200575#define HDSPM_AES32_AUTOSYNC_FROM_TCO 9
576#define HDSPM_AES32_AUTOSYNC_FROM_SYNC_IN 10
577#define HDSPM_AES32_AUTOSYNC_FROM_NONE 11
Remy Bruno3cee5a62006-10-16 12:46:32 +0200578
579/* status2 */
580/* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */
581#define HDSPM_LockAES 0x80
582#define HDSPM_LockAES1 0x80
583#define HDSPM_LockAES2 0x40
584#define HDSPM_LockAES3 0x20
585#define HDSPM_LockAES4 0x10
586#define HDSPM_LockAES5 0x8
587#define HDSPM_LockAES6 0x4
588#define HDSPM_LockAES7 0x2
589#define HDSPM_LockAES8 0x1
590/*
591 Timecode
592 After windows driver sources, bits 4*i to 4*i+3 give the input frequency on
593 AES i+1
594 bits 3210
595 0001 32kHz
596 0010 44.1kHz
597 0011 48kHz
598 0100 64kHz
599 0101 88.2kHz
600 0110 96kHz
601 0111 128kHz
602 1000 176.4kHz
603 1001 192kHz
604 NB: Timecode register doesn't seem to work on AES32 card revision 230
605*/
606
Takashi Iwai763f3562005-06-03 11:25:34 +0200607/* Mixer Values */
608#define UNITY_GAIN 32768 /* = 65536/2 */
609#define MINUS_INFINITY_GAIN 0
610
Takashi Iwai763f3562005-06-03 11:25:34 +0200611/* Number of channels for different Speed Modes */
612#define MADI_SS_CHANNELS 64
613#define MADI_DS_CHANNELS 32
614#define MADI_QS_CHANNELS 16
615
Adrian Knoth0dca1792011-01-26 19:32:14 +0100616#define RAYDAT_SS_CHANNELS 36
617#define RAYDAT_DS_CHANNELS 20
618#define RAYDAT_QS_CHANNELS 12
619
620#define AIO_IN_SS_CHANNELS 14
621#define AIO_IN_DS_CHANNELS 10
622#define AIO_IN_QS_CHANNELS 8
623#define AIO_OUT_SS_CHANNELS 16
624#define AIO_OUT_DS_CHANNELS 12
625#define AIO_OUT_QS_CHANNELS 10
626
Adrian Knothd2d10a22011-02-28 15:14:47 +0100627#define AES32_CHANNELS 16
628
Takashi Iwai763f3562005-06-03 11:25:34 +0200629/* the size of a substream (1 mono data stream) */
630#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024)
631#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
632
633/* the size of the area we need to allocate for DMA transfers. the
634 size is the same regardless of the number of channels, and
Adrian Knoth0dca1792011-01-26 19:32:14 +0100635 also the latency to use.
Takashi Iwai763f3562005-06-03 11:25:34 +0200636 for one direction !!!
637*/
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100638#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
Takashi Iwai763f3562005-06-03 11:25:34 +0200639#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
640
Adrian Knoth0dca1792011-01-26 19:32:14 +0100641#define HDSPM_RAYDAT_REV 211
642#define HDSPM_AIO_REV 212
643#define HDSPM_MADIFACE_REV 213
Remy Bruno3cee5a62006-10-16 12:46:32 +0200644
Remy Bruno65345992007-08-31 12:21:08 +0200645/* speed factor modes */
646#define HDSPM_SPEED_SINGLE 0
647#define HDSPM_SPEED_DOUBLE 1
648#define HDSPM_SPEED_QUAD 2
Adrian Knoth0dca1792011-01-26 19:32:14 +0100649
Remy Bruno65345992007-08-31 12:21:08 +0200650/* names for speed modes */
651static char *hdspm_speed_names[] = { "single", "double", "quad" };
652
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200653static const char *const texts_autosync_aes_tco[] = { "Word Clock",
Adrian Knoth0dca1792011-01-26 19:32:14 +0100654 "AES1", "AES2", "AES3", "AES4",
655 "AES5", "AES6", "AES7", "AES8",
Adrian Knothdb2d1a92013-07-05 11:28:08 +0200656 "TCO", "Sync In"
657};
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200658static const char *const texts_autosync_aes[] = { "Word Clock",
Adrian Knoth0dca1792011-01-26 19:32:14 +0100659 "AES1", "AES2", "AES3", "AES4",
Adrian Knothdb2d1a92013-07-05 11:28:08 +0200660 "AES5", "AES6", "AES7", "AES8",
661 "Sync In"
662};
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200663static const char *const texts_autosync_madi_tco[] = { "Word Clock",
Adrian Knoth0dca1792011-01-26 19:32:14 +0100664 "MADI", "TCO", "Sync In" };
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200665static const char *const texts_autosync_madi[] = { "Word Clock",
Adrian Knoth0dca1792011-01-26 19:32:14 +0100666 "MADI", "Sync In" };
667
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200668static const char *const texts_autosync_raydat_tco[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100669 "Word Clock",
670 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
671 "AES", "SPDIF", "TCO", "Sync In"
672};
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200673static const char *const texts_autosync_raydat[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100674 "Word Clock",
675 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
676 "AES", "SPDIF", "Sync In"
677};
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200678static const char *const texts_autosync_aio_tco[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100679 "Word Clock",
680 "ADAT", "AES", "SPDIF", "TCO", "Sync In"
681};
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200682static const char *const texts_autosync_aio[] = { "Word Clock",
Adrian Knoth0dca1792011-01-26 19:32:14 +0100683 "ADAT", "AES", "SPDIF", "Sync In" };
684
Adrian Knoth38816542013-07-05 11:28:20 +0200685static const char *const texts_freq[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100686 "No Lock",
687 "32 kHz",
688 "44.1 kHz",
689 "48 kHz",
690 "64 kHz",
691 "88.2 kHz",
692 "96 kHz",
693 "128 kHz",
694 "176.4 kHz",
695 "192 kHz"
696};
697
Adrian Knoth0dca1792011-01-26 19:32:14 +0100698static char *texts_ports_madi[] = {
699 "MADI.1", "MADI.2", "MADI.3", "MADI.4", "MADI.5", "MADI.6",
700 "MADI.7", "MADI.8", "MADI.9", "MADI.10", "MADI.11", "MADI.12",
701 "MADI.13", "MADI.14", "MADI.15", "MADI.16", "MADI.17", "MADI.18",
702 "MADI.19", "MADI.20", "MADI.21", "MADI.22", "MADI.23", "MADI.24",
703 "MADI.25", "MADI.26", "MADI.27", "MADI.28", "MADI.29", "MADI.30",
704 "MADI.31", "MADI.32", "MADI.33", "MADI.34", "MADI.35", "MADI.36",
705 "MADI.37", "MADI.38", "MADI.39", "MADI.40", "MADI.41", "MADI.42",
706 "MADI.43", "MADI.44", "MADI.45", "MADI.46", "MADI.47", "MADI.48",
707 "MADI.49", "MADI.50", "MADI.51", "MADI.52", "MADI.53", "MADI.54",
708 "MADI.55", "MADI.56", "MADI.57", "MADI.58", "MADI.59", "MADI.60",
709 "MADI.61", "MADI.62", "MADI.63", "MADI.64",
710};
711
712
713static char *texts_ports_raydat_ss[] = {
714 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT1.5", "ADAT1.6",
715 "ADAT1.7", "ADAT1.8", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
716 "ADAT2.5", "ADAT2.6", "ADAT2.7", "ADAT2.8", "ADAT3.1", "ADAT3.2",
717 "ADAT3.3", "ADAT3.4", "ADAT3.5", "ADAT3.6", "ADAT3.7", "ADAT3.8",
718 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4", "ADAT4.5", "ADAT4.6",
719 "ADAT4.7", "ADAT4.8",
720 "AES.L", "AES.R",
721 "SPDIF.L", "SPDIF.R"
722};
723
724static char *texts_ports_raydat_ds[] = {
725 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4",
726 "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
727 "ADAT3.1", "ADAT3.2", "ADAT3.3", "ADAT3.4",
728 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4",
729 "AES.L", "AES.R",
730 "SPDIF.L", "SPDIF.R"
731};
732
733static char *texts_ports_raydat_qs[] = {
734 "ADAT1.1", "ADAT1.2",
735 "ADAT2.1", "ADAT2.2",
736 "ADAT3.1", "ADAT3.2",
737 "ADAT4.1", "ADAT4.2",
738 "AES.L", "AES.R",
739 "SPDIF.L", "SPDIF.R"
740};
741
742
743static char *texts_ports_aio_in_ss[] = {
744 "Analogue.L", "Analogue.R",
745 "AES.L", "AES.R",
746 "SPDIF.L", "SPDIF.R",
747 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200748 "ADAT.7", "ADAT.8",
749 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100750};
751
752static char *texts_ports_aio_out_ss[] = {
753 "Analogue.L", "Analogue.R",
754 "AES.L", "AES.R",
755 "SPDIF.L", "SPDIF.R",
756 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
757 "ADAT.7", "ADAT.8",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200758 "Phone.L", "Phone.R",
759 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100760};
761
762static char *texts_ports_aio_in_ds[] = {
763 "Analogue.L", "Analogue.R",
764 "AES.L", "AES.R",
765 "SPDIF.L", "SPDIF.R",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200766 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
767 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100768};
769
770static char *texts_ports_aio_out_ds[] = {
771 "Analogue.L", "Analogue.R",
772 "AES.L", "AES.R",
773 "SPDIF.L", "SPDIF.R",
774 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200775 "Phone.L", "Phone.R",
776 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100777};
778
779static char *texts_ports_aio_in_qs[] = {
780 "Analogue.L", "Analogue.R",
781 "AES.L", "AES.R",
782 "SPDIF.L", "SPDIF.R",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200783 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
784 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100785};
786
787static char *texts_ports_aio_out_qs[] = {
788 "Analogue.L", "Analogue.R",
789 "AES.L", "AES.R",
790 "SPDIF.L", "SPDIF.R",
791 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200792 "Phone.L", "Phone.R",
793 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100794};
795
Adrian Knoth432d2502011-02-23 11:43:08 +0100796static char *texts_ports_aes32[] = {
797 "AES.1", "AES.2", "AES.3", "AES.4", "AES.5", "AES.6", "AES.7",
798 "AES.8", "AES.9.", "AES.10", "AES.11", "AES.12", "AES.13", "AES.14",
799 "AES.15", "AES.16"
800};
801
Adrian Knoth55a57602011-01-27 11:23:15 +0100802/* These tables map the ALSA channels 1..N to the channels that we
803 need to use in order to find the relevant channel buffer. RME
804 refers to this kind of mapping as between "the ADAT channel and
805 the DMA channel." We index it using the logical audio channel,
806 and the value is the DMA channel (i.e. channel buffer number)
807 where the data for that channel can be read/written from/to.
808*/
809
810static char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = {
811 0, 1, 2, 3, 4, 5, 6, 7,
812 8, 9, 10, 11, 12, 13, 14, 15,
813 16, 17, 18, 19, 20, 21, 22, 23,
814 24, 25, 26, 27, 28, 29, 30, 31,
815 32, 33, 34, 35, 36, 37, 38, 39,
816 40, 41, 42, 43, 44, 45, 46, 47,
817 48, 49, 50, 51, 52, 53, 54, 55,
818 56, 57, 58, 59, 60, 61, 62, 63
819};
820
Adrian Knoth55a57602011-01-27 11:23:15 +0100821static char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = {
822 4, 5, 6, 7, 8, 9, 10, 11, /* ADAT 1 */
823 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT 2 */
824 20, 21, 22, 23, 24, 25, 26, 27, /* ADAT 3 */
825 28, 29, 30, 31, 32, 33, 34, 35, /* ADAT 4 */
826 0, 1, /* AES */
827 2, 3, /* SPDIF */
828 -1, -1, -1, -1,
829 -1, -1, -1, -1, -1, -1, -1, -1,
830 -1, -1, -1, -1, -1, -1, -1, -1,
831 -1, -1, -1, -1, -1, -1, -1, -1,
832};
833
834static char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = {
835 4, 5, 6, 7, /* ADAT 1 */
836 8, 9, 10, 11, /* ADAT 2 */
837 12, 13, 14, 15, /* ADAT 3 */
838 16, 17, 18, 19, /* ADAT 4 */
839 0, 1, /* AES */
840 2, 3, /* SPDIF */
841 -1, -1, -1, -1,
842 -1, -1, -1, -1, -1, -1, -1, -1,
843 -1, -1, -1, -1, -1, -1, -1, -1,
844 -1, -1, -1, -1, -1, -1, -1, -1,
845 -1, -1, -1, -1, -1, -1, -1, -1,
846 -1, -1, -1, -1, -1, -1, -1, -1,
847};
848
849static char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = {
850 4, 5, /* ADAT 1 */
851 6, 7, /* ADAT 2 */
852 8, 9, /* ADAT 3 */
853 10, 11, /* ADAT 4 */
854 0, 1, /* AES */
855 2, 3, /* SPDIF */
856 -1, -1, -1, -1,
857 -1, -1, -1, -1, -1, -1, -1, -1,
858 -1, -1, -1, -1, -1, -1, -1, -1,
859 -1, -1, -1, -1, -1, -1, -1, -1,
860 -1, -1, -1, -1, -1, -1, -1, -1,
861 -1, -1, -1, -1, -1, -1, -1, -1,
862 -1, -1, -1, -1, -1, -1, -1, -1,
863};
864
865static char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = {
866 0, 1, /* line in */
867 8, 9, /* aes in, */
868 10, 11, /* spdif in */
869 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT in */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200870 2, 3, 4, 5, /* AEB */
871 -1, -1, -1, -1, -1, -1,
Adrian Knoth55a57602011-01-27 11:23:15 +0100872 -1, -1, -1, -1, -1, -1, -1, -1,
873 -1, -1, -1, -1, -1, -1, -1, -1,
874 -1, -1, -1, -1, -1, -1, -1, -1,
875 -1, -1, -1, -1, -1, -1, -1, -1,
876 -1, -1, -1, -1, -1, -1, -1, -1,
877};
878
879static char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = {
880 0, 1, /* line out */
881 8, 9, /* aes out */
882 10, 11, /* spdif out */
883 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT out */
884 6, 7, /* phone out */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200885 2, 3, 4, 5, /* AEB */
886 -1, -1, -1, -1,
Adrian Knoth55a57602011-01-27 11:23:15 +0100887 -1, -1, -1, -1, -1, -1, -1, -1,
888 -1, -1, -1, -1, -1, -1, -1, -1,
889 -1, -1, -1, -1, -1, -1, -1, -1,
890 -1, -1, -1, -1, -1, -1, -1, -1,
891 -1, -1, -1, -1, -1, -1, -1, -1,
892};
893
894static char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = {
895 0, 1, /* line in */
896 8, 9, /* aes in */
897 10, 11, /* spdif in */
898 12, 14, 16, 18, /* adat in */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200899 2, 3, 4, 5, /* AEB */
900 -1, -1,
Adrian Knoth55a57602011-01-27 11:23:15 +0100901 -1, -1, -1, -1, -1, -1, -1, -1,
902 -1, -1, -1, -1, -1, -1, -1, -1,
903 -1, -1, -1, -1, -1, -1, -1, -1,
904 -1, -1, -1, -1, -1, -1, -1, -1,
905 -1, -1, -1, -1, -1, -1, -1, -1,
906 -1, -1, -1, -1, -1, -1, -1, -1
907};
908
909static char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = {
910 0, 1, /* line out */
911 8, 9, /* aes out */
912 10, 11, /* spdif out */
913 12, 14, 16, 18, /* adat out */
914 6, 7, /* phone out */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200915 2, 3, 4, 5, /* AEB */
Adrian Knoth55a57602011-01-27 11:23:15 +0100916 -1, -1, -1, -1, -1, -1, -1, -1,
917 -1, -1, -1, -1, -1, -1, -1, -1,
918 -1, -1, -1, -1, -1, -1, -1, -1,
919 -1, -1, -1, -1, -1, -1, -1, -1,
920 -1, -1, -1, -1, -1, -1, -1, -1,
921 -1, -1, -1, -1, -1, -1, -1, -1
922};
923
924static char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = {
925 0, 1, /* line in */
926 8, 9, /* aes in */
927 10, 11, /* spdif in */
928 12, 16, /* adat in */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200929 2, 3, 4, 5, /* AEB */
930 -1, -1, -1, -1,
Adrian Knoth55a57602011-01-27 11:23:15 +0100931 -1, -1, -1, -1, -1, -1, -1, -1,
932 -1, -1, -1, -1, -1, -1, -1, -1,
933 -1, -1, -1, -1, -1, -1, -1, -1,
934 -1, -1, -1, -1, -1, -1, -1, -1,
935 -1, -1, -1, -1, -1, -1, -1, -1,
936 -1, -1, -1, -1, -1, -1, -1, -1
937};
938
939static char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = {
940 0, 1, /* line out */
941 8, 9, /* aes out */
942 10, 11, /* spdif out */
943 12, 16, /* adat out */
944 6, 7, /* phone out */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200945 2, 3, 4, 5, /* AEB */
946 -1, -1,
Adrian Knoth55a57602011-01-27 11:23:15 +0100947 -1, -1, -1, -1, -1, -1, -1, -1,
948 -1, -1, -1, -1, -1, -1, -1, -1,
949 -1, -1, -1, -1, -1, -1, -1, -1,
950 -1, -1, -1, -1, -1, -1, -1, -1,
951 -1, -1, -1, -1, -1, -1, -1, -1,
952 -1, -1, -1, -1, -1, -1, -1, -1
953};
954
Adrian Knoth432d2502011-02-23 11:43:08 +0100955static char channel_map_aes32[HDSPM_MAX_CHANNELS] = {
956 0, 1, 2, 3, 4, 5, 6, 7,
957 8, 9, 10, 11, 12, 13, 14, 15,
958 -1, -1, -1, -1, -1, -1, -1, -1,
959 -1, -1, -1, -1, -1, -1, -1, -1,
960 -1, -1, -1, -1, -1, -1, -1, -1,
961 -1, -1, -1, -1, -1, -1, -1, -1,
962 -1, -1, -1, -1, -1, -1, -1, -1,
963 -1, -1, -1, -1, -1, -1, -1, -1
964};
965
Takashi Iwai98274f02005-11-17 14:52:34 +0100966struct hdspm_midi {
967 struct hdspm *hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +0200968 int id;
Takashi Iwai98274f02005-11-17 14:52:34 +0100969 struct snd_rawmidi *rmidi;
970 struct snd_rawmidi_substream *input;
971 struct snd_rawmidi_substream *output;
Takashi Iwai763f3562005-06-03 11:25:34 +0200972 char istimer; /* timer in use */
973 struct timer_list timer;
974 spinlock_t lock;
975 int pending;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100976 int dataIn;
977 int statusIn;
978 int dataOut;
979 int statusOut;
980 int ie;
981 int irq;
982};
983
984struct hdspm_tco {
Martin Dausel69358fc2013-07-05 11:28:23 +0200985 int input; /* 0: LTC, 1:Video, 2: WC*/
986 int framerate; /* 0=24, 1=25, 2=29.97, 3=29.97d, 4=30, 5=30d */
987 int wordclock; /* 0=1:1, 1=44.1->48, 2=48->44.1 */
988 int samplerate; /* 0=44.1, 1=48, 2= freq from app */
989 int pull; /* 0=0, 1=+0.1%, 2=-0.1%, 3=+4%, 4=-4%*/
Adrian Knoth0dca1792011-01-26 19:32:14 +0100990 int term; /* 0 = off, 1 = on */
Takashi Iwai763f3562005-06-03 11:25:34 +0200991};
992
Takashi Iwai98274f02005-11-17 14:52:34 +0100993struct hdspm {
Takashi Iwai763f3562005-06-03 11:25:34 +0200994 spinlock_t lock;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200995 /* only one playback and/or capture stream */
996 struct snd_pcm_substream *capture_substream;
997 struct snd_pcm_substream *playback_substream;
Takashi Iwai763f3562005-06-03 11:25:34 +0200998
999 char *card_name; /* for procinfo */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001000 unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
1001
Adrian Knoth0dca1792011-01-26 19:32:14 +01001002 uint8_t io_type;
Takashi Iwai763f3562005-06-03 11:25:34 +02001003
Takashi Iwai763f3562005-06-03 11:25:34 +02001004 int monitor_outs; /* set up monitoring outs init flag */
1005
1006 u32 control_register; /* cached value */
1007 u32 control2_register; /* cached value */
Martin Dausel69358fc2013-07-05 11:28:23 +02001008 u32 settings_register; /* cached value for AIO / RayDat (sync reference, master/slave) */
Takashi Iwai763f3562005-06-03 11:25:34 +02001009
Adrian Knoth0dca1792011-01-26 19:32:14 +01001010 struct hdspm_midi midi[4];
Takashi Iwai763f3562005-06-03 11:25:34 +02001011 struct tasklet_struct midi_tasklet;
1012
1013 size_t period_bytes;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001014 unsigned char ss_in_channels;
1015 unsigned char ds_in_channels;
1016 unsigned char qs_in_channels;
1017 unsigned char ss_out_channels;
1018 unsigned char ds_out_channels;
1019 unsigned char qs_out_channels;
1020
1021 unsigned char max_channels_in;
1022 unsigned char max_channels_out;
1023
Takashi Iwai286bed02011-06-30 12:45:36 +02001024 signed char *channel_map_in;
1025 signed char *channel_map_out;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001026
Takashi Iwai286bed02011-06-30 12:45:36 +02001027 signed char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs;
1028 signed char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001029
1030 char **port_names_in;
1031 char **port_names_out;
1032
1033 char **port_names_in_ss, **port_names_in_ds, **port_names_in_qs;
1034 char **port_names_out_ss, **port_names_out_ds, **port_names_out_qs;
Takashi Iwai763f3562005-06-03 11:25:34 +02001035
1036 unsigned char *playback_buffer; /* suitably aligned address */
1037 unsigned char *capture_buffer; /* suitably aligned address */
1038
1039 pid_t capture_pid; /* process id which uses capture */
1040 pid_t playback_pid; /* process id which uses capture */
1041 int running; /* running status */
1042
1043 int last_external_sample_rate; /* samplerate mystic ... */
1044 int last_internal_sample_rate;
1045 int system_sample_rate;
1046
Takashi Iwai763f3562005-06-03 11:25:34 +02001047 int dev; /* Hardware vars... */
1048 int irq;
1049 unsigned long port;
1050 void __iomem *iobase;
1051
1052 int irq_count; /* for debug */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001053 int midiPorts;
Takashi Iwai763f3562005-06-03 11:25:34 +02001054
Takashi Iwai98274f02005-11-17 14:52:34 +01001055 struct snd_card *card; /* one card */
1056 struct snd_pcm *pcm; /* has one pcm */
1057 struct snd_hwdep *hwdep; /* and a hwdep for additional ioctl */
Takashi Iwai763f3562005-06-03 11:25:34 +02001058 struct pci_dev *pci; /* and an pci info */
1059
1060 /* Mixer vars */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001061 /* fast alsa mixer */
1062 struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS];
1063 /* but input to much, so not used */
1064 struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS];
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001065 /* full mixer accessible over mixer ioctl or hwdep-device */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001066 struct hdspm_mixer *mixer;
Takashi Iwai763f3562005-06-03 11:25:34 +02001067
Adrian Knoth0dca1792011-01-26 19:32:14 +01001068 struct hdspm_tco *tco; /* NULL if no TCO detected */
Takashi Iwai763f3562005-06-03 11:25:34 +02001069
Adrian Knotheb0d4db2013-07-05 11:28:21 +02001070 const char *const *texts_autosync;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001071 int texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +02001072
Adrian Knoth0dca1792011-01-26 19:32:14 +01001073 cycles_t last_interrupt;
Jaroslav Kysela730a5862011-01-27 13:03:15 +01001074
Adrian Knoth7d53a632012-01-04 14:31:16 +01001075 unsigned int serial;
1076
Jaroslav Kysela730a5862011-01-27 13:03:15 +01001077 struct hdspm_peak_rms peak_rms;
Takashi Iwai763f3562005-06-03 11:25:34 +02001078};
1079
Takashi Iwai763f3562005-06-03 11:25:34 +02001080
Benoit Taine9baa3c32014-08-08 15:56:03 +02001081static const struct pci_device_id snd_hdspm_ids[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02001082 {
1083 .vendor = PCI_VENDOR_ID_XILINX,
1084 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
1085 .subvendor = PCI_ANY_ID,
1086 .subdevice = PCI_ANY_ID,
1087 .class = 0,
1088 .class_mask = 0,
1089 .driver_data = 0},
1090 {0,}
1091};
1092
1093MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
1094
1095/* prototypes */
Bill Pembertone23e7a12012-12-06 12:35:10 -05001096static int snd_hdspm_create_alsa_devices(struct snd_card *card,
1097 struct hdspm *hdspm);
1098static int snd_hdspm_create_pcm(struct snd_card *card,
1099 struct hdspm *hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001100
Adrian Knoth0dca1792011-01-26 19:32:14 +01001101static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
Adrian Knoth3f7bf912013-03-10 00:37:21 +01001102static inline int hdspm_get_pll_freq(struct hdspm *hdspm);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001103static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
1104static int hdspm_autosync_ref(struct hdspm *hdspm);
Adrian Knoth34be7eb2013-07-05 11:27:56 +02001105static int hdspm_set_toggle_setting(struct hdspm *hdspm, u32 regmask, int out);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001106static int snd_hdspm_set_defaults(struct hdspm *hdspm);
Adrian Knoth21a164d2012-10-19 17:42:23 +02001107static int hdspm_system_clock_mode(struct hdspm *hdspm);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001108static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +02001109 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02001110 unsigned int reg, int channels);
1111
Adrian Knoth5b266352013-07-05 11:28:10 +02001112static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx);
1113static int hdspm_wc_sync_check(struct hdspm *hdspm);
1114static int hdspm_tco_sync_check(struct hdspm *hdspm);
1115static int hdspm_sync_in_sync_check(struct hdspm *hdspm);
1116
1117static int hdspm_get_aes_sample_rate(struct hdspm *hdspm, int index);
1118static int hdspm_get_tco_sample_rate(struct hdspm *hdspm);
1119static int hdspm_get_wc_sample_rate(struct hdspm *hdspm);
1120
1121
1122
Remy Bruno3cee5a62006-10-16 12:46:32 +02001123static inline int HDSPM_bit2freq(int n)
1124{
Denys Vlasenko62cef822008-04-14 13:04:18 +02001125 static const int bit2freq_tab[] = {
1126 0, 32000, 44100, 48000, 64000, 88200,
Remy Bruno3cee5a62006-10-16 12:46:32 +02001127 96000, 128000, 176400, 192000 };
1128 if (n < 1 || n > 9)
1129 return 0;
1130 return bit2freq_tab[n];
1131}
1132
Adrian Knothb2ed6322013-07-05 11:27:54 +02001133static bool hdspm_is_raydat_or_aio(struct hdspm *hdspm)
1134{
1135 return ((AIO == hdspm->io_type) || (RayDAT == hdspm->io_type));
1136}
1137
1138
Adrian Knoth0dca1792011-01-26 19:32:14 +01001139/* Write/read to/from HDSPM with Adresses in Bytes
Takashi Iwai763f3562005-06-03 11:25:34 +02001140 not words but only 32Bit writes are allowed */
1141
Takashi Iwai98274f02005-11-17 14:52:34 +01001142static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
Takashi Iwai763f3562005-06-03 11:25:34 +02001143 unsigned int val)
1144{
1145 writel(val, hdspm->iobase + reg);
1146}
1147
Takashi Iwai98274f02005-11-17 14:52:34 +01001148static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
Takashi Iwai763f3562005-06-03 11:25:34 +02001149{
1150 return readl(hdspm->iobase + reg);
1151}
1152
Adrian Knoth0dca1792011-01-26 19:32:14 +01001153/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
1154 mixer is write only on hardware so we have to cache him for read
Takashi Iwai763f3562005-06-03 11:25:34 +02001155 each fader is a u32, but uses only the first 16 bit */
1156
Takashi Iwai98274f02005-11-17 14:52:34 +01001157static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001158 unsigned int in)
1159{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001160 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001161 return 0;
1162
1163 return hdspm->mixer->ch[chan].in[in];
1164}
1165
Takashi Iwai98274f02005-11-17 14:52:34 +01001166static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001167 unsigned int pb)
1168{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001169 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001170 return 0;
1171 return hdspm->mixer->ch[chan].pb[pb];
1172}
1173
Denys Vlasenko62cef822008-04-14 13:04:18 +02001174static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001175 unsigned int in, unsigned short data)
1176{
1177 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
1178 return -1;
1179
1180 hdspm_write(hdspm,
1181 HDSPM_MADI_mixerBase +
1182 ((in + 128 * chan) * sizeof(u32)),
1183 (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
1184 return 0;
1185}
1186
Denys Vlasenko62cef822008-04-14 13:04:18 +02001187static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001188 unsigned int pb, unsigned short data)
1189{
1190 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
1191 return -1;
1192
1193 hdspm_write(hdspm,
1194 HDSPM_MADI_mixerBase +
1195 ((64 + pb + 128 * chan) * sizeof(u32)),
1196 (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
1197 return 0;
1198}
1199
1200
1201/* enable DMA for specific channels, now available for DSP-MADI */
Takashi Iwai98274f02005-11-17 14:52:34 +01001202static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001203{
1204 hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
1205}
1206
Takashi Iwai98274f02005-11-17 14:52:34 +01001207static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001208{
1209 hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
1210}
1211
1212/* check if same process is writing and reading */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001213static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001214{
1215 unsigned long flags;
1216 int ret = 1;
1217
1218 spin_lock_irqsave(&hdspm->lock, flags);
1219 if ((hdspm->playback_pid != hdspm->capture_pid) &&
1220 (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
1221 ret = 0;
1222 }
1223 spin_unlock_irqrestore(&hdspm->lock, flags);
1224 return ret;
1225}
1226
Adrian Knothfcdc4ba2013-03-10 00:37:22 +01001227/* round arbitary sample rates to commonly known rates */
1228static int hdspm_round_frequency(int rate)
1229{
1230 if (rate < 38050)
1231 return 32000;
1232 if (rate < 46008)
1233 return 44100;
1234 else
1235 return 48000;
1236}
1237
Adrian Knotha8a729f2013-05-31 12:57:10 +02001238/* QS and DS rates normally can not be detected
1239 * automatically by the card. Only exception is MADI
1240 * in 96k frame mode.
1241 *
1242 * So if we read SS values (32 .. 48k), check for
1243 * user-provided DS/QS bits in the control register
1244 * and multiply the base frequency accordingly.
1245 */
1246static int hdspm_rate_multiplier(struct hdspm *hdspm, int rate)
1247{
1248 if (rate <= 48000) {
1249 if (hdspm->control_register & HDSPM_QuadSpeed)
1250 return rate * 4;
1251 else if (hdspm->control_register &
1252 HDSPM_DoubleSpeed)
1253 return rate * 2;
Fengguang Wu68593c92013-07-15 21:41:32 +08001254 }
Adrian Knotha8a729f2013-05-31 12:57:10 +02001255 return rate;
1256}
1257
Adrian Knoth5b266352013-07-05 11:28:10 +02001258/* check for external sample rate, returns the sample rate in Hz*/
Denys Vlasenko62cef822008-04-14 13:04:18 +02001259static int hdspm_external_sample_rate(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001260{
Sudip Mukherjeedf57de12014-10-29 20:09:45 +05301261 unsigned int status, status2;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001262 int syncref, rate = 0, rate_bits;
Takashi Iwai763f3562005-06-03 11:25:34 +02001263
Adrian Knoth0dca1792011-01-26 19:32:14 +01001264 switch (hdspm->io_type) {
1265 case AES32:
1266 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1267 status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001268
1269 syncref = hdspm_autosync_ref(hdspm);
Adrian Knothdbae4a02013-07-05 11:28:14 +02001270 switch (syncref) {
1271 case HDSPM_AES32_AUTOSYNC_FROM_WORD:
1272 /* Check WC sync and get sample rate */
1273 if (hdspm_wc_sync_check(hdspm))
1274 return HDSPM_bit2freq(hdspm_get_wc_sample_rate(hdspm));
1275 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001276
Adrian Knothdbae4a02013-07-05 11:28:14 +02001277 case HDSPM_AES32_AUTOSYNC_FROM_AES1:
1278 case HDSPM_AES32_AUTOSYNC_FROM_AES2:
1279 case HDSPM_AES32_AUTOSYNC_FROM_AES3:
1280 case HDSPM_AES32_AUTOSYNC_FROM_AES4:
1281 case HDSPM_AES32_AUTOSYNC_FROM_AES5:
1282 case HDSPM_AES32_AUTOSYNC_FROM_AES6:
1283 case HDSPM_AES32_AUTOSYNC_FROM_AES7:
1284 case HDSPM_AES32_AUTOSYNC_FROM_AES8:
1285 /* Check AES sync and get sample rate */
1286 if (hdspm_aes_sync_check(hdspm, syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1))
1287 return HDSPM_bit2freq(hdspm_get_aes_sample_rate(hdspm,
1288 syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1));
1289 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001290
Adrian Knothdbae4a02013-07-05 11:28:14 +02001291
1292 case HDSPM_AES32_AUTOSYNC_FROM_TCO:
1293 /* Check TCO sync and get sample rate */
1294 if (hdspm_tco_sync_check(hdspm))
1295 return HDSPM_bit2freq(hdspm_get_tco_sample_rate(hdspm));
1296 break;
1297 default:
1298 return 0;
1299 } /* end switch(syncref) */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001300 break;
1301
1302 case MADIface:
1303 status = hdspm_read(hdspm, HDSPM_statusRegister);
1304
1305 if (!(status & HDSPM_madiLock)) {
1306 rate = 0; /* no lock */
1307 } else {
1308 switch (status & (HDSPM_status1_freqMask)) {
1309 case HDSPM_status1_F_0*1:
1310 rate = 32000; break;
1311 case HDSPM_status1_F_0*2:
1312 rate = 44100; break;
1313 case HDSPM_status1_F_0*3:
1314 rate = 48000; break;
1315 case HDSPM_status1_F_0*4:
1316 rate = 64000; break;
1317 case HDSPM_status1_F_0*5:
1318 rate = 88200; break;
1319 case HDSPM_status1_F_0*6:
1320 rate = 96000; break;
1321 case HDSPM_status1_F_0*7:
1322 rate = 128000; break;
1323 case HDSPM_status1_F_0*8:
1324 rate = 176400; break;
1325 case HDSPM_status1_F_0*9:
1326 rate = 192000; break;
1327 default:
1328 rate = 0; break;
1329 }
1330 }
1331
1332 break;
1333
1334 case MADI:
1335 case AIO:
1336 case RayDAT:
1337 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1338 status = hdspm_read(hdspm, HDSPM_statusRegister);
1339 rate = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02001340
Remy Bruno3cee5a62006-10-16 12:46:32 +02001341 /* if wordclock has synced freq and wordclock is valid */
1342 if ((status2 & HDSPM_wcLock) != 0 &&
Adrian Knothfedf1532011-06-12 17:26:18 +02001343 (status2 & HDSPM_SelSyncRef0) == 0) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02001344
1345 rate_bits = status2 & HDSPM_wcFreqMask;
1346
Adrian Knoth0dca1792011-01-26 19:32:14 +01001347
Remy Bruno3cee5a62006-10-16 12:46:32 +02001348 switch (rate_bits) {
1349 case HDSPM_wcFreq32:
1350 rate = 32000;
1351 break;
1352 case HDSPM_wcFreq44_1:
1353 rate = 44100;
1354 break;
1355 case HDSPM_wcFreq48:
1356 rate = 48000;
1357 break;
1358 case HDSPM_wcFreq64:
1359 rate = 64000;
1360 break;
1361 case HDSPM_wcFreq88_2:
1362 rate = 88200;
1363 break;
1364 case HDSPM_wcFreq96:
1365 rate = 96000;
1366 break;
Adrian Knotha8cd7142013-05-31 12:57:09 +02001367 case HDSPM_wcFreq128:
1368 rate = 128000;
1369 break;
1370 case HDSPM_wcFreq176_4:
1371 rate = 176400;
1372 break;
1373 case HDSPM_wcFreq192:
1374 rate = 192000;
1375 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001376 default:
1377 rate = 0;
1378 break;
1379 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001380 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001381
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001382 /* if rate detected and Syncref is Word than have it,
1383 * word has priority to MADI
1384 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001385 if (rate != 0 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001386 (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
Adrian Knoth7b559392013-05-31 12:57:11 +02001387 return hdspm_rate_multiplier(hdspm, rate);
Remy Bruno3cee5a62006-10-16 12:46:32 +02001388
Adrian Knoth0dca1792011-01-26 19:32:14 +01001389 /* maybe a madi input (which is taken if sel sync is madi) */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001390 if (status & HDSPM_madiLock) {
1391 rate_bits = status & HDSPM_madiFreqMask;
1392
1393 switch (rate_bits) {
1394 case HDSPM_madiFreq32:
1395 rate = 32000;
1396 break;
1397 case HDSPM_madiFreq44_1:
1398 rate = 44100;
1399 break;
1400 case HDSPM_madiFreq48:
1401 rate = 48000;
1402 break;
1403 case HDSPM_madiFreq64:
1404 rate = 64000;
1405 break;
1406 case HDSPM_madiFreq88_2:
1407 rate = 88200;
1408 break;
1409 case HDSPM_madiFreq96:
1410 rate = 96000;
1411 break;
1412 case HDSPM_madiFreq128:
1413 rate = 128000;
1414 break;
1415 case HDSPM_madiFreq176_4:
1416 rate = 176400;
1417 break;
1418 case HDSPM_madiFreq192:
1419 rate = 192000;
1420 break;
1421 default:
1422 rate = 0;
1423 break;
1424 }
Adrian Knothd12c51d2011-07-29 03:11:03 +02001425
Adrian Knothfcdc4ba2013-03-10 00:37:22 +01001426 } /* endif HDSPM_madiLock */
1427
1428 /* check sample rate from TCO or SYNC_IN */
1429 {
1430 bool is_valid_input = 0;
1431 bool has_sync = 0;
1432
1433 syncref = hdspm_autosync_ref(hdspm);
1434 if (HDSPM_AUTOSYNC_FROM_TCO == syncref) {
1435 is_valid_input = 1;
1436 has_sync = (HDSPM_SYNC_CHECK_SYNC ==
1437 hdspm_tco_sync_check(hdspm));
1438 } else if (HDSPM_AUTOSYNC_FROM_SYNC_IN == syncref) {
1439 is_valid_input = 1;
1440 has_sync = (HDSPM_SYNC_CHECK_SYNC ==
1441 hdspm_sync_in_sync_check(hdspm));
Adrian Knothd12c51d2011-07-29 03:11:03 +02001442 }
Adrian Knothfcdc4ba2013-03-10 00:37:22 +01001443
1444 if (is_valid_input && has_sync) {
1445 rate = hdspm_round_frequency(
1446 hdspm_get_pll_freq(hdspm));
1447 }
1448 }
1449
Adrian Knotha8a729f2013-05-31 12:57:10 +02001450 rate = hdspm_rate_multiplier(hdspm, rate);
1451
Adrian Knoth0dca1792011-01-26 19:32:14 +01001452 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001453 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001454
1455 return rate;
Takashi Iwai763f3562005-06-03 11:25:34 +02001456}
1457
Adrian Knoth7cb155f2011-08-15 00:22:53 +02001458/* return latency in samples per period */
1459static int hdspm_get_latency(struct hdspm *hdspm)
1460{
1461 int n;
1462
1463 n = hdspm_decode_latency(hdspm->control_register);
1464
1465 /* Special case for new RME cards with 32 samples period size.
1466 * The three latency bits in the control register
1467 * (HDSP_LatencyMask) encode latency values of 64 samples as
1468 * 0, 128 samples as 1 ... 4096 samples as 6. For old cards, 7
1469 * denotes 8192 samples, but on new cards like RayDAT or AIO,
1470 * it corresponds to 32 samples.
1471 */
1472 if ((7 == n) && (RayDAT == hdspm->io_type || AIO == hdspm->io_type))
1473 n = -1;
1474
1475 return 1 << (n + 6);
1476}
1477
Takashi Iwai763f3562005-06-03 11:25:34 +02001478/* Latency function */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001479static inline void hdspm_compute_period_size(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001480{
Adrian Knoth7cb155f2011-08-15 00:22:53 +02001481 hdspm->period_bytes = 4 * hdspm_get_latency(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001482}
1483
Adrian Knoth0dca1792011-01-26 19:32:14 +01001484
1485static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001486{
1487 int position;
1488
1489 position = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth483cee72011-02-23 11:43:09 +01001490
1491 switch (hdspm->io_type) {
1492 case RayDAT:
1493 case AIO:
1494 position &= HDSPM_BufferPositionMask;
1495 position /= 4; /* Bytes per sample */
1496 break;
1497 default:
1498 position = (position & HDSPM_BufferID) ?
1499 (hdspm->period_bytes / 4) : 0;
1500 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001501
1502 return position;
1503}
1504
1505
Takashi Iwai98274f02005-11-17 14:52:34 +01001506static inline void hdspm_start_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001507{
1508 s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
1509 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1510}
1511
Takashi Iwai98274f02005-11-17 14:52:34 +01001512static inline void hdspm_stop_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001513{
1514 s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
1515 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1516}
1517
1518/* should I silence all or only opened ones ? doit all for first even is 4MB*/
Denys Vlasenko62cef822008-04-14 13:04:18 +02001519static void hdspm_silence_playback(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001520{
1521 int i;
1522 int n = hdspm->period_bytes;
1523 void *buf = hdspm->playback_buffer;
1524
Remy Bruno3cee5a62006-10-16 12:46:32 +02001525 if (buf == NULL)
1526 return;
Takashi Iwai763f3562005-06-03 11:25:34 +02001527
1528 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
1529 memset(buf, 0, n);
1530 buf += HDSPM_CHANNEL_BUFFER_BYTES;
1531 }
1532}
1533
Adrian Knoth0dca1792011-01-26 19:32:14 +01001534static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames)
Takashi Iwai763f3562005-06-03 11:25:34 +02001535{
1536 int n;
1537
1538 spin_lock_irq(&s->lock);
1539
Adrian Knoth2e610272011-08-15 00:22:54 +02001540 if (32 == frames) {
1541 /* Special case for new RME cards like RayDAT/AIO which
1542 * support period sizes of 32 samples. Since latency is
1543 * encoded in the three bits of HDSP_LatencyMask, we can only
1544 * have values from 0 .. 7. While 0 still means 64 samples and
1545 * 6 represents 4096 samples on all cards, 7 represents 8192
1546 * on older cards and 32 samples on new cards.
1547 *
1548 * In other words, period size in samples is calculated by
1549 * 2^(n+6) with n ranging from 0 .. 7.
1550 */
1551 n = 7;
1552 } else {
1553 frames >>= 7;
1554 n = 0;
1555 while (frames) {
1556 n++;
1557 frames >>= 1;
1558 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001559 }
Adrian Knoth2e610272011-08-15 00:22:54 +02001560
Takashi Iwai763f3562005-06-03 11:25:34 +02001561 s->control_register &= ~HDSPM_LatencyMask;
1562 s->control_register |= hdspm_encode_latency(n);
1563
1564 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1565
1566 hdspm_compute_period_size(s);
1567
1568 spin_unlock_irq(&s->lock);
1569
1570 return 0;
1571}
1572
Adrian Knoth0dca1792011-01-26 19:32:14 +01001573static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period)
1574{
1575 u64 freq_const;
1576
1577 if (period == 0)
1578 return 0;
1579
1580 switch (hdspm->io_type) {
1581 case MADI:
1582 case AES32:
1583 freq_const = 110069313433624ULL;
1584 break;
1585 case RayDAT:
1586 case AIO:
1587 freq_const = 104857600000000ULL;
1588 break;
1589 case MADIface:
1590 freq_const = 131072000000000ULL;
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001591 break;
1592 default:
1593 snd_BUG();
1594 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001595 }
1596
1597 return div_u64(freq_const, period);
1598}
1599
1600
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001601static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
1602{
1603 u64 n;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001604
Takashi Iwaic1099c32016-02-29 14:32:42 +01001605 if (snd_BUG_ON(rate <= 0))
1606 return;
1607
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001608 if (rate >= 112000)
1609 rate /= 4;
1610 else if (rate >= 56000)
1611 rate /= 2;
1612
Adrian Knoth0dca1792011-01-26 19:32:14 +01001613 switch (hdspm->io_type) {
1614 case MADIface:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001615 n = 131072000000000ULL; /* 125 MHz */
1616 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001617 case MADI:
1618 case AES32:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001619 n = 110069313433624ULL; /* 105 MHz */
1620 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001621 case RayDAT:
1622 case AIO:
Takashi Iwai3d56c8e2011-08-05 12:30:12 +02001623 n = 104857600000000ULL; /* 100 MHz */
1624 break;
1625 default:
1626 snd_BUG();
1627 return;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001628 }
1629
Takashi Iwai3f7440a2009-06-05 17:40:04 +02001630 n = div_u64(n, rate);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001631 /* n should be less than 2^32 for being written to FREQ register */
Takashi Iwaida3cec32008-08-08 17:12:14 +02001632 snd_BUG_ON(n >> 32);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001633 hdspm_write(hdspm, HDSPM_freqReg, (u32)n);
1634}
Takashi Iwai763f3562005-06-03 11:25:34 +02001635
1636/* dummy set rate lets see what happens */
Takashi Iwai98274f02005-11-17 14:52:34 +01001637static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
Takashi Iwai763f3562005-06-03 11:25:34 +02001638{
Takashi Iwai763f3562005-06-03 11:25:34 +02001639 int current_rate;
1640 int rate_bits;
1641 int not_set = 0;
Remy Bruno65345992007-08-31 12:21:08 +02001642 int current_speed, target_speed;
Takashi Iwai763f3562005-06-03 11:25:34 +02001643
1644 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
1645 it (e.g. during module initialization).
1646 */
1647
1648 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
1649
Adrian Knoth0dca1792011-01-26 19:32:14 +01001650 /* SLAVE --- */
Takashi Iwai763f3562005-06-03 11:25:34 +02001651 if (called_internally) {
1652
Adrian Knoth0dca1792011-01-26 19:32:14 +01001653 /* request from ctl or card initialization
1654 just make a warning an remember setting
1655 for future master mode switching */
1656
Takashi Iwaie3a471d62014-02-26 12:05:40 +01001657 dev_warn(hdspm->card->dev,
1658 "Warning: device is not running as a clock master.\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001659 not_set = 1;
1660 } else {
1661
1662 /* hw_param request while in AutoSync mode */
1663 int external_freq =
1664 hdspm_external_sample_rate(hdspm);
1665
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001666 if (hdspm_autosync_ref(hdspm) ==
1667 HDSPM_AUTOSYNC_FROM_NONE) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001668
Takashi Iwaie3a471d62014-02-26 12:05:40 +01001669 dev_warn(hdspm->card->dev,
Colin Ian King07cb3272016-08-22 12:50:02 +01001670 "Detected no External Sync\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001671 not_set = 1;
1672
1673 } else if (rate != external_freq) {
1674
Takashi Iwaie3a471d62014-02-26 12:05:40 +01001675 dev_warn(hdspm->card->dev,
1676 "Warning: No AutoSync source for requested rate\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001677 not_set = 1;
1678 }
1679 }
1680 }
1681
1682 current_rate = hdspm->system_sample_rate;
1683
1684 /* Changing between Singe, Double and Quad speed is not
1685 allowed if any substreams are open. This is because such a change
1686 causes a shift in the location of the DMA buffers and a reduction
1687 in the number of available buffers.
1688
1689 Note that a similar but essentially insoluble problem exists for
1690 externally-driven rate changes. All we can do is to flag rate
Adrian Knoth0dca1792011-01-26 19:32:14 +01001691 changes in the read/write routines.
Takashi Iwai763f3562005-06-03 11:25:34 +02001692 */
1693
Remy Bruno65345992007-08-31 12:21:08 +02001694 if (current_rate <= 48000)
1695 current_speed = HDSPM_SPEED_SINGLE;
1696 else if (current_rate <= 96000)
1697 current_speed = HDSPM_SPEED_DOUBLE;
1698 else
1699 current_speed = HDSPM_SPEED_QUAD;
1700
1701 if (rate <= 48000)
1702 target_speed = HDSPM_SPEED_SINGLE;
1703 else if (rate <= 96000)
1704 target_speed = HDSPM_SPEED_DOUBLE;
1705 else
1706 target_speed = HDSPM_SPEED_QUAD;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001707
Takashi Iwai763f3562005-06-03 11:25:34 +02001708 switch (rate) {
1709 case 32000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001710 rate_bits = HDSPM_Frequency32KHz;
1711 break;
1712 case 44100:
Takashi Iwai763f3562005-06-03 11:25:34 +02001713 rate_bits = HDSPM_Frequency44_1KHz;
1714 break;
1715 case 48000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001716 rate_bits = HDSPM_Frequency48KHz;
1717 break;
1718 case 64000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001719 rate_bits = HDSPM_Frequency64KHz;
1720 break;
1721 case 88200:
Takashi Iwai763f3562005-06-03 11:25:34 +02001722 rate_bits = HDSPM_Frequency88_2KHz;
1723 break;
1724 case 96000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001725 rate_bits = HDSPM_Frequency96KHz;
1726 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001727 case 128000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001728 rate_bits = HDSPM_Frequency128KHz;
1729 break;
1730 case 176400:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001731 rate_bits = HDSPM_Frequency176_4KHz;
1732 break;
1733 case 192000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001734 rate_bits = HDSPM_Frequency192KHz;
1735 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001736 default:
1737 return -EINVAL;
1738 }
1739
Remy Bruno65345992007-08-31 12:21:08 +02001740 if (current_speed != target_speed
Takashi Iwai763f3562005-06-03 11:25:34 +02001741 && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01001742 dev_err(hdspm->card->dev,
1743 "cannot change from %s speed to %s speed mode (capture PID = %d, playback PID = %d)\n",
1744 hdspm_speed_names[current_speed],
1745 hdspm_speed_names[target_speed],
1746 hdspm->capture_pid, hdspm->playback_pid);
Takashi Iwai763f3562005-06-03 11:25:34 +02001747 return -EBUSY;
1748 }
1749
1750 hdspm->control_register &= ~HDSPM_FrequencyMask;
1751 hdspm->control_register |= rate_bits;
1752 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1753
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001754 /* For AES32, need to set DDS value in FREQ register
1755 For MADI, also apparently */
1756 hdspm_set_dds_value(hdspm, rate);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001757
1758 if (AES32 == hdspm->io_type && rate != current_rate)
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001759 hdspm_write(hdspm, HDSPM_eeprom_wr, 0);
Takashi Iwai763f3562005-06-03 11:25:34 +02001760
1761 hdspm->system_sample_rate = rate;
1762
Adrian Knoth0dca1792011-01-26 19:32:14 +01001763 if (rate <= 48000) {
1764 hdspm->channel_map_in = hdspm->channel_map_in_ss;
1765 hdspm->channel_map_out = hdspm->channel_map_out_ss;
1766 hdspm->max_channels_in = hdspm->ss_in_channels;
1767 hdspm->max_channels_out = hdspm->ss_out_channels;
1768 hdspm->port_names_in = hdspm->port_names_in_ss;
1769 hdspm->port_names_out = hdspm->port_names_out_ss;
1770 } else if (rate <= 96000) {
1771 hdspm->channel_map_in = hdspm->channel_map_in_ds;
1772 hdspm->channel_map_out = hdspm->channel_map_out_ds;
1773 hdspm->max_channels_in = hdspm->ds_in_channels;
1774 hdspm->max_channels_out = hdspm->ds_out_channels;
1775 hdspm->port_names_in = hdspm->port_names_in_ds;
1776 hdspm->port_names_out = hdspm->port_names_out_ds;
1777 } else {
1778 hdspm->channel_map_in = hdspm->channel_map_in_qs;
1779 hdspm->channel_map_out = hdspm->channel_map_out_qs;
1780 hdspm->max_channels_in = hdspm->qs_in_channels;
1781 hdspm->max_channels_out = hdspm->qs_out_channels;
1782 hdspm->port_names_in = hdspm->port_names_in_qs;
1783 hdspm->port_names_out = hdspm->port_names_out_qs;
1784 }
1785
Takashi Iwai763f3562005-06-03 11:25:34 +02001786 if (not_set != 0)
1787 return -1;
1788
1789 return 0;
1790}
1791
1792/* mainly for init to 0 on load */
Takashi Iwai98274f02005-11-17 14:52:34 +01001793static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
Takashi Iwai763f3562005-06-03 11:25:34 +02001794{
1795 int i, j;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001796 unsigned int gain;
1797
1798 if (sgain > UNITY_GAIN)
1799 gain = UNITY_GAIN;
1800 else if (sgain < 0)
1801 gain = 0;
1802 else
1803 gain = sgain;
Takashi Iwai763f3562005-06-03 11:25:34 +02001804
1805 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
1806 for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
1807 hdspm_write_in_gain(hdspm, i, j, gain);
1808 hdspm_write_pb_gain(hdspm, i, j, gain);
1809 }
1810}
1811
1812/*----------------------------------------------------------------------------
1813 MIDI
1814 ----------------------------------------------------------------------------*/
1815
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001816static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm,
1817 int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001818{
1819 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001820 return hdspm_read(hdspm, hdspm->midi[id].dataIn);
Takashi Iwai763f3562005-06-03 11:25:34 +02001821}
1822
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001823static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
1824 int val)
Takashi Iwai763f3562005-06-03 11:25:34 +02001825{
1826 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001827 return hdspm_write(hdspm, hdspm->midi[id].dataOut, val);
Takashi Iwai763f3562005-06-03 11:25:34 +02001828}
1829
Takashi Iwai98274f02005-11-17 14:52:34 +01001830static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001831{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001832 return hdspm_read(hdspm, hdspm->midi[id].statusIn) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001833}
1834
Takashi Iwai98274f02005-11-17 14:52:34 +01001835static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001836{
1837 int fifo_bytes_used;
1838
Adrian Knoth0dca1792011-01-26 19:32:14 +01001839 fifo_bytes_used = hdspm_read(hdspm, hdspm->midi[id].statusOut) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001840
1841 if (fifo_bytes_used < 128)
1842 return 128 - fifo_bytes_used;
1843 else
1844 return 0;
1845}
1846
Denys Vlasenko62cef822008-04-14 13:04:18 +02001847static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001848{
1849 while (snd_hdspm_midi_input_available (hdspm, id))
1850 snd_hdspm_midi_read_byte (hdspm, id);
1851}
1852
Takashi Iwai98274f02005-11-17 14:52:34 +01001853static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001854{
1855 unsigned long flags;
1856 int n_pending;
1857 int to_write;
1858 int i;
1859 unsigned char buf[128];
1860
1861 /* Output is not interrupt driven */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001862
Takashi Iwai763f3562005-06-03 11:25:34 +02001863 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001864 if (hmidi->output &&
1865 !snd_rawmidi_transmit_empty (hmidi->output)) {
1866 n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm,
1867 hmidi->id);
1868 if (n_pending > 0) {
1869 if (n_pending > (int)sizeof (buf))
1870 n_pending = sizeof (buf);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001871
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001872 to_write = snd_rawmidi_transmit (hmidi->output, buf,
1873 n_pending);
1874 if (to_write > 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001875 for (i = 0; i < to_write; ++i)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001876 snd_hdspm_midi_write_byte (hmidi->hdspm,
1877 hmidi->id,
1878 buf[i]);
Takashi Iwai763f3562005-06-03 11:25:34 +02001879 }
1880 }
1881 }
1882 spin_unlock_irqrestore (&hmidi->lock, flags);
1883 return 0;
1884}
1885
Takashi Iwai98274f02005-11-17 14:52:34 +01001886static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001887{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001888 unsigned char buf[128]; /* this buffer is designed to match the MIDI
1889 * input FIFO size
1890 */
Takashi Iwai763f3562005-06-03 11:25:34 +02001891 unsigned long flags;
1892 int n_pending;
1893 int i;
1894
1895 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001896 n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id);
1897 if (n_pending > 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001898 if (hmidi->input) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001899 if (n_pending > (int)sizeof (buf))
Takashi Iwai763f3562005-06-03 11:25:34 +02001900 n_pending = sizeof (buf);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001901 for (i = 0; i < n_pending; ++i)
1902 buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm,
1903 hmidi->id);
1904 if (n_pending)
1905 snd_rawmidi_receive (hmidi->input, buf,
1906 n_pending);
Takashi Iwai763f3562005-06-03 11:25:34 +02001907 } else {
1908 /* flush the MIDI input FIFO */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001909 while (n_pending--)
1910 snd_hdspm_midi_read_byte (hmidi->hdspm,
1911 hmidi->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02001912 }
1913 }
1914 hmidi->pending = 0;
Adrian Knothc0da0012011-06-12 17:26:17 +02001915 spin_unlock_irqrestore(&hmidi->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001916
Adrian Knothc0da0012011-06-12 17:26:17 +02001917 spin_lock_irqsave(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001918 hmidi->hdspm->control_register |= hmidi->ie;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001919 hdspm_write(hmidi->hdspm, HDSPM_controlRegister,
1920 hmidi->hdspm->control_register);
Adrian Knothc0da0012011-06-12 17:26:17 +02001921 spin_unlock_irqrestore(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001922
Takashi Iwai763f3562005-06-03 11:25:34 +02001923 return snd_hdspm_midi_output_write (hmidi);
1924}
1925
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001926static void
1927snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001928{
Takashi Iwai98274f02005-11-17 14:52:34 +01001929 struct hdspm *hdspm;
1930 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001931 unsigned long flags;
Takashi Iwai763f3562005-06-03 11:25:34 +02001932
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001933 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001934 hdspm = hmidi->hdspm;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001935
Takashi Iwai763f3562005-06-03 11:25:34 +02001936 spin_lock_irqsave (&hdspm->lock, flags);
1937 if (up) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001938 if (!(hdspm->control_register & hmidi->ie)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001939 snd_hdspm_flush_midi_input (hdspm, hmidi->id);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001940 hdspm->control_register |= hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001941 }
1942 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001943 hdspm->control_register &= ~hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001944 }
1945
1946 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1947 spin_unlock_irqrestore (&hdspm->lock, flags);
1948}
1949
1950static void snd_hdspm_midi_output_timer(unsigned long data)
1951{
Takashi Iwai98274f02005-11-17 14:52:34 +01001952 struct hdspm_midi *hmidi = (struct hdspm_midi *) data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001953 unsigned long flags;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001954
Takashi Iwai763f3562005-06-03 11:25:34 +02001955 snd_hdspm_midi_output_write(hmidi);
1956 spin_lock_irqsave (&hmidi->lock, flags);
1957
1958 /* this does not bump hmidi->istimer, because the
1959 kernel automatically removed the timer when it
1960 expired, and we are now adding it back, thus
Adrian Knoth0dca1792011-01-26 19:32:14 +01001961 leaving istimer wherever it was set before.
Takashi Iwai763f3562005-06-03 11:25:34 +02001962 */
1963
Takashi Iwai04018e12015-01-19 11:34:45 +01001964 if (hmidi->istimer)
1965 mod_timer(&hmidi->timer, 1 + jiffies);
Takashi Iwai763f3562005-06-03 11:25:34 +02001966
1967 spin_unlock_irqrestore (&hmidi->lock, flags);
1968}
1969
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001970static void
1971snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001972{
Takashi Iwai98274f02005-11-17 14:52:34 +01001973 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001974 unsigned long flags;
1975
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001976 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001977 spin_lock_irqsave (&hmidi->lock, flags);
1978 if (up) {
1979 if (!hmidi->istimer) {
Takashi Iwai04018e12015-01-19 11:34:45 +01001980 setup_timer(&hmidi->timer, snd_hdspm_midi_output_timer,
1981 (unsigned long) hmidi);
1982 mod_timer(&hmidi->timer, 1 + jiffies);
Takashi Iwai763f3562005-06-03 11:25:34 +02001983 hmidi->istimer++;
1984 }
1985 } else {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001986 if (hmidi->istimer && --hmidi->istimer <= 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02001987 del_timer (&hmidi->timer);
Takashi Iwai763f3562005-06-03 11:25:34 +02001988 }
1989 spin_unlock_irqrestore (&hmidi->lock, flags);
1990 if (up)
1991 snd_hdspm_midi_output_write(hmidi);
1992}
1993
Takashi Iwai98274f02005-11-17 14:52:34 +01001994static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001995{
Takashi Iwai98274f02005-11-17 14:52:34 +01001996 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001997
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001998 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001999 spin_lock_irq (&hmidi->lock);
2000 snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
2001 hmidi->input = substream;
2002 spin_unlock_irq (&hmidi->lock);
2003
2004 return 0;
2005}
2006
Takashi Iwai98274f02005-11-17 14:52:34 +01002007static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02002008{
Takashi Iwai98274f02005-11-17 14:52:34 +01002009 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02002010
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002011 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02002012 spin_lock_irq (&hmidi->lock);
2013 hmidi->output = substream;
2014 spin_unlock_irq (&hmidi->lock);
2015
2016 return 0;
2017}
2018
Takashi Iwai98274f02005-11-17 14:52:34 +01002019static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02002020{
Takashi Iwai98274f02005-11-17 14:52:34 +01002021 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02002022
2023 snd_hdspm_midi_input_trigger (substream, 0);
2024
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002025 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02002026 spin_lock_irq (&hmidi->lock);
2027 hmidi->input = NULL;
2028 spin_unlock_irq (&hmidi->lock);
2029
2030 return 0;
2031}
2032
Takashi Iwai98274f02005-11-17 14:52:34 +01002033static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02002034{
Takashi Iwai98274f02005-11-17 14:52:34 +01002035 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02002036
2037 snd_hdspm_midi_output_trigger (substream, 0);
2038
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002039 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02002040 spin_lock_irq (&hmidi->lock);
2041 hmidi->output = NULL;
2042 spin_unlock_irq (&hmidi->lock);
2043
2044 return 0;
2045}
2046
Takashi Iwai98274f02005-11-17 14:52:34 +01002047static struct snd_rawmidi_ops snd_hdspm_midi_output =
Takashi Iwai763f3562005-06-03 11:25:34 +02002048{
2049 .open = snd_hdspm_midi_output_open,
2050 .close = snd_hdspm_midi_output_close,
2051 .trigger = snd_hdspm_midi_output_trigger,
2052};
2053
Takashi Iwai98274f02005-11-17 14:52:34 +01002054static struct snd_rawmidi_ops snd_hdspm_midi_input =
Takashi Iwai763f3562005-06-03 11:25:34 +02002055{
2056 .open = snd_hdspm_midi_input_open,
2057 .close = snd_hdspm_midi_input_close,
2058 .trigger = snd_hdspm_midi_input_trigger,
2059};
2060
Bill Pembertone23e7a12012-12-06 12:35:10 -05002061static int snd_hdspm_create_midi(struct snd_card *card,
2062 struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02002063{
2064 int err;
2065 char buf[32];
2066
2067 hdspm->midi[id].id = id;
Takashi Iwai763f3562005-06-03 11:25:34 +02002068 hdspm->midi[id].hdspm = hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +02002069 spin_lock_init (&hdspm->midi[id].lock);
2070
Adrian Knoth0dca1792011-01-26 19:32:14 +01002071 if (0 == id) {
2072 if (MADIface == hdspm->io_type) {
2073 /* MIDI-over-MADI on HDSPe MADIface */
2074 hdspm->midi[0].dataIn = HDSPM_midiDataIn2;
2075 hdspm->midi[0].statusIn = HDSPM_midiStatusIn2;
2076 hdspm->midi[0].dataOut = HDSPM_midiDataOut2;
2077 hdspm->midi[0].statusOut = HDSPM_midiStatusOut2;
2078 hdspm->midi[0].ie = HDSPM_Midi2InterruptEnable;
2079 hdspm->midi[0].irq = HDSPM_midi2IRQPending;
2080 } else {
2081 hdspm->midi[0].dataIn = HDSPM_midiDataIn0;
2082 hdspm->midi[0].statusIn = HDSPM_midiStatusIn0;
2083 hdspm->midi[0].dataOut = HDSPM_midiDataOut0;
2084 hdspm->midi[0].statusOut = HDSPM_midiStatusOut0;
2085 hdspm->midi[0].ie = HDSPM_Midi0InterruptEnable;
2086 hdspm->midi[0].irq = HDSPM_midi0IRQPending;
2087 }
2088 } else if (1 == id) {
2089 hdspm->midi[1].dataIn = HDSPM_midiDataIn1;
2090 hdspm->midi[1].statusIn = HDSPM_midiStatusIn1;
2091 hdspm->midi[1].dataOut = HDSPM_midiDataOut1;
2092 hdspm->midi[1].statusOut = HDSPM_midiStatusOut1;
2093 hdspm->midi[1].ie = HDSPM_Midi1InterruptEnable;
2094 hdspm->midi[1].irq = HDSPM_midi1IRQPending;
2095 } else if ((2 == id) && (MADI == hdspm->io_type)) {
2096 /* MIDI-over-MADI on HDSPe MADI */
2097 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
2098 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
2099 hdspm->midi[2].dataOut = HDSPM_midiDataOut2;
2100 hdspm->midi[2].statusOut = HDSPM_midiStatusOut2;
2101 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
2102 hdspm->midi[2].irq = HDSPM_midi2IRQPending;
2103 } else if (2 == id) {
2104 /* TCO MTC, read only */
2105 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
2106 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
2107 hdspm->midi[2].dataOut = -1;
2108 hdspm->midi[2].statusOut = -1;
2109 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
2110 hdspm->midi[2].irq = HDSPM_midi2IRQPendingAES;
2111 } else if (3 == id) {
2112 /* TCO MTC on HDSPe MADI */
2113 hdspm->midi[3].dataIn = HDSPM_midiDataIn3;
2114 hdspm->midi[3].statusIn = HDSPM_midiStatusIn3;
2115 hdspm->midi[3].dataOut = -1;
2116 hdspm->midi[3].statusOut = -1;
2117 hdspm->midi[3].ie = HDSPM_Midi3InterruptEnable;
2118 hdspm->midi[3].irq = HDSPM_midi3IRQPending;
2119 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002120
Adrian Knoth0dca1792011-01-26 19:32:14 +01002121 if ((id < 2) || ((2 == id) && ((MADI == hdspm->io_type) ||
2122 (MADIface == hdspm->io_type)))) {
2123 if ((id == 0) && (MADIface == hdspm->io_type)) {
2124 sprintf(buf, "%s MIDIoverMADI", card->shortname);
2125 } else if ((id == 2) && (MADI == hdspm->io_type)) {
2126 sprintf(buf, "%s MIDIoverMADI", card->shortname);
2127 } else {
2128 sprintf(buf, "%s MIDI %d", card->shortname, id+1);
2129 }
2130 err = snd_rawmidi_new(card, buf, id, 1, 1,
2131 &hdspm->midi[id].rmidi);
2132 if (err < 0)
2133 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02002134
Adrian Knoth0dca1792011-01-26 19:32:14 +01002135 sprintf(hdspm->midi[id].rmidi->name, "%s MIDI %d",
2136 card->id, id+1);
2137 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
Takashi Iwai763f3562005-06-03 11:25:34 +02002138
Adrian Knoth0dca1792011-01-26 19:32:14 +01002139 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
2140 SNDRV_RAWMIDI_STREAM_OUTPUT,
2141 &snd_hdspm_midi_output);
2142 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
2143 SNDRV_RAWMIDI_STREAM_INPUT,
2144 &snd_hdspm_midi_input);
2145
2146 hdspm->midi[id].rmidi->info_flags |=
2147 SNDRV_RAWMIDI_INFO_OUTPUT |
2148 SNDRV_RAWMIDI_INFO_INPUT |
2149 SNDRV_RAWMIDI_INFO_DUPLEX;
2150 } else {
2151 /* TCO MTC, read only */
2152 sprintf(buf, "%s MTC %d", card->shortname, id+1);
2153 err = snd_rawmidi_new(card, buf, id, 1, 1,
2154 &hdspm->midi[id].rmidi);
2155 if (err < 0)
2156 return err;
2157
2158 sprintf(hdspm->midi[id].rmidi->name,
2159 "%s MTC %d", card->id, id+1);
2160 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
2161
2162 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
2163 SNDRV_RAWMIDI_STREAM_INPUT,
2164 &snd_hdspm_midi_input);
2165
2166 hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
2167 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002168
2169 return 0;
2170}
2171
2172
2173static void hdspm_midi_tasklet(unsigned long arg)
2174{
Takashi Iwai98274f02005-11-17 14:52:34 +01002175 struct hdspm *hdspm = (struct hdspm *)arg;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002176 int i = 0;
2177
2178 while (i < hdspm->midiPorts) {
2179 if (hdspm->midi[i].pending)
2180 snd_hdspm_midi_input_read(&hdspm->midi[i]);
2181
2182 i++;
2183 }
2184}
Takashi Iwai763f3562005-06-03 11:25:34 +02002185
2186
2187/*-----------------------------------------------------------------------------
2188 Status Interface
2189 ----------------------------------------------------------------------------*/
2190
2191/* get the system sample rate which is set */
2192
Adrian Knoth0dca1792011-01-26 19:32:14 +01002193
Adrian Knoth3f7bf912013-03-10 00:37:21 +01002194static inline int hdspm_get_pll_freq(struct hdspm *hdspm)
2195{
2196 unsigned int period, rate;
2197
2198 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
2199 rate = hdspm_calc_dds_value(hdspm, period);
2200
2201 return rate;
2202}
2203
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002204/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002205 * Calculate the real sample rate from the
2206 * current DDS value.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002207 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002208static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
2209{
Adrian Knoth3f7bf912013-03-10 00:37:21 +01002210 unsigned int rate;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002211
Adrian Knoth3f7bf912013-03-10 00:37:21 +01002212 rate = hdspm_get_pll_freq(hdspm);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002213
Adrian Knotha97bda72012-05-30 14:23:18 +02002214 if (rate > 207000) {
Adrian Knoth21a164d2012-10-19 17:42:23 +02002215 /* Unreasonable high sample rate as seen on PCI MADI cards. */
2216 if (0 == hdspm_system_clock_mode(hdspm)) {
2217 /* master mode, return internal sample rate */
2218 rate = hdspm->system_sample_rate;
2219 } else {
2220 /* slave mode, return external sample rate */
2221 rate = hdspm_external_sample_rate(hdspm);
Takashi Iwaic1099c32016-02-29 14:32:42 +01002222 if (!rate)
2223 rate = hdspm->system_sample_rate;
Adrian Knoth21a164d2012-10-19 17:42:23 +02002224 }
Adrian Knotha97bda72012-05-30 14:23:18 +02002225 }
2226
Adrian Knoth0dca1792011-01-26 19:32:14 +01002227 return rate;
2228}
2229
2230
Takashi Iwai763f3562005-06-03 11:25:34 +02002231#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02002232{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2233 .name = xname, \
2234 .index = xindex, \
2235 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2236 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2237 .info = snd_hdspm_info_system_sample_rate, \
2238 .put = snd_hdspm_put_system_sample_rate, \
2239 .get = snd_hdspm_get_system_sample_rate \
Takashi Iwai763f3562005-06-03 11:25:34 +02002240}
2241
Takashi Iwai98274f02005-11-17 14:52:34 +01002242static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
2243 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002244{
2245 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2246 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002247 uinfo->value.integer.min = 27000;
2248 uinfo->value.integer.max = 207000;
2249 uinfo->value.integer.step = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002250 return 0;
2251}
2252
Adrian Knoth0dca1792011-01-26 19:32:14 +01002253
Takashi Iwai98274f02005-11-17 14:52:34 +01002254static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
2255 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002256 ucontrol)
2257{
Takashi Iwai98274f02005-11-17 14:52:34 +01002258 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002259
Adrian Knoth0dca1792011-01-26 19:32:14 +01002260 ucontrol->value.integer.value[0] = hdspm_get_system_sample_rate(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002261 return 0;
2262}
2263
Adrian Knoth41285a92012-10-19 17:42:22 +02002264static int snd_hdspm_put_system_sample_rate(struct snd_kcontrol *kcontrol,
2265 struct snd_ctl_elem_value *
2266 ucontrol)
2267{
2268 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwaic1099c32016-02-29 14:32:42 +01002269 int rate = ucontrol->value.integer.value[0];
Adrian Knoth41285a92012-10-19 17:42:22 +02002270
Takashi Iwaic1099c32016-02-29 14:32:42 +01002271 if (rate < 27000 || rate > 207000)
2272 return -EINVAL;
Takashi Iwai537e4812016-02-29 14:25:16 +01002273 hdspm_set_dds_value(hdspm, ucontrol->value.integer.value[0]);
Adrian Knoth41285a92012-10-19 17:42:22 +02002274 return 0;
2275}
2276
Adrian Knoth0dca1792011-01-26 19:32:14 +01002277
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002278/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002279 * Returns the WordClock sample rate class for the given card.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002280 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002281static int hdspm_get_wc_sample_rate(struct hdspm *hdspm)
2282{
2283 int status;
2284
2285 switch (hdspm->io_type) {
2286 case RayDAT:
2287 case AIO:
2288 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2289 return (status >> 16) & 0xF;
2290 break;
Adrian Knotha57fea82013-07-05 11:28:11 +02002291 case AES32:
2292 status = hdspm_read(hdspm, HDSPM_statusRegister);
2293 return (status >> HDSPM_AES32_wcFreq_bit) & 0xF;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002294 default:
2295 break;
2296 }
2297
2298
2299 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002300}
2301
Adrian Knoth0dca1792011-01-26 19:32:14 +01002302
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002303/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002304 * Returns the TCO sample rate class for the given card.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002305 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002306static int hdspm_get_tco_sample_rate(struct hdspm *hdspm)
2307{
2308 int status;
2309
2310 if (hdspm->tco) {
2311 switch (hdspm->io_type) {
2312 case RayDAT:
2313 case AIO:
2314 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2315 return (status >> 20) & 0xF;
2316 break;
Adrian Knoth051c44f2013-07-05 11:28:12 +02002317 case AES32:
2318 status = hdspm_read(hdspm, HDSPM_statusRegister);
2319 return (status >> 1) & 0xF;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002320 default:
2321 break;
2322 }
2323 }
2324
2325 return 0;
2326}
2327
2328
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002329/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002330 * Returns the SYNC_IN sample rate class for the given card.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002331 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002332static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm)
2333{
2334 int status;
2335
2336 if (hdspm->tco) {
2337 switch (hdspm->io_type) {
2338 case RayDAT:
2339 case AIO:
2340 status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2341 return (status >> 12) & 0xF;
2342 break;
2343 default:
2344 break;
2345 }
2346 }
2347
2348 return 0;
2349}
2350
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002351/*
Adrian Knothd3c36ed2013-07-05 11:28:09 +02002352 * Returns the AES sample rate class for the given card.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002353 */
Adrian Knothd3c36ed2013-07-05 11:28:09 +02002354static int hdspm_get_aes_sample_rate(struct hdspm *hdspm, int index)
2355{
2356 int timecode;
2357
2358 switch (hdspm->io_type) {
2359 case AES32:
2360 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
2361 return (timecode >> (4*index)) & 0xF;
2362 break;
2363 default:
2364 break;
2365 }
2366 return 0;
2367}
Adrian Knoth0dca1792011-01-26 19:32:14 +01002368
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002369/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002370 * Returns the sample rate class for input source <idx> for
2371 * 'new style' cards like the AIO and RayDAT.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002372 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002373static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
2374{
2375 int status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2376
2377 return (status >> (idx*4)) & 0xF;
2378}
2379
Adrian Knoth8cea5712013-07-05 11:27:59 +02002380#define ENUMERATED_CTL_INFO(info, texts) \
Adrian Knoth38816542013-07-05 11:28:20 +02002381 snd_ctl_enum_info(info, 1, ARRAY_SIZE(texts), texts)
Adrian Knoth8cea5712013-07-05 11:27:59 +02002382
Adrian Knoth0dca1792011-01-26 19:32:14 +01002383
Adrian Knoth23361422013-07-05 11:28:17 +02002384/* Helper function to query the external sample rate and return the
2385 * corresponding enum to be returned to userspace.
2386 */
2387static int hdspm_external_rate_to_enum(struct hdspm *hdspm)
2388{
2389 int rate = hdspm_external_sample_rate(hdspm);
2390 int i, selected_rate = 0;
2391 for (i = 1; i < 10; i++)
2392 if (HDSPM_bit2freq(i) == rate) {
2393 selected_rate = i;
2394 break;
2395 }
2396 return selected_rate;
2397}
2398
Adrian Knoth0dca1792011-01-26 19:32:14 +01002399
2400#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
2401{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2402 .name = xname, \
2403 .private_value = xindex, \
2404 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2405 .info = snd_hdspm_info_autosync_sample_rate, \
2406 .get = snd_hdspm_get_autosync_sample_rate \
2407}
2408
2409
Takashi Iwai98274f02005-11-17 14:52:34 +01002410static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2411 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002412{
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01002413 ENUMERATED_CTL_INFO(uinfo, texts_freq);
Takashi Iwai763f3562005-06-03 11:25:34 +02002414 return 0;
2415}
2416
Adrian Knoth0dca1792011-01-26 19:32:14 +01002417
Takashi Iwai98274f02005-11-17 14:52:34 +01002418static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2419 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002420 ucontrol)
2421{
Takashi Iwai98274f02005-11-17 14:52:34 +01002422 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002423
Adrian Knoth0dca1792011-01-26 19:32:14 +01002424 switch (hdspm->io_type) {
2425 case RayDAT:
2426 switch (kcontrol->private_value) {
2427 case 0:
2428 ucontrol->value.enumerated.item[0] =
2429 hdspm_get_wc_sample_rate(hdspm);
2430 break;
2431 case 7:
2432 ucontrol->value.enumerated.item[0] =
2433 hdspm_get_tco_sample_rate(hdspm);
2434 break;
2435 case 8:
2436 ucontrol->value.enumerated.item[0] =
2437 hdspm_get_sync_in_sample_rate(hdspm);
2438 break;
2439 default:
2440 ucontrol->value.enumerated.item[0] =
2441 hdspm_get_s1_sample_rate(hdspm,
2442 kcontrol->private_value-1);
2443 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002444 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002445
Adrian Knoth0dca1792011-01-26 19:32:14 +01002446 case AIO:
2447 switch (kcontrol->private_value) {
2448 case 0: /* WC */
2449 ucontrol->value.enumerated.item[0] =
2450 hdspm_get_wc_sample_rate(hdspm);
2451 break;
2452 case 4: /* TCO */
2453 ucontrol->value.enumerated.item[0] =
2454 hdspm_get_tco_sample_rate(hdspm);
2455 break;
2456 case 5: /* SYNC_IN */
2457 ucontrol->value.enumerated.item[0] =
2458 hdspm_get_sync_in_sample_rate(hdspm);
2459 break;
2460 default:
2461 ucontrol->value.enumerated.item[0] =
2462 hdspm_get_s1_sample_rate(hdspm,
Adrian Knoth1cb7dbf2013-07-05 11:28:03 +02002463 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002464 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002465 break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002466
2467 case AES32:
2468
2469 switch (kcontrol->private_value) {
2470 case 0: /* WC */
2471 ucontrol->value.enumerated.item[0] =
2472 hdspm_get_wc_sample_rate(hdspm);
2473 break;
2474 case 9: /* TCO */
2475 ucontrol->value.enumerated.item[0] =
2476 hdspm_get_tco_sample_rate(hdspm);
2477 break;
2478 case 10: /* SYNC_IN */
2479 ucontrol->value.enumerated.item[0] =
2480 hdspm_get_sync_in_sample_rate(hdspm);
2481 break;
Adrian Knoth2d63ec32013-07-05 11:28:18 +02002482 case 11: /* External Rate */
2483 ucontrol->value.enumerated.item[0] =
2484 hdspm_external_rate_to_enum(hdspm);
2485 break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002486 default: /* AES1 to AES8 */
2487 ucontrol->value.enumerated.item[0] =
Adrian Knoth2d63ec32013-07-05 11:28:18 +02002488 hdspm_get_aes_sample_rate(hdspm,
2489 kcontrol->private_value -
2490 HDSPM_AES32_AUTOSYNC_FROM_AES1);
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002491 break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002492 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002493 break;
Adrian Knothb8812c52012-10-19 17:42:26 +02002494
2495 case MADI:
2496 case MADIface:
Adrian Knoth23361422013-07-05 11:28:17 +02002497 ucontrol->value.enumerated.item[0] =
2498 hdspm_external_rate_to_enum(hdspm);
Adrian Knothb8812c52012-10-19 17:42:26 +02002499 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002500 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002501 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002502 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002503
Takashi Iwai763f3562005-06-03 11:25:34 +02002504 return 0;
2505}
2506
Adrian Knoth0dca1792011-01-26 19:32:14 +01002507
Takashi Iwai763f3562005-06-03 11:25:34 +02002508#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002509{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2510 .name = xname, \
2511 .index = xindex, \
2512 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2513 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2514 .info = snd_hdspm_info_system_clock_mode, \
2515 .get = snd_hdspm_get_system_clock_mode, \
2516 .put = snd_hdspm_put_system_clock_mode, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002517}
2518
2519
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002520/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002521 * Returns the system clock mode for the given card.
2522 * @returns 0 - master, 1 - slave
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002523 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002524static int hdspm_system_clock_mode(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002525{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002526 switch (hdspm->io_type) {
2527 case AIO:
2528 case RayDAT:
2529 if (hdspm->settings_register & HDSPM_c0Master)
2530 return 0;
2531 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002532
Adrian Knoth0dca1792011-01-26 19:32:14 +01002533 default:
2534 if (hdspm->control_register & HDSPM_ClockModeMaster)
2535 return 0;
2536 }
2537
Takashi Iwai763f3562005-06-03 11:25:34 +02002538 return 1;
2539}
2540
Adrian Knoth0dca1792011-01-26 19:32:14 +01002541
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002542/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002543 * Sets the system clock mode.
2544 * @param mode 0 - master, 1 - slave
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002545 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002546static void hdspm_set_system_clock_mode(struct hdspm *hdspm, int mode)
2547{
Adrian Knoth34be7eb2013-07-05 11:27:56 +02002548 hdspm_set_toggle_setting(hdspm,
2549 (hdspm_is_raydat_or_aio(hdspm)) ?
2550 HDSPM_c0Master : HDSPM_ClockModeMaster,
2551 (0 == mode));
Adrian Knoth0dca1792011-01-26 19:32:14 +01002552}
2553
2554
Takashi Iwai98274f02005-11-17 14:52:34 +01002555static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
2556 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002557{
Adrian Knoth38816542013-07-05 11:28:20 +02002558 static const char *const texts[] = { "Master", "AutoSync" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01002559 ENUMERATED_CTL_INFO(uinfo, texts);
Takashi Iwai763f3562005-06-03 11:25:34 +02002560 return 0;
2561}
2562
Takashi Iwai98274f02005-11-17 14:52:34 +01002563static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
2564 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002565{
Takashi Iwai98274f02005-11-17 14:52:34 +01002566 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002567
Adrian Knoth0dca1792011-01-26 19:32:14 +01002568 ucontrol->value.enumerated.item[0] = hdspm_system_clock_mode(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002569 return 0;
2570}
2571
Adrian Knoth0dca1792011-01-26 19:32:14 +01002572static int snd_hdspm_put_system_clock_mode(struct snd_kcontrol *kcontrol,
2573 struct snd_ctl_elem_value *ucontrol)
2574{
2575 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2576 int val;
2577
2578 if (!snd_hdspm_use_is_exclusive(hdspm))
2579 return -EBUSY;
2580
2581 val = ucontrol->value.enumerated.item[0];
2582 if (val < 0)
2583 val = 0;
2584 else if (val > 1)
2585 val = 1;
2586
2587 hdspm_set_system_clock_mode(hdspm, val);
2588
2589 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002590}
2591
Adrian Knoth0dca1792011-01-26 19:32:14 +01002592
2593#define HDSPM_INTERNAL_CLOCK(xname, xindex) \
2594{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2595 .name = xname, \
2596 .index = xindex, \
2597 .info = snd_hdspm_info_clock_source, \
2598 .get = snd_hdspm_get_clock_source, \
2599 .put = snd_hdspm_put_clock_source \
2600}
2601
2602
Takashi Iwai98274f02005-11-17 14:52:34 +01002603static int hdspm_clock_source(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002604{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002605 switch (hdspm->system_sample_rate) {
2606 case 32000: return 0;
2607 case 44100: return 1;
2608 case 48000: return 2;
2609 case 64000: return 3;
2610 case 88200: return 4;
2611 case 96000: return 5;
2612 case 128000: return 6;
2613 case 176400: return 7;
2614 case 192000: return 8;
Takashi Iwai763f3562005-06-03 11:25:34 +02002615 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002616
2617 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002618}
2619
Takashi Iwai98274f02005-11-17 14:52:34 +01002620static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
Takashi Iwai763f3562005-06-03 11:25:34 +02002621{
2622 int rate;
2623 switch (mode) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002624 case 0:
2625 rate = 32000; break;
2626 case 1:
2627 rate = 44100; break;
2628 case 2:
2629 rate = 48000; break;
2630 case 3:
2631 rate = 64000; break;
2632 case 4:
2633 rate = 88200; break;
2634 case 5:
2635 rate = 96000; break;
2636 case 6:
2637 rate = 128000; break;
2638 case 7:
2639 rate = 176400; break;
2640 case 8:
2641 rate = 192000; break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002642 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002643 rate = 48000;
Takashi Iwai763f3562005-06-03 11:25:34 +02002644 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002645 hdspm_set_rate(hdspm, rate, 1);
2646 return 0;
2647}
2648
Takashi Iwai98274f02005-11-17 14:52:34 +01002649static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
2650 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002651{
Takashi Iwaic69a6372014-10-20 18:19:41 +02002652 return snd_ctl_enum_info(uinfo, 1, 9, texts_freq + 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02002653}
2654
Takashi Iwai98274f02005-11-17 14:52:34 +01002655static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
2656 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002657{
Takashi Iwai98274f02005-11-17 14:52:34 +01002658 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002659
2660 ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
2661 return 0;
2662}
2663
Takashi Iwai98274f02005-11-17 14:52:34 +01002664static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
2665 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002666{
Takashi Iwai98274f02005-11-17 14:52:34 +01002667 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002668 int change;
2669 int val;
2670
2671 if (!snd_hdspm_use_is_exclusive(hdspm))
2672 return -EBUSY;
2673 val = ucontrol->value.enumerated.item[0];
2674 if (val < 0)
2675 val = 0;
Remy Bruno65345992007-08-31 12:21:08 +02002676 if (val > 9)
2677 val = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002678 spin_lock_irq(&hdspm->lock);
2679 if (val != hdspm_clock_source(hdspm))
2680 change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
2681 else
2682 change = 0;
2683 spin_unlock_irq(&hdspm->lock);
2684 return change;
2685}
2686
Adrian Knoth0dca1792011-01-26 19:32:14 +01002687
Takashi Iwai763f3562005-06-03 11:25:34 +02002688#define HDSPM_PREF_SYNC_REF(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02002689{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002690 .name = xname, \
2691 .index = xindex, \
2692 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2693 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2694 .info = snd_hdspm_info_pref_sync_ref, \
2695 .get = snd_hdspm_get_pref_sync_ref, \
2696 .put = snd_hdspm_put_pref_sync_ref \
Takashi Iwai763f3562005-06-03 11:25:34 +02002697}
2698
Adrian Knoth0dca1792011-01-26 19:32:14 +01002699
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002700/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002701 * Returns the current preferred sync reference setting.
2702 * The semantics of the return value are depending on the
2703 * card, please see the comments for clarification.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002704 */
Takashi Iwai98274f02005-11-17 14:52:34 +01002705static int hdspm_pref_sync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002706{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002707 switch (hdspm->io_type) {
2708 case AES32:
Remy Bruno3cee5a62006-10-16 12:46:32 +02002709 switch (hdspm->control_register & HDSPM_SyncRefMask) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002710 case 0: return 0; /* WC */
2711 case HDSPM_SyncRef0: return 1; /* AES 1 */
2712 case HDSPM_SyncRef1: return 2; /* AES 2 */
2713 case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; /* AES 3 */
2714 case HDSPM_SyncRef2: return 4; /* AES 4 */
2715 case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; /* AES 5 */
2716 case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; /* AES 6 */
2717 case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0:
2718 return 7; /* AES 7 */
2719 case HDSPM_SyncRef3: return 8; /* AES 8 */
2720 case HDSPM_SyncRef3+HDSPM_SyncRef0: return 9; /* TCO */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002721 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002722 break;
2723
2724 case MADI:
2725 case MADIface:
2726 if (hdspm->tco) {
2727 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2728 case 0: return 0; /* WC */
2729 case HDSPM_SyncRef0: return 1; /* MADI */
2730 case HDSPM_SyncRef1: return 2; /* TCO */
2731 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2732 return 3; /* SYNC_IN */
2733 }
2734 } else {
2735 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2736 case 0: return 0; /* WC */
2737 case HDSPM_SyncRef0: return 1; /* MADI */
2738 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2739 return 2; /* SYNC_IN */
2740 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02002741 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002742 break;
2743
2744 case RayDAT:
2745 if (hdspm->tco) {
2746 switch ((hdspm->settings_register &
2747 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2748 case 0: return 0; /* WC */
2749 case 3: return 1; /* ADAT 1 */
2750 case 4: return 2; /* ADAT 2 */
2751 case 5: return 3; /* ADAT 3 */
2752 case 6: return 4; /* ADAT 4 */
2753 case 1: return 5; /* AES */
2754 case 2: return 6; /* SPDIF */
2755 case 9: return 7; /* TCO */
2756 case 10: return 8; /* SYNC_IN */
2757 }
2758 } else {
2759 switch ((hdspm->settings_register &
2760 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2761 case 0: return 0; /* WC */
2762 case 3: return 1; /* ADAT 1 */
2763 case 4: return 2; /* ADAT 2 */
2764 case 5: return 3; /* ADAT 3 */
2765 case 6: return 4; /* ADAT 4 */
2766 case 1: return 5; /* AES */
2767 case 2: return 6; /* SPDIF */
2768 case 10: return 7; /* SYNC_IN */
2769 }
2770 }
2771
2772 break;
2773
2774 case AIO:
2775 if (hdspm->tco) {
2776 switch ((hdspm->settings_register &
2777 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2778 case 0: return 0; /* WC */
2779 case 3: return 1; /* ADAT */
2780 case 1: return 2; /* AES */
2781 case 2: return 3; /* SPDIF */
2782 case 9: return 4; /* TCO */
2783 case 10: return 5; /* SYNC_IN */
2784 }
2785 } else {
2786 switch ((hdspm->settings_register &
2787 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2788 case 0: return 0; /* WC */
2789 case 3: return 1; /* ADAT */
2790 case 1: return 2; /* AES */
2791 case 2: return 3; /* SPDIF */
2792 case 10: return 4; /* SYNC_IN */
2793 }
2794 }
2795
2796 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002797 }
2798
Adrian Knoth0dca1792011-01-26 19:32:14 +01002799 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002800}
2801
Adrian Knoth0dca1792011-01-26 19:32:14 +01002802
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002803/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002804 * Set the preferred sync reference to <pref>. The semantics
2805 * of <pref> are depending on the card type, see the comments
2806 * for clarification.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002807 */
Takashi Iwai98274f02005-11-17 14:52:34 +01002808static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
Takashi Iwai763f3562005-06-03 11:25:34 +02002809{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002810 int p = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002811
Adrian Knoth0dca1792011-01-26 19:32:14 +01002812 switch (hdspm->io_type) {
2813 case AES32:
2814 hdspm->control_register &= ~HDSPM_SyncRefMask;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002815 switch (pref) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002816 case 0: /* WC */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002817 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002818 case 1: /* AES 1 */
2819 hdspm->control_register |= HDSPM_SyncRef0;
2820 break;
2821 case 2: /* AES 2 */
2822 hdspm->control_register |= HDSPM_SyncRef1;
2823 break;
2824 case 3: /* AES 3 */
2825 hdspm->control_register |=
2826 HDSPM_SyncRef1+HDSPM_SyncRef0;
2827 break;
2828 case 4: /* AES 4 */
2829 hdspm->control_register |= HDSPM_SyncRef2;
2830 break;
2831 case 5: /* AES 5 */
2832 hdspm->control_register |=
2833 HDSPM_SyncRef2+HDSPM_SyncRef0;
2834 break;
2835 case 6: /* AES 6 */
2836 hdspm->control_register |=
2837 HDSPM_SyncRef2+HDSPM_SyncRef1;
2838 break;
2839 case 7: /* AES 7 */
2840 hdspm->control_register |=
2841 HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
2842 break;
2843 case 8: /* AES 8 */
2844 hdspm->control_register |= HDSPM_SyncRef3;
2845 break;
2846 case 9: /* TCO */
2847 hdspm->control_register |=
2848 HDSPM_SyncRef3+HDSPM_SyncRef0;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002849 break;
2850 default:
2851 return -1;
2852 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002853
2854 break;
2855
2856 case MADI:
2857 case MADIface:
2858 hdspm->control_register &= ~HDSPM_SyncRefMask;
2859 if (hdspm->tco) {
2860 switch (pref) {
2861 case 0: /* WC */
2862 break;
2863 case 1: /* MADI */
2864 hdspm->control_register |= HDSPM_SyncRef0;
2865 break;
2866 case 2: /* TCO */
2867 hdspm->control_register |= HDSPM_SyncRef1;
2868 break;
2869 case 3: /* SYNC_IN */
2870 hdspm->control_register |=
2871 HDSPM_SyncRef0+HDSPM_SyncRef1;
2872 break;
2873 default:
2874 return -1;
2875 }
2876 } else {
2877 switch (pref) {
2878 case 0: /* WC */
2879 break;
2880 case 1: /* MADI */
2881 hdspm->control_register |= HDSPM_SyncRef0;
2882 break;
2883 case 2: /* SYNC_IN */
2884 hdspm->control_register |=
2885 HDSPM_SyncRef0+HDSPM_SyncRef1;
2886 break;
2887 default:
2888 return -1;
2889 }
2890 }
2891
2892 break;
2893
2894 case RayDAT:
2895 if (hdspm->tco) {
2896 switch (pref) {
2897 case 0: p = 0; break; /* WC */
2898 case 1: p = 3; break; /* ADAT 1 */
2899 case 2: p = 4; break; /* ADAT 2 */
2900 case 3: p = 5; break; /* ADAT 3 */
2901 case 4: p = 6; break; /* ADAT 4 */
2902 case 5: p = 1; break; /* AES */
2903 case 6: p = 2; break; /* SPDIF */
2904 case 7: p = 9; break; /* TCO */
2905 case 8: p = 10; break; /* SYNC_IN */
2906 default: return -1;
2907 }
2908 } else {
2909 switch (pref) {
2910 case 0: p = 0; break; /* WC */
2911 case 1: p = 3; break; /* ADAT 1 */
2912 case 2: p = 4; break; /* ADAT 2 */
2913 case 3: p = 5; break; /* ADAT 3 */
2914 case 4: p = 6; break; /* ADAT 4 */
2915 case 5: p = 1; break; /* AES */
2916 case 6: p = 2; break; /* SPDIF */
2917 case 7: p = 10; break; /* SYNC_IN */
2918 default: return -1;
2919 }
2920 }
2921 break;
2922
2923 case AIO:
2924 if (hdspm->tco) {
2925 switch (pref) {
2926 case 0: p = 0; break; /* WC */
2927 case 1: p = 3; break; /* ADAT */
2928 case 2: p = 1; break; /* AES */
2929 case 3: p = 2; break; /* SPDIF */
2930 case 4: p = 9; break; /* TCO */
2931 case 5: p = 10; break; /* SYNC_IN */
2932 default: return -1;
2933 }
2934 } else {
2935 switch (pref) {
2936 case 0: p = 0; break; /* WC */
2937 case 1: p = 3; break; /* ADAT */
2938 case 2: p = 1; break; /* AES */
2939 case 3: p = 2; break; /* SPDIF */
2940 case 4: p = 10; break; /* SYNC_IN */
2941 default: return -1;
2942 }
2943 }
2944 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002945 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002946
2947 switch (hdspm->io_type) {
2948 case RayDAT:
2949 case AIO:
2950 hdspm->settings_register &= ~HDSPM_c0_SyncRefMask;
2951 hdspm->settings_register |= HDSPM_c0_SyncRef0 * p;
2952 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2953 break;
2954
2955 case MADI:
2956 case MADIface:
2957 case AES32:
2958 hdspm_write(hdspm, HDSPM_controlRegister,
2959 hdspm->control_register);
2960 }
2961
Takashi Iwai763f3562005-06-03 11:25:34 +02002962 return 0;
2963}
2964
Adrian Knoth0dca1792011-01-26 19:32:14 +01002965
Takashi Iwai98274f02005-11-17 14:52:34 +01002966static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
2967 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002968{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002969 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002970
Adrian Knotheb0d4db2013-07-05 11:28:21 +02002971 snd_ctl_enum_info(uinfo, 1, hdspm->texts_autosync_items, hdspm->texts_autosync);
Remy Bruno3cee5a62006-10-16 12:46:32 +02002972
Takashi Iwai763f3562005-06-03 11:25:34 +02002973 return 0;
2974}
2975
Takashi Iwai98274f02005-11-17 14:52:34 +01002976static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
2977 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002978{
Takashi Iwai98274f02005-11-17 14:52:34 +01002979 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002980 int psf = hdspm_pref_sync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002981
Adrian Knoth0dca1792011-01-26 19:32:14 +01002982 if (psf >= 0) {
2983 ucontrol->value.enumerated.item[0] = psf;
2984 return 0;
2985 }
2986
2987 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002988}
2989
Takashi Iwai98274f02005-11-17 14:52:34 +01002990static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
2991 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002992{
Takashi Iwai98274f02005-11-17 14:52:34 +01002993 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002994 int val, change = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002995
2996 if (!snd_hdspm_use_is_exclusive(hdspm))
2997 return -EBUSY;
2998
Adrian Knoth0dca1792011-01-26 19:32:14 +01002999 val = ucontrol->value.enumerated.item[0];
3000
3001 if (val < 0)
3002 val = 0;
3003 else if (val >= hdspm->texts_autosync_items)
3004 val = hdspm->texts_autosync_items-1;
Takashi Iwai763f3562005-06-03 11:25:34 +02003005
3006 spin_lock_irq(&hdspm->lock);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003007 if (val != hdspm_pref_sync_ref(hdspm))
3008 change = (0 == hdspm_set_pref_sync_ref(hdspm, val)) ? 1 : 0;
3009
Takashi Iwai763f3562005-06-03 11:25:34 +02003010 spin_unlock_irq(&hdspm->lock);
3011 return change;
3012}
3013
Adrian Knoth0dca1792011-01-26 19:32:14 +01003014
Takashi Iwai763f3562005-06-03 11:25:34 +02003015#define HDSPM_AUTOSYNC_REF(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003016{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3017 .name = xname, \
3018 .index = xindex, \
3019 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
3020 .info = snd_hdspm_info_autosync_ref, \
3021 .get = snd_hdspm_get_autosync_ref, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003022}
3023
Adrian Knoth0dca1792011-01-26 19:32:14 +01003024static int hdspm_autosync_ref(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003025{
Adrian Knoth2d60fc72013-07-05 11:28:15 +02003026 /* This looks at the autosync selected sync reference */
Adrian Knoth0dca1792011-01-26 19:32:14 +01003027 if (AES32 == hdspm->io_type) {
Takashi Iwai763f3562005-06-03 11:25:34 +02003028
Adrian Knoth2d60fc72013-07-05 11:28:15 +02003029 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
3030 unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) & 0xF;
3031 if ((syncref >= HDSPM_AES32_AUTOSYNC_FROM_WORD) &&
3032 (syncref <= HDSPM_AES32_AUTOSYNC_FROM_SYNC_IN)) {
3033 return syncref;
3034 }
3035 return HDSPM_AES32_AUTOSYNC_FROM_NONE;
3036
3037 } else if (MADI == hdspm->io_type) {
3038
3039 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003040 switch (status2 & HDSPM_SelSyncRefMask) {
3041 case HDSPM_SelSyncRef_WORD:
3042 return HDSPM_AUTOSYNC_FROM_WORD;
3043 case HDSPM_SelSyncRef_MADI:
3044 return HDSPM_AUTOSYNC_FROM_MADI;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003045 case HDSPM_SelSyncRef_TCO:
3046 return HDSPM_AUTOSYNC_FROM_TCO;
3047 case HDSPM_SelSyncRef_SyncIn:
3048 return HDSPM_AUTOSYNC_FROM_SYNC_IN;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003049 case HDSPM_SelSyncRef_NVALID:
3050 return HDSPM_AUTOSYNC_FROM_NONE;
3051 default:
Adrian Knothe71b95a2013-07-05 11:28:06 +02003052 return HDSPM_AUTOSYNC_FROM_NONE;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003053 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003054
Takashi Iwai763f3562005-06-03 11:25:34 +02003055 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01003056 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02003057}
3058
Adrian Knoth0dca1792011-01-26 19:32:14 +01003059
Takashi Iwai98274f02005-11-17 14:52:34 +01003060static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
3061 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003062{
Remy Bruno3cee5a62006-10-16 12:46:32 +02003063 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003064
Adrian Knoth0dca1792011-01-26 19:32:14 +01003065 if (AES32 == hdspm->io_type) {
Adrian Knoth04659f92013-07-05 11:28:22 +02003066 static const char *const texts[] = { "WordClock", "AES1", "AES2", "AES3",
Adrian Knothdb2d1a92013-07-05 11:28:08 +02003067 "AES4", "AES5", "AES6", "AES7", "AES8", "TCO", "Sync In", "None"};
Remy Bruno3cee5a62006-10-16 12:46:32 +02003068
Adrian Knoth04659f92013-07-05 11:28:22 +02003069 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003070 } else if (MADI == hdspm->io_type) {
Adrian Knoth04659f92013-07-05 11:28:22 +02003071 static const char *const texts[] = {"Word Clock", "MADI", "TCO",
Adrian Knoth0dca1792011-01-26 19:32:14 +01003072 "Sync In", "None" };
Remy Bruno3cee5a62006-10-16 12:46:32 +02003073
Adrian Knoth04659f92013-07-05 11:28:22 +02003074 ENUMERATED_CTL_INFO(uinfo, texts);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003075 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003076 return 0;
3077}
3078
Takashi Iwai98274f02005-11-17 14:52:34 +01003079static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
3080 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003081{
Takashi Iwai98274f02005-11-17 14:52:34 +01003082 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003083
Remy Bruno65345992007-08-31 12:21:08 +02003084 ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02003085 return 0;
3086}
3087
Adrian Knothf99c7882013-03-10 00:37:26 +01003088
3089
3090#define HDSPM_TCO_VIDEO_INPUT_FORMAT(xname, xindex) \
3091{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3092 .name = xname, \
3093 .access = SNDRV_CTL_ELEM_ACCESS_READ |\
3094 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3095 .info = snd_hdspm_info_tco_video_input_format, \
3096 .get = snd_hdspm_get_tco_video_input_format, \
3097}
3098
3099static int snd_hdspm_info_tco_video_input_format(struct snd_kcontrol *kcontrol,
3100 struct snd_ctl_elem_info *uinfo)
3101{
Adrian Knoth38816542013-07-05 11:28:20 +02003102 static const char *const texts[] = {"No video", "NTSC", "PAL"};
Adrian Knothf99c7882013-03-10 00:37:26 +01003103 ENUMERATED_CTL_INFO(uinfo, texts);
3104 return 0;
3105}
3106
3107static int snd_hdspm_get_tco_video_input_format(struct snd_kcontrol *kcontrol,
3108 struct snd_ctl_elem_value *ucontrol)
3109{
3110 u32 status;
3111 int ret = 0;
3112
3113 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3114 status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
3115 switch (status & (HDSPM_TCO1_Video_Input_Format_NTSC |
3116 HDSPM_TCO1_Video_Input_Format_PAL)) {
3117 case HDSPM_TCO1_Video_Input_Format_NTSC:
3118 /* ntsc */
3119 ret = 1;
3120 break;
3121 case HDSPM_TCO1_Video_Input_Format_PAL:
3122 /* pal */
3123 ret = 2;
3124 break;
3125 default:
3126 /* no video */
3127 ret = 0;
3128 break;
3129 }
3130 ucontrol->value.enumerated.item[0] = ret;
3131 return 0;
3132}
3133
3134
3135
3136#define HDSPM_TCO_LTC_FRAMES(xname, xindex) \
3137{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3138 .name = xname, \
3139 .access = SNDRV_CTL_ELEM_ACCESS_READ |\
3140 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3141 .info = snd_hdspm_info_tco_ltc_frames, \
3142 .get = snd_hdspm_get_tco_ltc_frames, \
3143}
3144
3145static int snd_hdspm_info_tco_ltc_frames(struct snd_kcontrol *kcontrol,
3146 struct snd_ctl_elem_info *uinfo)
3147{
Adrian Knoth38816542013-07-05 11:28:20 +02003148 static const char *const texts[] = {"No lock", "24 fps", "25 fps", "29.97 fps",
Adrian Knothf99c7882013-03-10 00:37:26 +01003149 "30 fps"};
3150 ENUMERATED_CTL_INFO(uinfo, texts);
3151 return 0;
3152}
3153
3154static int hdspm_tco_ltc_frames(struct hdspm *hdspm)
3155{
3156 u32 status;
3157 int ret = 0;
3158
3159 status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
3160 if (status & HDSPM_TCO1_LTC_Input_valid) {
3161 switch (status & (HDSPM_TCO1_LTC_Format_LSB |
3162 HDSPM_TCO1_LTC_Format_MSB)) {
3163 case 0:
3164 /* 24 fps */
Adrian Knoth1568b882013-08-19 17:20:31 +02003165 ret = fps_24;
Adrian Knothf99c7882013-03-10 00:37:26 +01003166 break;
3167 case HDSPM_TCO1_LTC_Format_LSB:
3168 /* 25 fps */
Adrian Knoth1568b882013-08-19 17:20:31 +02003169 ret = fps_25;
Adrian Knothf99c7882013-03-10 00:37:26 +01003170 break;
3171 case HDSPM_TCO1_LTC_Format_MSB:
Adrian Knoth1568b882013-08-19 17:20:31 +02003172 /* 29.97 fps */
3173 ret = fps_2997;
Adrian Knothf99c7882013-03-10 00:37:26 +01003174 break;
3175 default:
3176 /* 30 fps */
Adrian Knoth1568b882013-08-19 17:20:31 +02003177 ret = fps_30;
Adrian Knothf99c7882013-03-10 00:37:26 +01003178 break;
3179 }
3180 }
3181
3182 return ret;
3183}
3184
3185static int snd_hdspm_get_tco_ltc_frames(struct snd_kcontrol *kcontrol,
3186 struct snd_ctl_elem_value *ucontrol)
3187{
3188 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3189
3190 ucontrol->value.enumerated.item[0] = hdspm_tco_ltc_frames(hdspm);
3191 return 0;
3192}
3193
Adrian Knothbf0ff872012-12-03 14:55:49 +01003194#define HDSPM_TOGGLE_SETTING(xname, xindex) \
3195{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3196 .name = xname, \
3197 .private_value = xindex, \
3198 .info = snd_hdspm_info_toggle_setting, \
3199 .get = snd_hdspm_get_toggle_setting, \
3200 .put = snd_hdspm_put_toggle_setting \
3201}
3202
3203static int hdspm_toggle_setting(struct hdspm *hdspm, u32 regmask)
3204{
Adrian Knothce13f3f2013-07-05 11:27:55 +02003205 u32 reg;
3206
3207 if (hdspm_is_raydat_or_aio(hdspm))
3208 reg = hdspm->settings_register;
3209 else
3210 reg = hdspm->control_register;
3211
3212 return (reg & regmask) ? 1 : 0;
Adrian Knothbf0ff872012-12-03 14:55:49 +01003213}
3214
3215static int hdspm_set_toggle_setting(struct hdspm *hdspm, u32 regmask, int out)
3216{
Adrian Knothce13f3f2013-07-05 11:27:55 +02003217 u32 *reg;
3218 u32 target_reg;
3219
3220 if (hdspm_is_raydat_or_aio(hdspm)) {
3221 reg = &(hdspm->settings_register);
3222 target_reg = HDSPM_WR_SETTINGS;
3223 } else {
3224 reg = &(hdspm->control_register);
3225 target_reg = HDSPM_controlRegister;
3226 }
3227
Adrian Knothbf0ff872012-12-03 14:55:49 +01003228 if (out)
Adrian Knothce13f3f2013-07-05 11:27:55 +02003229 *reg |= regmask;
Adrian Knothbf0ff872012-12-03 14:55:49 +01003230 else
Adrian Knothce13f3f2013-07-05 11:27:55 +02003231 *reg &= ~regmask;
3232
3233 hdspm_write(hdspm, target_reg, *reg);
Adrian Knothbf0ff872012-12-03 14:55:49 +01003234
3235 return 0;
3236}
3237
3238#define snd_hdspm_info_toggle_setting snd_ctl_boolean_mono_info
3239
3240static int snd_hdspm_get_toggle_setting(struct snd_kcontrol *kcontrol,
3241 struct snd_ctl_elem_value *ucontrol)
3242{
3243 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3244 u32 regmask = kcontrol->private_value;
3245
3246 spin_lock_irq(&hdspm->lock);
3247 ucontrol->value.integer.value[0] = hdspm_toggle_setting(hdspm, regmask);
3248 spin_unlock_irq(&hdspm->lock);
3249 return 0;
3250}
3251
3252static int snd_hdspm_put_toggle_setting(struct snd_kcontrol *kcontrol,
3253 struct snd_ctl_elem_value *ucontrol)
3254{
3255 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3256 u32 regmask = kcontrol->private_value;
3257 int change;
3258 unsigned int val;
3259
3260 if (!snd_hdspm_use_is_exclusive(hdspm))
3261 return -EBUSY;
3262 val = ucontrol->value.integer.value[0] & 1;
3263 spin_lock_irq(&hdspm->lock);
3264 change = (int) val != hdspm_toggle_setting(hdspm, regmask);
3265 hdspm_set_toggle_setting(hdspm, regmask, val);
3266 spin_unlock_irq(&hdspm->lock);
3267 return change;
3268}
3269
Takashi Iwai763f3562005-06-03 11:25:34 +02003270#define HDSPM_INPUT_SELECT(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003271{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3272 .name = xname, \
3273 .index = xindex, \
3274 .info = snd_hdspm_info_input_select, \
3275 .get = snd_hdspm_get_input_select, \
3276 .put = snd_hdspm_put_input_select \
Takashi Iwai763f3562005-06-03 11:25:34 +02003277}
3278
Takashi Iwai98274f02005-11-17 14:52:34 +01003279static int hdspm_input_select(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003280{
3281 return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
3282}
3283
Takashi Iwai98274f02005-11-17 14:52:34 +01003284static int hdspm_set_input_select(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02003285{
3286 if (out)
3287 hdspm->control_register |= HDSPM_InputSelect0;
3288 else
3289 hdspm->control_register &= ~HDSPM_InputSelect0;
3290 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3291
3292 return 0;
3293}
3294
Takashi Iwai98274f02005-11-17 14:52:34 +01003295static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
3296 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003297{
Adrian Knoth38816542013-07-05 11:28:20 +02003298 static const char *const texts[] = { "optical", "coaxial" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003299 ENUMERATED_CTL_INFO(uinfo, texts);
Takashi Iwai763f3562005-06-03 11:25:34 +02003300 return 0;
3301}
3302
Takashi Iwai98274f02005-11-17 14:52:34 +01003303static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
3304 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003305{
Takashi Iwai98274f02005-11-17 14:52:34 +01003306 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003307
3308 spin_lock_irq(&hdspm->lock);
3309 ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
3310 spin_unlock_irq(&hdspm->lock);
3311 return 0;
3312}
3313
Takashi Iwai98274f02005-11-17 14:52:34 +01003314static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
3315 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003316{
Takashi Iwai98274f02005-11-17 14:52:34 +01003317 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003318 int change;
3319 unsigned int val;
3320
3321 if (!snd_hdspm_use_is_exclusive(hdspm))
3322 return -EBUSY;
3323 val = ucontrol->value.integer.value[0] & 1;
3324 spin_lock_irq(&hdspm->lock);
3325 change = (int) val != hdspm_input_select(hdspm);
3326 hdspm_set_input_select(hdspm, val);
3327 spin_unlock_irq(&hdspm->lock);
3328 return change;
3329}
3330
Adrian Knoth0dca1792011-01-26 19:32:14 +01003331
Remy Bruno3cee5a62006-10-16 12:46:32 +02003332#define HDSPM_DS_WIRE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003333{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3334 .name = xname, \
3335 .index = xindex, \
3336 .info = snd_hdspm_info_ds_wire, \
3337 .get = snd_hdspm_get_ds_wire, \
3338 .put = snd_hdspm_put_ds_wire \
Remy Bruno3cee5a62006-10-16 12:46:32 +02003339}
3340
3341static int hdspm_ds_wire(struct hdspm * hdspm)
3342{
3343 return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
3344}
3345
3346static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
3347{
3348 if (ds)
3349 hdspm->control_register |= HDSPM_DS_DoubleWire;
3350 else
3351 hdspm->control_register &= ~HDSPM_DS_DoubleWire;
3352 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3353
3354 return 0;
3355}
3356
3357static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
3358 struct snd_ctl_elem_info *uinfo)
3359{
Adrian Knoth38816542013-07-05 11:28:20 +02003360 static const char *const texts[] = { "Single", "Double" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003361 ENUMERATED_CTL_INFO(uinfo, texts);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003362 return 0;
3363}
3364
3365static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
3366 struct snd_ctl_elem_value *ucontrol)
3367{
3368 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3369
3370 spin_lock_irq(&hdspm->lock);
3371 ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
3372 spin_unlock_irq(&hdspm->lock);
3373 return 0;
3374}
3375
3376static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
3377 struct snd_ctl_elem_value *ucontrol)
3378{
3379 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3380 int change;
3381 unsigned int val;
3382
3383 if (!snd_hdspm_use_is_exclusive(hdspm))
3384 return -EBUSY;
3385 val = ucontrol->value.integer.value[0] & 1;
3386 spin_lock_irq(&hdspm->lock);
3387 change = (int) val != hdspm_ds_wire(hdspm);
3388 hdspm_set_ds_wire(hdspm, val);
3389 spin_unlock_irq(&hdspm->lock);
3390 return change;
3391}
3392
Adrian Knoth0dca1792011-01-26 19:32:14 +01003393
Remy Bruno3cee5a62006-10-16 12:46:32 +02003394#define HDSPM_QS_WIRE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003395{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3396 .name = xname, \
3397 .index = xindex, \
3398 .info = snd_hdspm_info_qs_wire, \
3399 .get = snd_hdspm_get_qs_wire, \
3400 .put = snd_hdspm_put_qs_wire \
Remy Bruno3cee5a62006-10-16 12:46:32 +02003401}
3402
3403static int hdspm_qs_wire(struct hdspm * hdspm)
3404{
3405 if (hdspm->control_register & HDSPM_QS_DoubleWire)
3406 return 1;
3407 if (hdspm->control_register & HDSPM_QS_QuadWire)
3408 return 2;
3409 return 0;
3410}
3411
3412static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
3413{
3414 hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
3415 switch (mode) {
3416 case 0:
3417 break;
3418 case 1:
3419 hdspm->control_register |= HDSPM_QS_DoubleWire;
3420 break;
3421 case 2:
3422 hdspm->control_register |= HDSPM_QS_QuadWire;
3423 break;
3424 }
3425 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3426
3427 return 0;
3428}
3429
3430static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
3431 struct snd_ctl_elem_info *uinfo)
3432{
Adrian Knoth38816542013-07-05 11:28:20 +02003433 static const char *const texts[] = { "Single", "Double", "Quad" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003434 ENUMERATED_CTL_INFO(uinfo, texts);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003435 return 0;
3436}
3437
3438static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
3439 struct snd_ctl_elem_value *ucontrol)
3440{
3441 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3442
3443 spin_lock_irq(&hdspm->lock);
3444 ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
3445 spin_unlock_irq(&hdspm->lock);
3446 return 0;
3447}
3448
3449static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
3450 struct snd_ctl_elem_value *ucontrol)
3451{
3452 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3453 int change;
3454 int val;
3455
3456 if (!snd_hdspm_use_is_exclusive(hdspm))
3457 return -EBUSY;
3458 val = ucontrol->value.integer.value[0];
3459 if (val < 0)
3460 val = 0;
3461 if (val > 2)
3462 val = 2;
3463 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003464 change = val != hdspm_qs_wire(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003465 hdspm_set_qs_wire(hdspm, val);
3466 spin_unlock_irq(&hdspm->lock);
3467 return change;
3468}
3469
Adrian Knothacf14762013-07-05 11:28:00 +02003470#define HDSPM_CONTROL_TRISTATE(xname, xindex) \
3471{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3472 .name = xname, \
3473 .private_value = xindex, \
3474 .info = snd_hdspm_info_tristate, \
3475 .get = snd_hdspm_get_tristate, \
3476 .put = snd_hdspm_put_tristate \
3477}
3478
3479static int hdspm_tristate(struct hdspm *hdspm, u32 regmask)
3480{
3481 u32 reg = hdspm->settings_register & (regmask * 3);
3482 return reg / regmask;
3483}
3484
3485static int hdspm_set_tristate(struct hdspm *hdspm, int mode, u32 regmask)
3486{
3487 hdspm->settings_register &= ~(regmask * 3);
3488 hdspm->settings_register |= (regmask * mode);
3489 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
3490
3491 return 0;
3492}
3493
3494static int snd_hdspm_info_tristate(struct snd_kcontrol *kcontrol,
3495 struct snd_ctl_elem_info *uinfo)
3496{
3497 u32 regmask = kcontrol->private_value;
3498
Adrian Knoth38816542013-07-05 11:28:20 +02003499 static const char *const texts_spdif[] = { "Optical", "Coaxial", "Internal" };
3500 static const char *const texts_levels[] = { "Hi Gain", "+4 dBu", "-10 dBV" };
Adrian Knothacf14762013-07-05 11:28:00 +02003501
3502 switch (regmask) {
3503 case HDSPM_c0_Input0:
3504 ENUMERATED_CTL_INFO(uinfo, texts_spdif);
3505 break;
3506 default:
3507 ENUMERATED_CTL_INFO(uinfo, texts_levels);
3508 break;
3509 }
3510 return 0;
3511}
3512
3513static int snd_hdspm_get_tristate(struct snd_kcontrol *kcontrol,
3514 struct snd_ctl_elem_value *ucontrol)
3515{
3516 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3517 u32 regmask = kcontrol->private_value;
3518
3519 spin_lock_irq(&hdspm->lock);
3520 ucontrol->value.enumerated.item[0] = hdspm_tristate(hdspm, regmask);
3521 spin_unlock_irq(&hdspm->lock);
3522 return 0;
3523}
3524
3525static int snd_hdspm_put_tristate(struct snd_kcontrol *kcontrol,
3526 struct snd_ctl_elem_value *ucontrol)
3527{
3528 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3529 u32 regmask = kcontrol->private_value;
3530 int change;
3531 int val;
3532
3533 if (!snd_hdspm_use_is_exclusive(hdspm))
3534 return -EBUSY;
3535 val = ucontrol->value.integer.value[0];
3536 if (val < 0)
3537 val = 0;
3538 if (val > 2)
3539 val = 2;
3540
3541 spin_lock_irq(&hdspm->lock);
3542 change = val != hdspm_tristate(hdspm, regmask);
3543 hdspm_set_tristate(hdspm, val, regmask);
3544 spin_unlock_irq(&hdspm->lock);
3545 return change;
3546}
3547
Adrian Knoth700d1ef2011-07-29 03:11:02 +02003548#define HDSPM_MADI_SPEEDMODE(xname, xindex) \
3549{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3550 .name = xname, \
3551 .index = xindex, \
3552 .info = snd_hdspm_info_madi_speedmode, \
3553 .get = snd_hdspm_get_madi_speedmode, \
3554 .put = snd_hdspm_put_madi_speedmode \
3555}
3556
3557static int hdspm_madi_speedmode(struct hdspm *hdspm)
3558{
3559 if (hdspm->control_register & HDSPM_QuadSpeed)
3560 return 2;
3561 if (hdspm->control_register & HDSPM_DoubleSpeed)
3562 return 1;
3563 return 0;
3564}
3565
3566static int hdspm_set_madi_speedmode(struct hdspm *hdspm, int mode)
3567{
3568 hdspm->control_register &= ~(HDSPM_DoubleSpeed | HDSPM_QuadSpeed);
3569 switch (mode) {
3570 case 0:
3571 break;
3572 case 1:
3573 hdspm->control_register |= HDSPM_DoubleSpeed;
3574 break;
3575 case 2:
3576 hdspm->control_register |= HDSPM_QuadSpeed;
3577 break;
3578 }
3579 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3580
3581 return 0;
3582}
3583
3584static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol,
3585 struct snd_ctl_elem_info *uinfo)
3586{
Adrian Knoth38816542013-07-05 11:28:20 +02003587 static const char *const texts[] = { "Single", "Double", "Quad" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003588 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth700d1ef2011-07-29 03:11:02 +02003589 return 0;
3590}
3591
3592static int snd_hdspm_get_madi_speedmode(struct snd_kcontrol *kcontrol,
3593 struct snd_ctl_elem_value *ucontrol)
3594{
3595 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3596
3597 spin_lock_irq(&hdspm->lock);
3598 ucontrol->value.enumerated.item[0] = hdspm_madi_speedmode(hdspm);
3599 spin_unlock_irq(&hdspm->lock);
3600 return 0;
3601}
3602
3603static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol,
3604 struct snd_ctl_elem_value *ucontrol)
3605{
3606 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3607 int change;
3608 int val;
3609
3610 if (!snd_hdspm_use_is_exclusive(hdspm))
3611 return -EBUSY;
3612 val = ucontrol->value.integer.value[0];
3613 if (val < 0)
3614 val = 0;
3615 if (val > 2)
3616 val = 2;
3617 spin_lock_irq(&hdspm->lock);
3618 change = val != hdspm_madi_speedmode(hdspm);
3619 hdspm_set_madi_speedmode(hdspm, val);
3620 spin_unlock_irq(&hdspm->lock);
3621 return change;
3622}
Takashi Iwai763f3562005-06-03 11:25:34 +02003623
3624#define HDSPM_MIXER(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003625{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
3626 .name = xname, \
3627 .index = xindex, \
3628 .device = 0, \
3629 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
3630 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3631 .info = snd_hdspm_info_mixer, \
3632 .get = snd_hdspm_get_mixer, \
3633 .put = snd_hdspm_put_mixer \
Takashi Iwai763f3562005-06-03 11:25:34 +02003634}
3635
Takashi Iwai98274f02005-11-17 14:52:34 +01003636static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
3637 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003638{
3639 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3640 uinfo->count = 3;
3641 uinfo->value.integer.min = 0;
3642 uinfo->value.integer.max = 65535;
3643 uinfo->value.integer.step = 1;
3644 return 0;
3645}
3646
Takashi Iwai98274f02005-11-17 14:52:34 +01003647static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
3648 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003649{
Takashi Iwai98274f02005-11-17 14:52:34 +01003650 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003651 int source;
3652 int destination;
3653
3654 source = ucontrol->value.integer.value[0];
3655 if (source < 0)
3656 source = 0;
3657 else if (source >= 2 * HDSPM_MAX_CHANNELS)
3658 source = 2 * HDSPM_MAX_CHANNELS - 1;
3659
3660 destination = ucontrol->value.integer.value[1];
3661 if (destination < 0)
3662 destination = 0;
3663 else if (destination >= HDSPM_MAX_CHANNELS)
3664 destination = HDSPM_MAX_CHANNELS - 1;
3665
3666 spin_lock_irq(&hdspm->lock);
3667 if (source >= HDSPM_MAX_CHANNELS)
3668 ucontrol->value.integer.value[2] =
3669 hdspm_read_pb_gain(hdspm, destination,
3670 source - HDSPM_MAX_CHANNELS);
3671 else
3672 ucontrol->value.integer.value[2] =
3673 hdspm_read_in_gain(hdspm, destination, source);
3674
3675 spin_unlock_irq(&hdspm->lock);
3676
3677 return 0;
3678}
3679
Takashi Iwai98274f02005-11-17 14:52:34 +01003680static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
3681 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003682{
Takashi Iwai98274f02005-11-17 14:52:34 +01003683 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003684 int change;
3685 int source;
3686 int destination;
3687 int gain;
3688
3689 if (!snd_hdspm_use_is_exclusive(hdspm))
3690 return -EBUSY;
3691
3692 source = ucontrol->value.integer.value[0];
3693 destination = ucontrol->value.integer.value[1];
3694
3695 if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
3696 return -1;
3697 if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
3698 return -1;
3699
3700 gain = ucontrol->value.integer.value[2];
3701
3702 spin_lock_irq(&hdspm->lock);
3703
3704 if (source >= HDSPM_MAX_CHANNELS)
3705 change = gain != hdspm_read_pb_gain(hdspm, destination,
3706 source -
3707 HDSPM_MAX_CHANNELS);
3708 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003709 change = gain != hdspm_read_in_gain(hdspm, destination,
3710 source);
Takashi Iwai763f3562005-06-03 11:25:34 +02003711
3712 if (change) {
3713 if (source >= HDSPM_MAX_CHANNELS)
3714 hdspm_write_pb_gain(hdspm, destination,
3715 source - HDSPM_MAX_CHANNELS,
3716 gain);
3717 else
3718 hdspm_write_in_gain(hdspm, destination, source,
3719 gain);
3720 }
3721 spin_unlock_irq(&hdspm->lock);
3722
3723 return change;
3724}
3725
3726/* The simple mixer control(s) provide gain control for the
3727 basic 1:1 mappings of playback streams to output
Adrian Knoth0dca1792011-01-26 19:32:14 +01003728 streams.
Takashi Iwai763f3562005-06-03 11:25:34 +02003729*/
3730
3731#define HDSPM_PLAYBACK_MIXER \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003732{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3733 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
3734 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3735 .info = snd_hdspm_info_playback_mixer, \
3736 .get = snd_hdspm_get_playback_mixer, \
3737 .put = snd_hdspm_put_playback_mixer \
Takashi Iwai763f3562005-06-03 11:25:34 +02003738}
3739
Takashi Iwai98274f02005-11-17 14:52:34 +01003740static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
3741 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003742{
3743 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3744 uinfo->count = 1;
3745 uinfo->value.integer.min = 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003746 uinfo->value.integer.max = 64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003747 uinfo->value.integer.step = 1;
3748 return 0;
3749}
3750
Takashi Iwai98274f02005-11-17 14:52:34 +01003751static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
3752 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003753{
Takashi Iwai98274f02005-11-17 14:52:34 +01003754 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003755 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003756
3757 channel = ucontrol->id.index - 1;
3758
Takashi Iwaida3cec32008-08-08 17:12:14 +02003759 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3760 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003761
Takashi Iwai763f3562005-06-03 11:25:34 +02003762 spin_lock_irq(&hdspm->lock);
3763 ucontrol->value.integer.value[0] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003764 (hdspm_read_pb_gain(hdspm, channel, channel)*64)/UNITY_GAIN;
Takashi Iwai763f3562005-06-03 11:25:34 +02003765 spin_unlock_irq(&hdspm->lock);
3766
Takashi Iwai763f3562005-06-03 11:25:34 +02003767 return 0;
3768}
3769
Takashi Iwai98274f02005-11-17 14:52:34 +01003770static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
3771 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003772{
Takashi Iwai98274f02005-11-17 14:52:34 +01003773 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003774 int change;
3775 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003776 int gain;
3777
3778 if (!snd_hdspm_use_is_exclusive(hdspm))
3779 return -EBUSY;
3780
3781 channel = ucontrol->id.index - 1;
3782
Takashi Iwaida3cec32008-08-08 17:12:14 +02003783 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3784 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003785
Adrian Knoth0dca1792011-01-26 19:32:14 +01003786 gain = ucontrol->value.integer.value[0]*UNITY_GAIN/64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003787
3788 spin_lock_irq(&hdspm->lock);
3789 change =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003790 gain != hdspm_read_pb_gain(hdspm, channel,
3791 channel);
Takashi Iwai763f3562005-06-03 11:25:34 +02003792 if (change)
Adrian Knoth0dca1792011-01-26 19:32:14 +01003793 hdspm_write_pb_gain(hdspm, channel, channel,
Takashi Iwai763f3562005-06-03 11:25:34 +02003794 gain);
3795 spin_unlock_irq(&hdspm->lock);
3796 return change;
3797}
3798
Adrian Knoth0dca1792011-01-26 19:32:14 +01003799#define HDSPM_SYNC_CHECK(xname, xindex) \
3800{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3801 .name = xname, \
3802 .private_value = xindex, \
3803 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3804 .info = snd_hdspm_info_sync_check, \
3805 .get = snd_hdspm_get_sync_check \
Takashi Iwai763f3562005-06-03 11:25:34 +02003806}
3807
Adrian Knoth34542212013-03-10 00:37:25 +01003808#define HDSPM_TCO_LOCK_CHECK(xname, xindex) \
3809{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3810 .name = xname, \
3811 .private_value = xindex, \
3812 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3813 .info = snd_hdspm_tco_info_lock_check, \
3814 .get = snd_hdspm_get_sync_check \
3815}
3816
3817
Adrian Knoth0dca1792011-01-26 19:32:14 +01003818
Takashi Iwai98274f02005-11-17 14:52:34 +01003819static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
3820 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003821{
Adrian Knoth38816542013-07-05 11:28:20 +02003822 static const char *const texts[] = { "No Lock", "Lock", "Sync", "N/A" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003823 ENUMERATED_CTL_INFO(uinfo, texts);
Takashi Iwai763f3562005-06-03 11:25:34 +02003824 return 0;
3825}
3826
Adrian Knoth34542212013-03-10 00:37:25 +01003827static int snd_hdspm_tco_info_lock_check(struct snd_kcontrol *kcontrol,
3828 struct snd_ctl_elem_info *uinfo)
3829{
Adrian Knoth38816542013-07-05 11:28:20 +02003830 static const char *const texts[] = { "No Lock", "Lock" };
Adrian Knoth34542212013-03-10 00:37:25 +01003831 ENUMERATED_CTL_INFO(uinfo, texts);
3832 return 0;
3833}
3834
Adrian Knoth0dca1792011-01-26 19:32:14 +01003835static int hdspm_wc_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003836{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003837 int status, status2;
3838
3839 switch (hdspm->io_type) {
3840 case AES32:
3841 status = hdspm_read(hdspm, HDSPM_statusRegister);
Andre Schramm56bde0f2013-01-09 14:40:18 +01003842 if (status & HDSPM_AES32_wcLock) {
3843 if (status & HDSPM_AES32_wcSync)
3844 return 2;
3845 else
3846 return 1;
3847 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02003848 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003849 break;
3850
3851 case MADI:
3852 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003853 if (status2 & HDSPM_wcLock) {
3854 if (status2 & HDSPM_wcSync)
3855 return 2;
3856 else
3857 return 1;
3858 }
3859 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003860 break;
3861
3862 case RayDAT:
3863 case AIO:
3864 status = hdspm_read(hdspm, HDSPM_statusRegister);
3865
3866 if (status & 0x2000000)
3867 return 2;
3868 else if (status & 0x1000000)
3869 return 1;
3870 return 0;
3871
3872 break;
3873
3874 case MADIface:
3875 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02003876 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003877
Takashi Iwai763f3562005-06-03 11:25:34 +02003878
Adrian Knoth0dca1792011-01-26 19:32:14 +01003879 return 3;
Takashi Iwai763f3562005-06-03 11:25:34 +02003880}
3881
3882
Adrian Knoth0dca1792011-01-26 19:32:14 +01003883static int hdspm_madi_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003884{
3885 int status = hdspm_read(hdspm, HDSPM_statusRegister);
3886 if (status & HDSPM_madiLock) {
3887 if (status & HDSPM_madiSync)
3888 return 2;
3889 else
3890 return 1;
3891 }
3892 return 0;
3893}
3894
Adrian Knoth0dca1792011-01-26 19:32:14 +01003895
3896static int hdspm_s1_sync_check(struct hdspm *hdspm, int idx)
3897{
3898 int status, lock, sync;
3899
3900 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3901
3902 lock = (status & (0x1<<idx)) ? 1 : 0;
3903 sync = (status & (0x100<<idx)) ? 1 : 0;
3904
3905 if (lock && sync)
3906 return 2;
3907 else if (lock)
3908 return 1;
3909 return 0;
3910}
3911
3912
3913static int hdspm_sync_in_sync_check(struct hdspm *hdspm)
3914{
3915 int status, lock = 0, sync = 0;
3916
3917 switch (hdspm->io_type) {
3918 case RayDAT:
3919 case AIO:
3920 status = hdspm_read(hdspm, HDSPM_RD_STATUS_3);
3921 lock = (status & 0x400) ? 1 : 0;
3922 sync = (status & 0x800) ? 1 : 0;
3923 break;
3924
3925 case MADI:
Adrian Knoth2e0452f2012-10-19 17:42:27 +02003926 status = hdspm_read(hdspm, HDSPM_statusRegister);
3927 lock = (status & HDSPM_syncInLock) ? 1 : 0;
3928 sync = (status & HDSPM_syncInSync) ? 1 : 0;
3929 break;
3930
Adrian Knoth0dca1792011-01-26 19:32:14 +01003931 case AES32:
3932 status = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth9a215f42012-10-19 17:42:28 +02003933 lock = (status & 0x100000) ? 1 : 0;
3934 sync = (status & 0x200000) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003935 break;
3936
3937 case MADIface:
3938 break;
3939 }
3940
3941 if (lock && sync)
3942 return 2;
3943 else if (lock)
3944 return 1;
3945
3946 return 0;
3947}
3948
3949static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx)
3950{
3951 int status2, lock, sync;
3952 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
3953
3954 lock = (status2 & (0x0080 >> idx)) ? 1 : 0;
3955 sync = (status2 & (0x8000 >> idx)) ? 1 : 0;
3956
3957 if (sync)
3958 return 2;
3959 else if (lock)
3960 return 1;
3961 return 0;
3962}
3963
Adrian Knoth34542212013-03-10 00:37:25 +01003964static int hdspm_tco_input_check(struct hdspm *hdspm, u32 mask)
3965{
3966 u32 status;
3967 status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
3968
3969 return (status & mask) ? 1 : 0;
3970}
3971
Adrian Knoth0dca1792011-01-26 19:32:14 +01003972
3973static int hdspm_tco_sync_check(struct hdspm *hdspm)
3974{
3975 int status;
3976
3977 if (hdspm->tco) {
3978 switch (hdspm->io_type) {
3979 case MADI:
Adrian Knothb0bf5502013-07-05 11:28:05 +02003980 status = hdspm_read(hdspm, HDSPM_statusRegister);
3981 if (status & HDSPM_tcoLockMadi) {
3982 if (status & HDSPM_tcoSync)
3983 return 2;
3984 else
3985 return 1;
3986 }
3987 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003988 case AES32:
3989 status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knothb0bf5502013-07-05 11:28:05 +02003990 if (status & HDSPM_tcoLockAes) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01003991 if (status & HDSPM_tcoSync)
3992 return 2;
3993 else
3994 return 1;
3995 }
3996 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003997 case RayDAT:
3998 case AIO:
3999 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
4000
4001 if (status & 0x8000000)
4002 return 2; /* Sync */
4003 if (status & 0x4000000)
4004 return 1; /* Lock */
4005 return 0; /* No signal */
Adrian Knoth0dca1792011-01-26 19:32:14 +01004006
4007 default:
4008 break;
4009 }
4010 }
4011
4012 return 3; /* N/A */
4013}
4014
4015
4016static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
4017 struct snd_ctl_elem_value *ucontrol)
4018{
4019 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4020 int val = -1;
4021
4022 switch (hdspm->io_type) {
4023 case RayDAT:
4024 switch (kcontrol->private_value) {
4025 case 0: /* WC */
4026 val = hdspm_wc_sync_check(hdspm); break;
4027 case 7: /* TCO */
4028 val = hdspm_tco_sync_check(hdspm); break;
4029 case 8: /* SYNC IN */
4030 val = hdspm_sync_in_sync_check(hdspm); break;
4031 default:
Adrian Knothd1a3c982012-11-07 18:00:09 +01004032 val = hdspm_s1_sync_check(hdspm,
4033 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004034 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02004035 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004036
4037 case AIO:
4038 switch (kcontrol->private_value) {
4039 case 0: /* WC */
4040 val = hdspm_wc_sync_check(hdspm); break;
4041 case 4: /* TCO */
4042 val = hdspm_tco_sync_check(hdspm); break;
4043 case 5: /* SYNC IN */
4044 val = hdspm_sync_in_sync_check(hdspm); break;
4045 default:
Adrian Knoth1cb7dbf2013-07-05 11:28:03 +02004046 val = hdspm_s1_sync_check(hdspm,
4047 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004048 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02004049 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004050
4051 case MADI:
4052 switch (kcontrol->private_value) {
4053 case 0: /* WC */
4054 val = hdspm_wc_sync_check(hdspm); break;
4055 case 1: /* MADI */
4056 val = hdspm_madi_sync_check(hdspm); break;
4057 case 2: /* TCO */
4058 val = hdspm_tco_sync_check(hdspm); break;
4059 case 3: /* SYNC_IN */
4060 val = hdspm_sync_in_sync_check(hdspm); break;
4061 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02004062 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004063
4064 case MADIface:
4065 val = hdspm_madi_sync_check(hdspm); /* MADI */
4066 break;
4067
4068 case AES32:
4069 switch (kcontrol->private_value) {
4070 case 0: /* WC */
4071 val = hdspm_wc_sync_check(hdspm); break;
4072 case 9: /* TCO */
4073 val = hdspm_tco_sync_check(hdspm); break;
4074 case 10 /* SYNC IN */:
4075 val = hdspm_sync_in_sync_check(hdspm); break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01004076 default: /* AES1 to AES8 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01004077 val = hdspm_aes_sync_check(hdspm,
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01004078 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004079 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02004080 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004081
4082 }
4083
Adrian Knoth34542212013-03-10 00:37:25 +01004084 if (hdspm->tco) {
4085 switch (kcontrol->private_value) {
4086 case 11:
4087 /* Check TCO for lock state of its current input */
4088 val = hdspm_tco_input_check(hdspm, HDSPM_TCO1_TCO_lock);
4089 break;
4090 case 12:
4091 /* Check TCO for valid time code on LTC input. */
4092 val = hdspm_tco_input_check(hdspm,
4093 HDSPM_TCO1_LTC_Input_valid);
4094 break;
4095 default:
4096 break;
4097 }
4098 }
4099
Adrian Knoth0dca1792011-01-26 19:32:14 +01004100 if (-1 == val)
4101 val = 3;
4102
4103 ucontrol->value.enumerated.item[0] = val;
4104 return 0;
4105}
4106
4107
4108
Takashi Iwaiddcecf62014-11-10 17:24:26 +01004109/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01004110 * TCO controls
Takashi Iwaiddcecf62014-11-10 17:24:26 +01004111 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01004112static void hdspm_tco_write(struct hdspm *hdspm)
4113{
4114 unsigned int tc[4] = { 0, 0, 0, 0};
4115
4116 switch (hdspm->tco->input) {
4117 case 0:
4118 tc[2] |= HDSPM_TCO2_set_input_MSB;
4119 break;
4120 case 1:
4121 tc[2] |= HDSPM_TCO2_set_input_LSB;
4122 break;
4123 default:
4124 break;
4125 }
4126
4127 switch (hdspm->tco->framerate) {
4128 case 1:
4129 tc[1] |= HDSPM_TCO1_LTC_Format_LSB;
4130 break;
4131 case 2:
4132 tc[1] |= HDSPM_TCO1_LTC_Format_MSB;
4133 break;
4134 case 3:
4135 tc[1] |= HDSPM_TCO1_LTC_Format_MSB +
4136 HDSPM_TCO1_set_drop_frame_flag;
4137 break;
4138 case 4:
4139 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
4140 HDSPM_TCO1_LTC_Format_MSB;
4141 break;
4142 case 5:
4143 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
4144 HDSPM_TCO1_LTC_Format_MSB +
4145 HDSPM_TCO1_set_drop_frame_flag;
4146 break;
4147 default:
4148 break;
4149 }
4150
4151 switch (hdspm->tco->wordclock) {
4152 case 1:
4153 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_LSB;
4154 break;
4155 case 2:
4156 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_MSB;
4157 break;
4158 default:
4159 break;
4160 }
4161
4162 switch (hdspm->tco->samplerate) {
4163 case 1:
4164 tc[2] |= HDSPM_TCO2_set_freq;
4165 break;
4166 case 2:
4167 tc[2] |= HDSPM_TCO2_set_freq_from_app;
4168 break;
4169 default:
4170 break;
4171 }
4172
4173 switch (hdspm->tco->pull) {
4174 case 1:
4175 tc[2] |= HDSPM_TCO2_set_pull_up;
4176 break;
4177 case 2:
4178 tc[2] |= HDSPM_TCO2_set_pull_down;
4179 break;
4180 case 3:
4181 tc[2] |= HDSPM_TCO2_set_pull_up + HDSPM_TCO2_set_01_4;
4182 break;
4183 case 4:
4184 tc[2] |= HDSPM_TCO2_set_pull_down + HDSPM_TCO2_set_01_4;
4185 break;
4186 default:
4187 break;
4188 }
4189
4190 if (1 == hdspm->tco->term) {
4191 tc[2] |= HDSPM_TCO2_set_term_75R;
4192 }
4193
4194 hdspm_write(hdspm, HDSPM_WR_TCO, tc[0]);
4195 hdspm_write(hdspm, HDSPM_WR_TCO+4, tc[1]);
4196 hdspm_write(hdspm, HDSPM_WR_TCO+8, tc[2]);
4197 hdspm_write(hdspm, HDSPM_WR_TCO+12, tc[3]);
4198}
4199
4200
4201#define HDSPM_TCO_SAMPLE_RATE(xname, xindex) \
4202{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4203 .name = xname, \
4204 .index = xindex, \
4205 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4206 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4207 .info = snd_hdspm_info_tco_sample_rate, \
4208 .get = snd_hdspm_get_tco_sample_rate, \
4209 .put = snd_hdspm_put_tco_sample_rate \
4210}
4211
4212static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol,
4213 struct snd_ctl_elem_info *uinfo)
4214{
Martin Dausel69358fc2013-07-05 11:28:23 +02004215 /* TODO freq from app could be supported here, see tco->samplerate */
Adrian Knoth38816542013-07-05 11:28:20 +02004216 static const char *const texts[] = { "44.1 kHz", "48 kHz" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004217 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004218 return 0;
4219}
4220
4221static int snd_hdspm_get_tco_sample_rate(struct snd_kcontrol *kcontrol,
4222 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02004223{
Takashi Iwai98274f02005-11-17 14:52:34 +01004224 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02004225
Adrian Knoth0dca1792011-01-26 19:32:14 +01004226 ucontrol->value.enumerated.item[0] = hdspm->tco->samplerate;
4227
Takashi Iwai763f3562005-06-03 11:25:34 +02004228 return 0;
4229}
4230
Adrian Knoth0dca1792011-01-26 19:32:14 +01004231static int snd_hdspm_put_tco_sample_rate(struct snd_kcontrol *kcontrol,
4232 struct snd_ctl_elem_value *ucontrol)
Remy Bruno3cee5a62006-10-16 12:46:32 +02004233{
Adrian Knoth0dca1792011-01-26 19:32:14 +01004234 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4235
4236 if (hdspm->tco->samplerate != ucontrol->value.enumerated.item[0]) {
4237 hdspm->tco->samplerate = ucontrol->value.enumerated.item[0];
4238
4239 hdspm_tco_write(hdspm);
4240
4241 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004242 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01004243
Remy Bruno3cee5a62006-10-16 12:46:32 +02004244 return 0;
4245}
4246
Adrian Knoth0dca1792011-01-26 19:32:14 +01004247
4248#define HDSPM_TCO_PULL(xname, xindex) \
4249{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4250 .name = xname, \
4251 .index = xindex, \
4252 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4253 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4254 .info = snd_hdspm_info_tco_pull, \
4255 .get = snd_hdspm_get_tco_pull, \
4256 .put = snd_hdspm_put_tco_pull \
4257}
4258
4259static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol,
4260 struct snd_ctl_elem_info *uinfo)
4261{
Adrian Knoth38816542013-07-05 11:28:20 +02004262 static const char *const texts[] = { "0", "+ 0.1 %", "- 0.1 %",
4263 "+ 4 %", "- 4 %" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004264 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004265 return 0;
4266}
4267
4268static int snd_hdspm_get_tco_pull(struct snd_kcontrol *kcontrol,
4269 struct snd_ctl_elem_value *ucontrol)
4270{
4271 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4272
4273 ucontrol->value.enumerated.item[0] = hdspm->tco->pull;
4274
4275 return 0;
4276}
4277
4278static int snd_hdspm_put_tco_pull(struct snd_kcontrol *kcontrol,
4279 struct snd_ctl_elem_value *ucontrol)
4280{
4281 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4282
4283 if (hdspm->tco->pull != ucontrol->value.enumerated.item[0]) {
4284 hdspm->tco->pull = ucontrol->value.enumerated.item[0];
4285
4286 hdspm_tco_write(hdspm);
4287
4288 return 1;
4289 }
4290
4291 return 0;
4292}
4293
4294#define HDSPM_TCO_WCK_CONVERSION(xname, xindex) \
4295{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4296 .name = xname, \
4297 .index = xindex, \
4298 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4299 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4300 .info = snd_hdspm_info_tco_wck_conversion, \
4301 .get = snd_hdspm_get_tco_wck_conversion, \
4302 .put = snd_hdspm_put_tco_wck_conversion \
4303}
4304
4305static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4306 struct snd_ctl_elem_info *uinfo)
4307{
Adrian Knoth38816542013-07-05 11:28:20 +02004308 static const char *const texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004309 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004310 return 0;
4311}
4312
4313static int snd_hdspm_get_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4314 struct snd_ctl_elem_value *ucontrol)
4315{
4316 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4317
4318 ucontrol->value.enumerated.item[0] = hdspm->tco->wordclock;
4319
4320 return 0;
4321}
4322
4323static int snd_hdspm_put_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4324 struct snd_ctl_elem_value *ucontrol)
4325{
4326 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4327
4328 if (hdspm->tco->wordclock != ucontrol->value.enumerated.item[0]) {
4329 hdspm->tco->wordclock = ucontrol->value.enumerated.item[0];
4330
4331 hdspm_tco_write(hdspm);
4332
4333 return 1;
4334 }
4335
4336 return 0;
4337}
4338
4339
4340#define HDSPM_TCO_FRAME_RATE(xname, xindex) \
4341{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4342 .name = xname, \
4343 .index = xindex, \
4344 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4345 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4346 .info = snd_hdspm_info_tco_frame_rate, \
4347 .get = snd_hdspm_get_tco_frame_rate, \
4348 .put = snd_hdspm_put_tco_frame_rate \
4349}
4350
4351static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol,
4352 struct snd_ctl_elem_info *uinfo)
4353{
Adrian Knoth38816542013-07-05 11:28:20 +02004354 static const char *const texts[] = { "24 fps", "25 fps", "29.97fps",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004355 "29.97 dfps", "30 fps", "30 dfps" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004356 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004357 return 0;
4358}
4359
4360static int snd_hdspm_get_tco_frame_rate(struct snd_kcontrol *kcontrol,
Remy Bruno3cee5a62006-10-16 12:46:32 +02004361 struct snd_ctl_elem_value *ucontrol)
4362{
Remy Bruno3cee5a62006-10-16 12:46:32 +02004363 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4364
Adrian Knoth0dca1792011-01-26 19:32:14 +01004365 ucontrol->value.enumerated.item[0] = hdspm->tco->framerate;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004366
Remy Bruno3cee5a62006-10-16 12:46:32 +02004367 return 0;
4368}
Takashi Iwai763f3562005-06-03 11:25:34 +02004369
Adrian Knoth0dca1792011-01-26 19:32:14 +01004370static int snd_hdspm_put_tco_frame_rate(struct snd_kcontrol *kcontrol,
4371 struct snd_ctl_elem_value *ucontrol)
4372{
4373 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4374
4375 if (hdspm->tco->framerate != ucontrol->value.enumerated.item[0]) {
4376 hdspm->tco->framerate = ucontrol->value.enumerated.item[0];
4377
4378 hdspm_tco_write(hdspm);
4379
4380 return 1;
4381 }
4382
4383 return 0;
4384}
4385
4386
4387#define HDSPM_TCO_SYNC_SOURCE(xname, xindex) \
4388{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4389 .name = xname, \
4390 .index = xindex, \
4391 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4392 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4393 .info = snd_hdspm_info_tco_sync_source, \
4394 .get = snd_hdspm_get_tco_sync_source, \
4395 .put = snd_hdspm_put_tco_sync_source \
4396}
4397
4398static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol,
4399 struct snd_ctl_elem_info *uinfo)
4400{
Adrian Knoth38816542013-07-05 11:28:20 +02004401 static const char *const texts[] = { "LTC", "Video", "WCK" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004402 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004403 return 0;
4404}
4405
4406static int snd_hdspm_get_tco_sync_source(struct snd_kcontrol *kcontrol,
4407 struct snd_ctl_elem_value *ucontrol)
4408{
4409 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4410
4411 ucontrol->value.enumerated.item[0] = hdspm->tco->input;
4412
4413 return 0;
4414}
4415
4416static int snd_hdspm_put_tco_sync_source(struct snd_kcontrol *kcontrol,
4417 struct snd_ctl_elem_value *ucontrol)
4418{
4419 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4420
4421 if (hdspm->tco->input != ucontrol->value.enumerated.item[0]) {
4422 hdspm->tco->input = ucontrol->value.enumerated.item[0];
4423
4424 hdspm_tco_write(hdspm);
4425
4426 return 1;
4427 }
4428
4429 return 0;
4430}
4431
4432
4433#define HDSPM_TCO_WORD_TERM(xname, xindex) \
4434{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4435 .name = xname, \
4436 .index = xindex, \
4437 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4438 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4439 .info = snd_hdspm_info_tco_word_term, \
4440 .get = snd_hdspm_get_tco_word_term, \
4441 .put = snd_hdspm_put_tco_word_term \
4442}
4443
4444static int snd_hdspm_info_tco_word_term(struct snd_kcontrol *kcontrol,
4445 struct snd_ctl_elem_info *uinfo)
4446{
4447 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
4448 uinfo->count = 1;
4449 uinfo->value.integer.min = 0;
4450 uinfo->value.integer.max = 1;
4451
4452 return 0;
4453}
4454
4455
4456static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol,
4457 struct snd_ctl_elem_value *ucontrol)
4458{
4459 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4460
Takashi Iwai537e4812016-02-29 14:25:16 +01004461 ucontrol->value.integer.value[0] = hdspm->tco->term;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004462
4463 return 0;
4464}
4465
4466
4467static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol,
4468 struct snd_ctl_elem_value *ucontrol)
4469{
4470 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4471
Takashi Iwai537e4812016-02-29 14:25:16 +01004472 if (hdspm->tco->term != ucontrol->value.integer.value[0]) {
4473 hdspm->tco->term = ucontrol->value.integer.value[0];
Adrian Knoth0dca1792011-01-26 19:32:14 +01004474
4475 hdspm_tco_write(hdspm);
4476
4477 return 1;
4478 }
4479
4480 return 0;
4481}
4482
4483
4484
Takashi Iwai763f3562005-06-03 11:25:34 +02004485
Remy Bruno3cee5a62006-10-16 12:46:32 +02004486static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004487 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004488 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Takashi Iwai763f3562005-06-03 11:25:34 +02004489 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4490 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4491 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4492 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Adrian Knothb8812c52012-10-19 17:42:26 +02004493 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004494 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4495 HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
Adrian Knoth930f4ff2012-10-19 17:42:29 +02004496 HDSPM_SYNC_CHECK("TCO SyncCheck", 2),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004497 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
Adrian Knothc9e16682012-12-03 14:55:50 +01004498 HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
4499 HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
Adrian Knoth696be0f2013-03-10 00:37:23 +01004500 HDSPM_TOGGLE_SETTING("Disable 96K frames", HDSPM_SMUX),
Adrian Knothc9e16682012-12-03 14:55:50 +01004501 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
4502 HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
Adrian Knoth700d1ef2011-07-29 03:11:02 +02004503 HDSPM_INPUT_SELECT("Input Select", 0),
4504 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004505};
4506
4507
4508static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
4509 HDSPM_MIXER("Mixer", 0),
4510 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4511 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4512 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4513 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4514 HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
Adrian Knothc9e16682012-12-03 14:55:50 +01004515 HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
4516 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
4517 HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
Adrian Knoth700d1ef2011-07-29 03:11:02 +02004518 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004519};
4520
Adrian Knoth0dca1792011-01-26 19:32:14 +01004521static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004522 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004523 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004524 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4525 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004526 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004527 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004528 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4529 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4530 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4531 HDSPM_SYNC_CHECK("ADAT SyncCheck", 3),
4532 HDSPM_SYNC_CHECK("TCO SyncCheck", 4),
4533 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 5),
4534 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4535 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4536 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4537 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT Frequency", 3),
4538 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 4),
Adrian Knothfb0f1212013-07-05 11:27:58 +02004539 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5),
Adrian Knoth42f4c122013-07-05 11:28:01 +02004540 HDSPM_CONTROL_TRISTATE("S/PDIF Input", HDSPM_c0_Input0),
Adrian Knothfb0f1212013-07-05 11:27:58 +02004541 HDSPM_TOGGLE_SETTING("S/PDIF Out Optical", HDSPM_c0_Spdif_Opt),
4542 HDSPM_TOGGLE_SETTING("S/PDIF Out Professional", HDSPM_c0_Pro),
4543 HDSPM_TOGGLE_SETTING("ADAT internal (AEB/TEB)", HDSPM_c0_AEB1),
4544 HDSPM_TOGGLE_SETTING("XLR Breakout Cable", HDSPM_c0_Sym6db),
Adrian Knoth42f4c122013-07-05 11:28:01 +02004545 HDSPM_TOGGLE_SETTING("Single Speed WordClock Out", HDSPM_c0_Wck48),
4546 HDSPM_CONTROL_TRISTATE("Input Level", HDSPM_c0_AD_GAIN0),
4547 HDSPM_CONTROL_TRISTATE("Output Level", HDSPM_c0_DA_GAIN0),
4548 HDSPM_CONTROL_TRISTATE("Phones Level", HDSPM_c0_PH_GAIN0)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004549
4550 /*
4551 HDSPM_INPUT_SELECT("Input Select", 0),
4552 HDSPM_SPDIF_OPTICAL("SPDIF Out Optical", 0),
4553 HDSPM_PROFESSIONAL("SPDIF Out Professional", 0);
4554 HDSPM_SPDIF_IN("SPDIF In", 0);
4555 HDSPM_BREAKOUT_CABLE("Breakout Cable", 0);
4556 HDSPM_INPUT_LEVEL("Input Level", 0);
4557 HDSPM_OUTPUT_LEVEL("Output Level", 0);
4558 HDSPM_PHONES("Phones", 0);
4559 */
4560};
4561
4562static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = {
4563 HDSPM_MIXER("Mixer", 0),
4564 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4565 HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0),
4566 HDSPM_PREF_SYNC_REF("Pref Sync Ref", 0),
4567 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4568 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4569 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4570 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4571 HDSPM_SYNC_CHECK("ADAT1 SyncCheck", 3),
4572 HDSPM_SYNC_CHECK("ADAT2 SyncCheck", 4),
4573 HDSPM_SYNC_CHECK("ADAT3 SyncCheck", 5),
4574 HDSPM_SYNC_CHECK("ADAT4 SyncCheck", 6),
4575 HDSPM_SYNC_CHECK("TCO SyncCheck", 7),
4576 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 8),
4577 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4578 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4579 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4580 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT1 Frequency", 3),
4581 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT2 Frequency", 4),
4582 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT3 Frequency", 5),
4583 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT4 Frequency", 6),
4584 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 7),
Adrian Knoth11a5cd32013-07-05 11:27:57 +02004585 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8),
4586 HDSPM_TOGGLE_SETTING("S/PDIF Out Professional", HDSPM_c0_Pro),
4587 HDSPM_TOGGLE_SETTING("Single Speed WordClock Out", HDSPM_c0_Wck48)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004588};
4589
4590static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
4591 HDSPM_MIXER("Mixer", 0),
4592 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4593 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4594 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4595 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4596 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Adrian Knoth2d63ec32013-07-05 11:28:18 +02004597 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 11),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004598 HDSPM_SYNC_CHECK("WC Sync Check", 0),
4599 HDSPM_SYNC_CHECK("AES1 Sync Check", 1),
4600 HDSPM_SYNC_CHECK("AES2 Sync Check", 2),
4601 HDSPM_SYNC_CHECK("AES3 Sync Check", 3),
4602 HDSPM_SYNC_CHECK("AES4 Sync Check", 4),
4603 HDSPM_SYNC_CHECK("AES5 Sync Check", 5),
4604 HDSPM_SYNC_CHECK("AES6 Sync Check", 6),
4605 HDSPM_SYNC_CHECK("AES7 Sync Check", 7),
4606 HDSPM_SYNC_CHECK("AES8 Sync Check", 8),
4607 HDSPM_SYNC_CHECK("TCO Sync Check", 9),
4608 HDSPM_SYNC_CHECK("SYNC IN Sync Check", 10),
4609 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4610 HDSPM_AUTOSYNC_SAMPLE_RATE("AES1 Frequency", 1),
4611 HDSPM_AUTOSYNC_SAMPLE_RATE("AES2 Frequency", 2),
4612 HDSPM_AUTOSYNC_SAMPLE_RATE("AES3 Frequency", 3),
4613 HDSPM_AUTOSYNC_SAMPLE_RATE("AES4 Frequency", 4),
4614 HDSPM_AUTOSYNC_SAMPLE_RATE("AES5 Frequency", 5),
4615 HDSPM_AUTOSYNC_SAMPLE_RATE("AES6 Frequency", 6),
4616 HDSPM_AUTOSYNC_SAMPLE_RATE("AES7 Frequency", 7),
4617 HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8),
4618 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9),
4619 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10),
Adrian Knothc9e16682012-12-03 14:55:50 +01004620 HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
4621 HDSPM_TOGGLE_SETTING("Emphasis", HDSPM_Emphasis),
4622 HDSPM_TOGGLE_SETTING("Non Audio", HDSPM_Dolby),
4623 HDSPM_TOGGLE_SETTING("Professional", HDSPM_Professional),
4624 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004625 HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
4626 HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
4627};
4628
Adrian Knoth0dca1792011-01-26 19:32:14 +01004629
4630
4631/* Control elements for the optional TCO module */
4632static struct snd_kcontrol_new snd_hdspm_controls_tco[] = {
4633 HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0),
4634 HDSPM_TCO_PULL("TCO Pull", 0),
4635 HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0),
4636 HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0),
4637 HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0),
Adrian Knotha8176502013-03-10 00:37:27 +01004638 HDSPM_TCO_WORD_TERM("TCO Word Term", 0),
4639 HDSPM_TCO_LOCK_CHECK("TCO Input Check", 11),
4640 HDSPM_TCO_LOCK_CHECK("TCO LTC Valid", 12),
4641 HDSPM_TCO_LTC_FRAMES("TCO Detected Frame Rate", 0),
4642 HDSPM_TCO_VIDEO_INPUT_FORMAT("Video Input Format", 0)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004643};
4644
4645
Takashi Iwai98274f02005-11-17 14:52:34 +01004646static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
Takashi Iwai763f3562005-06-03 11:25:34 +02004647
4648
Takashi Iwai98274f02005-11-17 14:52:34 +01004649static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004650{
4651 int i;
4652
Adrian Knoth0dca1792011-01-26 19:32:14 +01004653 for (i = hdspm->ds_out_channels; i < hdspm->ss_out_channels; ++i) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004654 if (hdspm->system_sample_rate > 48000) {
4655 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004656 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
4657 SNDRV_CTL_ELEM_ACCESS_READ |
4658 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004659 } else {
4660 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004661 SNDRV_CTL_ELEM_ACCESS_READWRITE |
4662 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004663 }
4664 snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
Adrian Knoth0dca1792011-01-26 19:32:14 +01004665 SNDRV_CTL_EVENT_MASK_INFO,
4666 &hdspm->playback_mixer_ctls[i]->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02004667 }
4668
4669 return 0;
4670}
4671
4672
Adrian Knoth0dca1792011-01-26 19:32:14 +01004673static int snd_hdspm_create_controls(struct snd_card *card,
4674 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004675{
4676 unsigned int idx, limit;
4677 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01004678 struct snd_kcontrol *kctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004679 struct snd_kcontrol_new *list = NULL;
Takashi Iwai763f3562005-06-03 11:25:34 +02004680
Adrian Knoth0dca1792011-01-26 19:32:14 +01004681 switch (hdspm->io_type) {
4682 case MADI:
4683 list = snd_hdspm_controls_madi;
4684 limit = ARRAY_SIZE(snd_hdspm_controls_madi);
4685 break;
4686 case MADIface:
4687 list = snd_hdspm_controls_madiface;
4688 limit = ARRAY_SIZE(snd_hdspm_controls_madiface);
4689 break;
4690 case AIO:
4691 list = snd_hdspm_controls_aio;
4692 limit = ARRAY_SIZE(snd_hdspm_controls_aio);
4693 break;
4694 case RayDAT:
4695 list = snd_hdspm_controls_raydat;
4696 limit = ARRAY_SIZE(snd_hdspm_controls_raydat);
4697 break;
4698 case AES32:
4699 list = snd_hdspm_controls_aes32;
4700 limit = ARRAY_SIZE(snd_hdspm_controls_aes32);
4701 break;
4702 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004703
Adrian Knoth0dca1792011-01-26 19:32:14 +01004704 if (NULL != list) {
4705 for (idx = 0; idx < limit; idx++) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004706 err = snd_ctl_add(card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004707 snd_ctl_new1(&list[idx], hdspm));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004708 if (err < 0)
4709 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004710 }
4711 }
4712
Takashi Iwai763f3562005-06-03 11:25:34 +02004713
Adrian Knoth0dca1792011-01-26 19:32:14 +01004714 /* create simple 1:1 playback mixer controls */
Takashi Iwai763f3562005-06-03 11:25:34 +02004715 snd_hdspm_playback_mixer.name = "Chn";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004716 if (hdspm->system_sample_rate >= 128000) {
4717 limit = hdspm->qs_out_channels;
4718 } else if (hdspm->system_sample_rate >= 64000) {
4719 limit = hdspm->ds_out_channels;
4720 } else {
4721 limit = hdspm->ss_out_channels;
4722 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004723 for (idx = 0; idx < limit; ++idx) {
4724 snd_hdspm_playback_mixer.index = idx + 1;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004725 kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm);
4726 err = snd_ctl_add(card, kctl);
4727 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004728 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004729 hdspm->playback_mixer_ctls[idx] = kctl;
4730 }
4731
Adrian Knoth0dca1792011-01-26 19:32:14 +01004732
4733 if (hdspm->tco) {
4734 /* add tco control elements */
4735 list = snd_hdspm_controls_tco;
4736 limit = ARRAY_SIZE(snd_hdspm_controls_tco);
4737 for (idx = 0; idx < limit; idx++) {
4738 err = snd_ctl_add(card,
4739 snd_ctl_new1(&list[idx], hdspm));
4740 if (err < 0)
4741 return err;
4742 }
4743 }
4744
Takashi Iwai763f3562005-06-03 11:25:34 +02004745 return 0;
4746}
4747
4748/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01004749 /proc interface
Takashi Iwai763f3562005-06-03 11:25:34 +02004750 ------------------------------------------------------------*/
4751
4752static void
Adrian Knoth57601072013-07-05 11:28:04 +02004753snd_hdspm_proc_read_tco(struct snd_info_entry *entry,
4754 struct snd_info_buffer *buffer)
Takashi Iwai763f3562005-06-03 11:25:34 +02004755{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004756 struct hdspm *hdspm = entry->private_data;
Adrian Knoth57601072013-07-05 11:28:04 +02004757 unsigned int status, control;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004758 int a, ltc, frames, seconds, minutes, hours;
4759 unsigned int period;
4760 u64 freq_const = 0;
4761 u32 rate;
4762
Adrian Knoth57601072013-07-05 11:28:04 +02004763 snd_iprintf(buffer, "--- TCO ---\n");
4764
Takashi Iwai763f3562005-06-03 11:25:34 +02004765 status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004766 control = hdspm->control_register;
Takashi Iwai763f3562005-06-03 11:25:34 +02004767
Adrian Knoth0dca1792011-01-26 19:32:14 +01004768
Adrian Knoth0dca1792011-01-26 19:32:14 +01004769 if (status & HDSPM_tco_detect) {
4770 snd_iprintf(buffer, "TCO module detected.\n");
4771 a = hdspm_read(hdspm, HDSPM_RD_TCO+4);
4772 if (a & HDSPM_TCO1_LTC_Input_valid) {
4773 snd_iprintf(buffer, " LTC valid, ");
4774 switch (a & (HDSPM_TCO1_LTC_Format_LSB |
4775 HDSPM_TCO1_LTC_Format_MSB)) {
4776 case 0:
4777 snd_iprintf(buffer, "24 fps, ");
4778 break;
4779 case HDSPM_TCO1_LTC_Format_LSB:
4780 snd_iprintf(buffer, "25 fps, ");
4781 break;
4782 case HDSPM_TCO1_LTC_Format_MSB:
4783 snd_iprintf(buffer, "29.97 fps, ");
4784 break;
4785 default:
4786 snd_iprintf(buffer, "30 fps, ");
4787 break;
4788 }
4789 if (a & HDSPM_TCO1_set_drop_frame_flag) {
4790 snd_iprintf(buffer, "drop frame\n");
4791 } else {
4792 snd_iprintf(buffer, "full frame\n");
4793 }
4794 } else {
4795 snd_iprintf(buffer, " no LTC\n");
4796 }
4797 if (a & HDSPM_TCO1_Video_Input_Format_NTSC) {
4798 snd_iprintf(buffer, " Video: NTSC\n");
4799 } else if (a & HDSPM_TCO1_Video_Input_Format_PAL) {
4800 snd_iprintf(buffer, " Video: PAL\n");
4801 } else {
4802 snd_iprintf(buffer, " No video\n");
4803 }
4804 if (a & HDSPM_TCO1_TCO_lock) {
4805 snd_iprintf(buffer, " Sync: lock\n");
4806 } else {
4807 snd_iprintf(buffer, " Sync: no lock\n");
4808 }
4809
4810 switch (hdspm->io_type) {
4811 case MADI:
4812 case AES32:
4813 freq_const = 110069313433624ULL;
4814 break;
4815 case RayDAT:
4816 case AIO:
4817 freq_const = 104857600000000ULL;
4818 break;
4819 case MADIface:
4820 break; /* no TCO possible */
4821 }
4822
4823 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
4824 snd_iprintf(buffer, " period: %u\n", period);
4825
4826
4827 /* rate = freq_const/period; */
4828 rate = div_u64(freq_const, period);
4829
4830 if (control & HDSPM_QuadSpeed) {
4831 rate *= 4;
4832 } else if (control & HDSPM_DoubleSpeed) {
4833 rate *= 2;
4834 }
4835
4836 snd_iprintf(buffer, " Frequency: %u Hz\n",
4837 (unsigned int) rate);
4838
4839 ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
4840 frames = ltc & 0xF;
4841 ltc >>= 4;
4842 frames += (ltc & 0x3) * 10;
4843 ltc >>= 4;
4844 seconds = ltc & 0xF;
4845 ltc >>= 4;
4846 seconds += (ltc & 0x7) * 10;
4847 ltc >>= 4;
4848 minutes = ltc & 0xF;
4849 ltc >>= 4;
4850 minutes += (ltc & 0x7) * 10;
4851 ltc >>= 4;
4852 hours = ltc & 0xF;
4853 ltc >>= 4;
4854 hours += (ltc & 0x3) * 10;
4855 snd_iprintf(buffer,
4856 " LTC In: %02d:%02d:%02d:%02d\n",
4857 hours, minutes, seconds, frames);
4858
4859 } else {
4860 snd_iprintf(buffer, "No TCO module detected.\n");
4861 }
Adrian Knoth57601072013-07-05 11:28:04 +02004862}
4863
4864static void
4865snd_hdspm_proc_read_madi(struct snd_info_entry *entry,
4866 struct snd_info_buffer *buffer)
4867{
4868 struct hdspm *hdspm = entry->private_data;
Sudip Mukherjeedf57de12014-10-29 20:09:45 +05304869 unsigned int status, status2;
Adrian Knoth57601072013-07-05 11:28:04 +02004870
4871 char *pref_sync_ref;
4872 char *autosync_ref;
4873 char *system_clock_mode;
Adrian Knoth57601072013-07-05 11:28:04 +02004874 int x, x2;
4875
4876 status = hdspm_read(hdspm, HDSPM_statusRegister);
4877 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth57601072013-07-05 11:28:04 +02004878
4879 snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
4880 hdspm->card_name, hdspm->card->number + 1,
4881 hdspm->firmware_rev,
4882 (status2 & HDSPM_version0) |
4883 (status2 & HDSPM_version1) | (status2 &
4884 HDSPM_version2));
4885
4886 snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n",
4887 (hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF,
4888 hdspm->serial);
4889
4890 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
4891 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
4892
4893 snd_iprintf(buffer, "--- System ---\n");
4894
4895 snd_iprintf(buffer,
4896 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4897 status & HDSPM_audioIRQPending,
4898 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4899 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4900 hdspm->irq_count);
4901 snd_iprintf(buffer,
4902 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4903 "estimated= %ld (bytes)\n",
4904 ((status & HDSPM_BufferID) ? 1 : 0),
4905 (status & HDSPM_BufferPositionMask),
4906 (status & HDSPM_BufferPositionMask) %
4907 (2 * (int)hdspm->period_bytes),
4908 ((status & HDSPM_BufferPositionMask) - 64) %
4909 (2 * (int)hdspm->period_bytes),
4910 (long) hdspm_hw_pointer(hdspm) * 4);
4911
4912 snd_iprintf(buffer,
4913 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4914 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4915 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4916 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4917 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
4918 snd_iprintf(buffer,
4919 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4920 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4921 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4922 snd_iprintf(buffer,
4923 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4924 "status2=0x%x\n",
4925 hdspm->control_register, hdspm->control2_register,
4926 status, status2);
4927
Takashi Iwai763f3562005-06-03 11:25:34 +02004928
4929 snd_iprintf(buffer, "--- Settings ---\n");
4930
Adrian Knoth7cb155f2011-08-15 00:22:53 +02004931 x = hdspm_get_latency(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02004932
4933 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004934 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4935 x, (unsigned long) hdspm->period_bytes);
Takashi Iwai763f3562005-06-03 11:25:34 +02004936
Adrian Knoth0dca1792011-01-26 19:32:14 +01004937 snd_iprintf(buffer, "Line out: %s\n",
4938 (hdspm->control_register & HDSPM_LineOut) ? "on " : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004939
Takashi Iwai763f3562005-06-03 11:25:34 +02004940 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004941 "ClearTrackMarker = %s, Transmit in %s Channel Mode, "
4942 "Auto Input %s\n",
4943 (hdspm->control_register & HDSPM_clr_tms) ? "on" : "off",
4944 (hdspm->control_register & HDSPM_TX_64ch) ? "64" : "56",
4945 (hdspm->control_register & HDSPM_AutoInp) ? "on" : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004946
Adrian Knoth0dca1792011-01-26 19:32:14 +01004947
Remy Bruno3cee5a62006-10-16 12:46:32 +02004948 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
Adrian Knoth0dca1792011-01-26 19:32:14 +01004949 system_clock_mode = "AutoSync";
Remy Bruno3cee5a62006-10-16 12:46:32 +02004950 else
Takashi Iwai763f3562005-06-03 11:25:34 +02004951 system_clock_mode = "Master";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004952 snd_iprintf(buffer, "AutoSync Reference: %s\n", system_clock_mode);
Takashi Iwai763f3562005-06-03 11:25:34 +02004953
4954 switch (hdspm_pref_sync_ref(hdspm)) {
4955 case HDSPM_SYNC_FROM_WORD:
4956 pref_sync_ref = "Word Clock";
4957 break;
4958 case HDSPM_SYNC_FROM_MADI:
4959 pref_sync_ref = "MADI Sync";
4960 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004961 case HDSPM_SYNC_FROM_TCO:
4962 pref_sync_ref = "TCO";
4963 break;
4964 case HDSPM_SYNC_FROM_SYNC_IN:
4965 pref_sync_ref = "Sync In";
4966 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004967 default:
4968 pref_sync_ref = "XXXX Clock";
4969 break;
4970 }
4971 snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004972 pref_sync_ref);
Takashi Iwai763f3562005-06-03 11:25:34 +02004973
4974 snd_iprintf(buffer, "System Clock Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004975 hdspm->system_sample_rate);
Takashi Iwai763f3562005-06-03 11:25:34 +02004976
4977
4978 snd_iprintf(buffer, "--- Status:\n");
4979
4980 x = status & HDSPM_madiSync;
4981 x2 = status2 & HDSPM_wcSync;
4982
4983 snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004984 (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
4985 "NoLock",
4986 (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
4987 "NoLock");
Takashi Iwai763f3562005-06-03 11:25:34 +02004988
4989 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004990 case HDSPM_AUTOSYNC_FROM_SYNC_IN:
4991 autosync_ref = "Sync In";
4992 break;
4993 case HDSPM_AUTOSYNC_FROM_TCO:
4994 autosync_ref = "TCO";
4995 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004996 case HDSPM_AUTOSYNC_FROM_WORD:
4997 autosync_ref = "Word Clock";
4998 break;
4999 case HDSPM_AUTOSYNC_FROM_MADI:
5000 autosync_ref = "MADI Sync";
5001 break;
5002 case HDSPM_AUTOSYNC_FROM_NONE:
5003 autosync_ref = "Input not valid";
5004 break;
5005 default:
5006 autosync_ref = "---";
5007 break;
5008 }
5009 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005010 "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
5011 autosync_ref, hdspm_external_sample_rate(hdspm),
5012 (status & HDSPM_madiFreqMask) >> 22,
5013 (status2 & HDSPM_wcFreqMask) >> 5);
Takashi Iwai763f3562005-06-03 11:25:34 +02005014
5015 snd_iprintf(buffer, "Input: %s, Mode=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01005016 (status & HDSPM_AB_int) ? "Coax" : "Optical",
5017 (status & HDSPM_RX_64ch) ? "64 channels" :
5018 "56 channels");
Takashi Iwai763f3562005-06-03 11:25:34 +02005019
Adrian Knoth57601072013-07-05 11:28:04 +02005020 /* call readout function for TCO specific status */
5021 snd_hdspm_proc_read_tco(entry, buffer);
5022
Takashi Iwai763f3562005-06-03 11:25:34 +02005023 snd_iprintf(buffer, "\n");
5024}
5025
Remy Bruno3cee5a62006-10-16 12:46:32 +02005026static void
5027snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
5028 struct snd_info_buffer *buffer)
5029{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005030 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005031 unsigned int status;
5032 unsigned int status2;
5033 unsigned int timecode;
Andre Schramm56bde0f2013-01-09 14:40:18 +01005034 unsigned int wcLock, wcSync;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005035 int pref_syncref;
5036 char *autosync_ref;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005037 int x;
5038
5039 status = hdspm_read(hdspm, HDSPM_statusRegister);
5040 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
5041 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
5042
5043 snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
5044 hdspm->card_name, hdspm->card->number + 1,
5045 hdspm->firmware_rev);
5046
5047 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
5048 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
5049
5050 snd_iprintf(buffer, "--- System ---\n");
5051
5052 snd_iprintf(buffer,
5053 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
5054 status & HDSPM_audioIRQPending,
5055 (status & HDSPM_midi0IRQPending) ? 1 : 0,
5056 (status & HDSPM_midi1IRQPending) ? 1 : 0,
5057 hdspm->irq_count);
5058 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005059 "HW pointer: id = %d, rawptr = %d (%d->%d) "
5060 "estimated= %ld (bytes)\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005061 ((status & HDSPM_BufferID) ? 1 : 0),
5062 (status & HDSPM_BufferPositionMask),
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005063 (status & HDSPM_BufferPositionMask) %
5064 (2 * (int)hdspm->period_bytes),
5065 ((status & HDSPM_BufferPositionMask) - 64) %
5066 (2 * (int)hdspm->period_bytes),
Remy Bruno3cee5a62006-10-16 12:46:32 +02005067 (long) hdspm_hw_pointer(hdspm) * 4);
5068
5069 snd_iprintf(buffer,
5070 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
5071 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
5072 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
5073 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
5074 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
5075 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005076 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
5077 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
5078 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
5079 snd_iprintf(buffer,
5080 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
5081 "status2=0x%x\n",
5082 hdspm->control_register, hdspm->control2_register,
5083 status, status2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02005084
5085 snd_iprintf(buffer, "--- Settings ---\n");
5086
Adrian Knoth7cb155f2011-08-15 00:22:53 +02005087 x = hdspm_get_latency(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02005088
5089 snd_iprintf(buffer,
5090 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
5091 x, (unsigned long) hdspm->period_bytes);
5092
Adrian Knoth0dca1792011-01-26 19:32:14 +01005093 snd_iprintf(buffer, "Line out: %s\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005094 (hdspm->
Adrian Knoth0dca1792011-01-26 19:32:14 +01005095 control_register & HDSPM_LineOut) ? "on " : "off");
Remy Bruno3cee5a62006-10-16 12:46:32 +02005096
5097 snd_iprintf(buffer,
5098 "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
5099 (hdspm->
5100 control_register & HDSPM_clr_tms) ? "on" : "off",
5101 (hdspm->
5102 control_register & HDSPM_Emphasis) ? "on" : "off",
5103 (hdspm->
5104 control_register & HDSPM_Dolby) ? "on" : "off");
5105
Remy Bruno3cee5a62006-10-16 12:46:32 +02005106
5107 pref_syncref = hdspm_pref_sync_ref(hdspm);
5108 if (pref_syncref == 0)
5109 snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
5110 else
5111 snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
5112 pref_syncref);
5113
5114 snd_iprintf(buffer, "System Clock Frequency: %d\n",
5115 hdspm->system_sample_rate);
5116
5117 snd_iprintf(buffer, "Double speed: %s\n",
5118 hdspm->control_register & HDSPM_DS_DoubleWire?
5119 "Double wire" : "Single wire");
5120 snd_iprintf(buffer, "Quad speed: %s\n",
5121 hdspm->control_register & HDSPM_QS_DoubleWire?
5122 "Double wire" :
5123 hdspm->control_register & HDSPM_QS_QuadWire?
5124 "Quad wire" : "Single wire");
5125
5126 snd_iprintf(buffer, "--- Status:\n");
5127
Andre Schramm56bde0f2013-01-09 14:40:18 +01005128 wcLock = status & HDSPM_AES32_wcLock;
5129 wcSync = wcLock && (status & HDSPM_AES32_wcSync);
5130
Remy Bruno3cee5a62006-10-16 12:46:32 +02005131 snd_iprintf(buffer, "Word: %s Frequency: %d\n",
Andre Schramm56bde0f2013-01-09 14:40:18 +01005132 (wcLock) ? (wcSync ? "Sync " : "Lock ") : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005133 HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02005134
5135 for (x = 0; x < 8; x++) {
5136 snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005137 x+1,
5138 (status2 & (HDSPM_LockAES >> x)) ?
Adrian Knoth0dca1792011-01-26 19:32:14 +01005139 "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005140 HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02005141 }
5142
5143 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005144 case HDSPM_AES32_AUTOSYNC_FROM_NONE:
5145 autosync_ref = "None"; break;
5146 case HDSPM_AES32_AUTOSYNC_FROM_WORD:
5147 autosync_ref = "Word Clock"; break;
5148 case HDSPM_AES32_AUTOSYNC_FROM_AES1:
5149 autosync_ref = "AES1"; break;
5150 case HDSPM_AES32_AUTOSYNC_FROM_AES2:
5151 autosync_ref = "AES2"; break;
5152 case HDSPM_AES32_AUTOSYNC_FROM_AES3:
5153 autosync_ref = "AES3"; break;
5154 case HDSPM_AES32_AUTOSYNC_FROM_AES4:
5155 autosync_ref = "AES4"; break;
5156 case HDSPM_AES32_AUTOSYNC_FROM_AES5:
5157 autosync_ref = "AES5"; break;
5158 case HDSPM_AES32_AUTOSYNC_FROM_AES6:
5159 autosync_ref = "AES6"; break;
5160 case HDSPM_AES32_AUTOSYNC_FROM_AES7:
5161 autosync_ref = "AES7"; break;
5162 case HDSPM_AES32_AUTOSYNC_FROM_AES8:
5163 autosync_ref = "AES8"; break;
Adrian Knoth194062d2013-07-05 11:28:16 +02005164 case HDSPM_AES32_AUTOSYNC_FROM_TCO:
5165 autosync_ref = "TCO"; break;
5166 case HDSPM_AES32_AUTOSYNC_FROM_SYNC_IN:
5167 autosync_ref = "Sync In"; break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005168 default:
5169 autosync_ref = "---"; break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005170 }
5171 snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
5172
Adrian Knoth194062d2013-07-05 11:28:16 +02005173 /* call readout function for TCO specific status */
5174 snd_hdspm_proc_read_tco(entry, buffer);
5175
Remy Bruno3cee5a62006-10-16 12:46:32 +02005176 snd_iprintf(buffer, "\n");
5177}
5178
Adrian Knoth0dca1792011-01-26 19:32:14 +01005179static void
5180snd_hdspm_proc_read_raydat(struct snd_info_entry *entry,
5181 struct snd_info_buffer *buffer)
5182{
5183 struct hdspm *hdspm = entry->private_data;
Sudip Mukherjeedf57de12014-10-29 20:09:45 +05305184 unsigned int status1, status2, status3, i;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005185 unsigned int lock, sync;
5186
5187 status1 = hdspm_read(hdspm, HDSPM_RD_STATUS_1); /* s1 */
5188 status2 = hdspm_read(hdspm, HDSPM_RD_STATUS_2); /* freq */
5189 status3 = hdspm_read(hdspm, HDSPM_RD_STATUS_3); /* s2 */
5190
Adrian Knoth0dca1792011-01-26 19:32:14 +01005191 snd_iprintf(buffer, "STATUS1: 0x%08x\n", status1);
5192 snd_iprintf(buffer, "STATUS2: 0x%08x\n", status2);
5193 snd_iprintf(buffer, "STATUS3: 0x%08x\n", status3);
5194
5195
5196 snd_iprintf(buffer, "\n*** CLOCK MODE\n\n");
5197
5198 snd_iprintf(buffer, "Clock mode : %s\n",
5199 (hdspm_system_clock_mode(hdspm) == 0) ? "master" : "slave");
5200 snd_iprintf(buffer, "System frequency: %d Hz\n",
5201 hdspm_get_system_sample_rate(hdspm));
5202
5203 snd_iprintf(buffer, "\n*** INPUT STATUS\n\n");
5204
5205 lock = 0x1;
5206 sync = 0x100;
5207
5208 for (i = 0; i < 8; i++) {
5209 snd_iprintf(buffer, "s1_input %d: Lock %d, Sync %d, Freq %s\n",
5210 i,
5211 (status1 & lock) ? 1 : 0,
5212 (status1 & sync) ? 1 : 0,
5213 texts_freq[(status2 >> (i * 4)) & 0xF]);
5214
5215 lock = lock<<1;
5216 sync = sync<<1;
5217 }
5218
5219 snd_iprintf(buffer, "WC input: Lock %d, Sync %d, Freq %s\n",
5220 (status1 & 0x1000000) ? 1 : 0,
5221 (status1 & 0x2000000) ? 1 : 0,
5222 texts_freq[(status1 >> 16) & 0xF]);
5223
5224 snd_iprintf(buffer, "TCO input: Lock %d, Sync %d, Freq %s\n",
5225 (status1 & 0x4000000) ? 1 : 0,
5226 (status1 & 0x8000000) ? 1 : 0,
5227 texts_freq[(status1 >> 20) & 0xF]);
5228
5229 snd_iprintf(buffer, "SYNC IN: Lock %d, Sync %d, Freq %s\n",
5230 (status3 & 0x400) ? 1 : 0,
5231 (status3 & 0x800) ? 1 : 0,
5232 texts_freq[(status2 >> 12) & 0xF]);
5233
5234}
5235
Remy Bruno3cee5a62006-10-16 12:46:32 +02005236#ifdef CONFIG_SND_DEBUG
5237static void
Adrian Knoth0dca1792011-01-26 19:32:14 +01005238snd_hdspm_proc_read_debug(struct snd_info_entry *entry,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005239 struct snd_info_buffer *buffer)
5240{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005241 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005242
5243 int j,i;
5244
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005245 for (i = 0; i < 256 /* 1024*64 */; i += j) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02005246 snd_iprintf(buffer, "0x%08X: ", i);
5247 for (j = 0; j < 16; j += 4)
5248 snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
5249 snd_iprintf(buffer, "\n");
5250 }
5251}
5252#endif
5253
5254
Adrian Knoth0dca1792011-01-26 19:32:14 +01005255static void snd_hdspm_proc_ports_in(struct snd_info_entry *entry,
5256 struct snd_info_buffer *buffer)
5257{
5258 struct hdspm *hdspm = entry->private_data;
5259 int i;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005260
Adrian Knoth0dca1792011-01-26 19:32:14 +01005261 snd_iprintf(buffer, "# generated by hdspm\n");
5262
5263 for (i = 0; i < hdspm->max_channels_in; i++) {
5264 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_in[i]);
5265 }
5266}
5267
5268static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry,
5269 struct snd_info_buffer *buffer)
5270{
5271 struct hdspm *hdspm = entry->private_data;
5272 int i;
5273
5274 snd_iprintf(buffer, "# generated by hdspm\n");
5275
5276 for (i = 0; i < hdspm->max_channels_out; i++) {
5277 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_out[i]);
5278 }
5279}
5280
5281
Bill Pembertone23e7a12012-12-06 12:35:10 -05005282static void snd_hdspm_proc_init(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005283{
Takashi Iwai98274f02005-11-17 14:52:34 +01005284 struct snd_info_entry *entry;
Takashi Iwai763f3562005-06-03 11:25:34 +02005285
Adrian Knoth0dca1792011-01-26 19:32:14 +01005286 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) {
5287 switch (hdspm->io_type) {
5288 case AES32:
5289 snd_info_set_text_ops(entry, hdspm,
5290 snd_hdspm_proc_read_aes32);
5291 break;
5292 case MADI:
5293 snd_info_set_text_ops(entry, hdspm,
5294 snd_hdspm_proc_read_madi);
5295 break;
5296 case MADIface:
5297 /* snd_info_set_text_ops(entry, hdspm,
5298 snd_hdspm_proc_read_madiface); */
5299 break;
5300 case RayDAT:
5301 snd_info_set_text_ops(entry, hdspm,
5302 snd_hdspm_proc_read_raydat);
5303 break;
5304 case AIO:
5305 break;
5306 }
5307 }
5308
5309 if (!snd_card_proc_new(hdspm->card, "ports.in", &entry)) {
5310 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_in);
5311 }
5312
5313 if (!snd_card_proc_new(hdspm->card, "ports.out", &entry)) {
5314 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_out);
5315 }
5316
Remy Bruno3cee5a62006-10-16 12:46:32 +02005317#ifdef CONFIG_SND_DEBUG
5318 /* debug file to read all hdspm registers */
5319 if (!snd_card_proc_new(hdspm->card, "debug", &entry))
5320 snd_info_set_text_ops(entry, hdspm,
5321 snd_hdspm_proc_read_debug);
5322#endif
Takashi Iwai763f3562005-06-03 11:25:34 +02005323}
5324
5325/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005326 hdspm intitialize
Takashi Iwai763f3562005-06-03 11:25:34 +02005327 ------------------------------------------------------------*/
5328
Takashi Iwai98274f02005-11-17 14:52:34 +01005329static int snd_hdspm_set_defaults(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005330{
Takashi Iwai763f3562005-06-03 11:25:34 +02005331 /* ASSUMPTION: hdspm->lock is either held, or there is no need to
Joe Perches561de312007-12-18 13:13:47 +01005332 hold it (e.g. during module initialization).
Adrian Knoth0dca1792011-01-26 19:32:14 +01005333 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005334
5335 /* set defaults: */
5336
Adrian Knoth0dca1792011-01-26 19:32:14 +01005337 hdspm->settings_register = 0;
5338
5339 switch (hdspm->io_type) {
5340 case MADI:
5341 case MADIface:
5342 hdspm->control_register =
5343 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5344 break;
5345
5346 case RayDAT:
5347 case AIO:
5348 hdspm->settings_register = 0x1 + 0x1000;
5349 /* Magic values are: LAT_0, LAT_2, Master, freq1, tx64ch, inp_0,
5350 * line_out */
5351 hdspm->control_register =
5352 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5353 break;
5354
5355 case AES32:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005356 hdspm->control_register =
Adrian Knothe71b95a2013-07-05 11:28:06 +02005357 HDSPM_ClockModeMaster | /* Master Clock Mode on */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005358 hdspm_encode_latency(7) | /* latency max=8192samples */
Remy Bruno3cee5a62006-10-16 12:46:32 +02005359 HDSPM_SyncRef0 | /* AES1 is syncclock */
5360 HDSPM_LineOut | /* Analog output in */
5361 HDSPM_Professional; /* Professional mode */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005362 break;
5363 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005364
5365 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5366
Adrian Knoth0dca1792011-01-26 19:32:14 +01005367 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005368 /* No control2 register for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005369#ifdef SNDRV_BIG_ENDIAN
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005370 hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
Takashi Iwai763f3562005-06-03 11:25:34 +02005371#else
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005372 hdspm->control2_register = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005373#endif
5374
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005375 hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
5376 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005377 hdspm_compute_period_size(hdspm);
5378
5379 /* silence everything */
5380
5381 all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
5382
Adrian Knothb2ed6322013-07-05 11:27:54 +02005383 if (hdspm_is_raydat_or_aio(hdspm))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005384 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
Takashi Iwai763f3562005-06-03 11:25:34 +02005385
5386 /* set a default rate so that the channel map is set up. */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005387 hdspm_set_rate(hdspm, 48000, 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02005388
5389 return 0;
5390}
5391
5392
5393/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005394 interrupt
Takashi Iwai763f3562005-06-03 11:25:34 +02005395 ------------------------------------------------------------*/
5396
David Howells7d12e782006-10-05 14:55:46 +01005397static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02005398{
Takashi Iwai98274f02005-11-17 14:52:34 +01005399 struct hdspm *hdspm = (struct hdspm *) dev_id;
Takashi Iwai763f3562005-06-03 11:25:34 +02005400 unsigned int status;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005401 int i, audio, midi, schedule = 0;
5402 /* cycles_t now; */
Takashi Iwai763f3562005-06-03 11:25:34 +02005403
5404 status = hdspm_read(hdspm, HDSPM_statusRegister);
5405
5406 audio = status & HDSPM_audioIRQPending;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005407 midi = status & (HDSPM_midi0IRQPending | HDSPM_midi1IRQPending |
5408 HDSPM_midi2IRQPending | HDSPM_midi3IRQPending);
Takashi Iwai763f3562005-06-03 11:25:34 +02005409
Adrian Knoth0dca1792011-01-26 19:32:14 +01005410 /* now = get_cycles(); */
Takashi Iwaiddcecf62014-11-10 17:24:26 +01005411 /*
Adrian Knoth0dca1792011-01-26 19:32:14 +01005412 * LAT_2..LAT_0 period counter (win) counter (mac)
5413 * 6 4096 ~256053425 ~514672358
5414 * 5 2048 ~128024983 ~257373821
5415 * 4 1024 ~64023706 ~128718089
5416 * 3 512 ~32005945 ~64385999
5417 * 2 256 ~16003039 ~32260176
5418 * 1 128 ~7998738 ~16194507
5419 * 0 64 ~3998231 ~8191558
Takashi Iwaiddcecf62014-11-10 17:24:26 +01005420 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005421 /*
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005422 dev_info(hdspm->card->dev, "snd_hdspm_interrupt %llu @ %llx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01005423 now-hdspm->last_interrupt, status & 0xFFC0);
5424 hdspm->last_interrupt = now;
5425 */
5426
5427 if (!audio && !midi)
Takashi Iwai763f3562005-06-03 11:25:34 +02005428 return IRQ_NONE;
5429
5430 hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
5431 hdspm->irq_count++;
5432
Takashi Iwai763f3562005-06-03 11:25:34 +02005433
5434 if (audio) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005435 if (hdspm->capture_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005436 snd_pcm_period_elapsed(hdspm->capture_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005437
5438 if (hdspm->playback_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005439 snd_pcm_period_elapsed(hdspm->playback_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005440 }
5441
Adrian Knoth0dca1792011-01-26 19:32:14 +01005442 if (midi) {
5443 i = 0;
5444 while (i < hdspm->midiPorts) {
5445 if ((hdspm_read(hdspm,
5446 hdspm->midi[i].statusIn) & 0xff) &&
5447 (status & hdspm->midi[i].irq)) {
5448 /* we disable interrupts for this input until
5449 * processing is done
5450 */
5451 hdspm->control_register &= ~hdspm->midi[i].ie;
5452 hdspm_write(hdspm, HDSPM_controlRegister,
5453 hdspm->control_register);
5454 hdspm->midi[i].pending = 1;
5455 schedule = 1;
5456 }
5457
5458 i++;
5459 }
5460
5461 if (schedule)
5462 tasklet_hi_schedule(&hdspm->midi_tasklet);
Takashi Iwai763f3562005-06-03 11:25:34 +02005463 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005464
Takashi Iwai763f3562005-06-03 11:25:34 +02005465 return IRQ_HANDLED;
5466}
5467
5468/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005469 pcm interface
Takashi Iwai763f3562005-06-03 11:25:34 +02005470 ------------------------------------------------------------*/
5471
5472
Adrian Knoth0dca1792011-01-26 19:32:14 +01005473static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream
5474 *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005475{
Takashi Iwai98274f02005-11-17 14:52:34 +01005476 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005477 return hdspm_hw_pointer(hdspm);
5478}
5479
Takashi Iwai763f3562005-06-03 11:25:34 +02005480
Takashi Iwai98274f02005-11-17 14:52:34 +01005481static int snd_hdspm_reset(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005482{
Takashi Iwai98274f02005-11-17 14:52:34 +01005483 struct snd_pcm_runtime *runtime = substream->runtime;
5484 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5485 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005486
5487 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5488 other = hdspm->capture_substream;
5489 else
5490 other = hdspm->playback_substream;
5491
5492 if (hdspm->running)
5493 runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
5494 else
5495 runtime->status->hw_ptr = 0;
5496 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005497 struct snd_pcm_substream *s;
5498 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01005499 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005500 if (s == other) {
5501 oruntime->status->hw_ptr =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005502 runtime->status->hw_ptr;
Takashi Iwai763f3562005-06-03 11:25:34 +02005503 break;
5504 }
5505 }
5506 }
5507 return 0;
5508}
5509
Takashi Iwai98274f02005-11-17 14:52:34 +01005510static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
5511 struct snd_pcm_hw_params *params)
Takashi Iwai763f3562005-06-03 11:25:34 +02005512{
Takashi Iwai98274f02005-11-17 14:52:34 +01005513 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005514 int err;
5515 int i;
5516 pid_t this_pid;
5517 pid_t other_pid;
Takashi Iwai763f3562005-06-03 11:25:34 +02005518
5519 spin_lock_irq(&hdspm->lock);
5520
5521 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5522 this_pid = hdspm->playback_pid;
5523 other_pid = hdspm->capture_pid;
5524 } else {
5525 this_pid = hdspm->capture_pid;
5526 other_pid = hdspm->playback_pid;
5527 }
5528
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005529 if (other_pid > 0 && this_pid != other_pid) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005530
5531 /* The other stream is open, and not by the same
5532 task as this one. Make sure that the parameters
5533 that matter are the same.
Adrian Knoth0dca1792011-01-26 19:32:14 +01005534 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005535
5536 if (params_rate(params) != hdspm->system_sample_rate) {
5537 spin_unlock_irq(&hdspm->lock);
5538 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005539 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005540 return -EBUSY;
5541 }
5542
5543 if (params_period_size(params) != hdspm->period_bytes / 4) {
5544 spin_unlock_irq(&hdspm->lock);
5545 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005546 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005547 return -EBUSY;
5548 }
5549
5550 }
5551 /* We're fine. */
5552 spin_unlock_irq(&hdspm->lock);
5553
5554 /* how to make sure that the rate matches an externally-set one ? */
5555
5556 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005557 err = hdspm_set_rate(hdspm, params_rate(params), 0);
5558 if (err < 0) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005559 dev_info(hdspm->card->dev, "err on hdspm_set_rate: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005560 spin_unlock_irq(&hdspm->lock);
5561 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005562 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005563 return err;
5564 }
5565 spin_unlock_irq(&hdspm->lock);
5566
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005567 err = hdspm_set_interrupt_interval(hdspm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005568 params_period_size(params));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005569 if (err < 0) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005570 dev_info(hdspm->card->dev,
5571 "err on hdspm_set_interrupt_interval: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005572 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005573 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005574 return err;
5575 }
5576
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005577 /* Memory allocation, takashi's method, dont know if we should
5578 * spinlock
5579 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005580 /* malloc all buffer even if not enabled to get sure */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005581 /* Update for MADI rev 204: we need to allocate for all channels,
5582 * otherwise it doesn't work at 96kHz */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005583
Takashi Iwai763f3562005-06-03 11:25:34 +02005584 err =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005585 snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
5586 if (err < 0) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005587 dev_info(hdspm->card->dev,
5588 "err on snd_pcm_lib_malloc_pages: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005589 return err;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005590 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005591
Takashi Iwai763f3562005-06-03 11:25:34 +02005592 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5593
Takashi Iwai77a23f22008-08-21 13:00:13 +02005594 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferOut,
Takashi Iwai763f3562005-06-03 11:25:34 +02005595 params_channels(params));
5596
5597 for (i = 0; i < params_channels(params); ++i)
5598 snd_hdspm_enable_out(hdspm, i, 1);
5599
5600 hdspm->playback_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005601 (unsigned char *) substream->runtime->dma_area;
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005602 dev_dbg(hdspm->card->dev,
5603 "Allocated sample buffer for playback at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005604 hdspm->playback_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005605 } else {
Takashi Iwai77a23f22008-08-21 13:00:13 +02005606 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn,
Takashi Iwai763f3562005-06-03 11:25:34 +02005607 params_channels(params));
5608
5609 for (i = 0; i < params_channels(params); ++i)
5610 snd_hdspm_enable_in(hdspm, i, 1);
5611
5612 hdspm->capture_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005613 (unsigned char *) substream->runtime->dma_area;
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005614 dev_dbg(hdspm->card->dev,
5615 "Allocated sample buffer for capture at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005616 hdspm->capture_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005617 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005618
Remy Bruno3cee5a62006-10-16 12:46:32 +02005619 /*
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005620 dev_dbg(hdspm->card->dev,
5621 "Allocated sample buffer for %s at 0x%08X\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005622 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5623 "playback" : "capture",
Takashi Iwai77a23f22008-08-21 13:00:13 +02005624 snd_pcm_sgbuf_get_addr(substream, 0));
Adrian Knoth0dca1792011-01-26 19:32:14 +01005625 */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005626 /*
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005627 dev_dbg(hdspm->card->dev,
5628 "set_hwparams: %s %d Hz, %d channels, bs = %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01005629 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5630 "playback" : "capture",
5631 params_rate(params), params_channels(params),
5632 params_buffer_size(params));
5633 */
5634
5635
Adrian Knoth3ac9b0a2013-07-05 11:28:13 +02005636 /* For AES cards, the float format bit is the same as the
5637 * preferred sync reference. Since we don't want to break
5638 * sync settings, we have to skip the remaining part of this
5639 * function.
5640 */
5641 if (hdspm->io_type == AES32) {
5642 return 0;
5643 }
5644
5645
Adrian Knoth0dca1792011-01-26 19:32:14 +01005646 /* Switch to native float format if requested */
5647 if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) {
5648 if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT))
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005649 dev_info(hdspm->card->dev,
5650 "Switching to native 32bit LE float format.\n");
Adrian Knoth0dca1792011-01-26 19:32:14 +01005651
5652 hdspm->control_register |= HDSPe_FLOAT_FORMAT;
5653 } else if (SNDRV_PCM_FORMAT_S32_LE == params_format(params)) {
5654 if (hdspm->control_register & HDSPe_FLOAT_FORMAT)
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005655 dev_info(hdspm->card->dev,
5656 "Switching to native 32bit LE integer format.\n");
Adrian Knoth0dca1792011-01-26 19:32:14 +01005657
5658 hdspm->control_register &= ~HDSPe_FLOAT_FORMAT;
5659 }
5660 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5661
Takashi Iwai763f3562005-06-03 11:25:34 +02005662 return 0;
5663}
5664
Takashi Iwai98274f02005-11-17 14:52:34 +01005665static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005666{
5667 int i;
Takashi Iwai98274f02005-11-17 14:52:34 +01005668 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005669
5670 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5671
Adrian Knoth0dca1792011-01-26 19:32:14 +01005672 /* params_channels(params) should be enough,
Takashi Iwai763f3562005-06-03 11:25:34 +02005673 but to get sure in case of error */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005674 for (i = 0; i < hdspm->max_channels_out; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005675 snd_hdspm_enable_out(hdspm, i, 0);
5676
5677 hdspm->playback_buffer = NULL;
5678 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005679 for (i = 0; i < hdspm->max_channels_in; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005680 snd_hdspm_enable_in(hdspm, i, 0);
5681
5682 hdspm->capture_buffer = NULL;
5683
5684 }
5685
5686 snd_pcm_lib_free_pages(substream);
5687
5688 return 0;
5689}
5690
Adrian Knoth0dca1792011-01-26 19:32:14 +01005691
Takashi Iwai98274f02005-11-17 14:52:34 +01005692static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005693 struct snd_pcm_channel_info *info)
Takashi Iwai763f3562005-06-03 11:25:34 +02005694{
Takashi Iwai98274f02005-11-17 14:52:34 +01005695 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai44bb2652018-04-24 08:03:14 +02005696 unsigned int channel = info->channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02005697
Adrian Knoth0dca1792011-01-26 19:32:14 +01005698 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
Takashi Iwai44bb2652018-04-24 08:03:14 +02005699 if (snd_BUG_ON(channel >= hdspm->max_channels_out)) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005700 dev_info(hdspm->card->dev,
5701 "snd_hdspm_channel_info: output channel out of range (%d)\n",
Takashi Iwai44bb2652018-04-24 08:03:14 +02005702 channel);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005703 return -EINVAL;
5704 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005705
Takashi Iwai44bb2652018-04-24 08:03:14 +02005706 channel = array_index_nospec(channel, hdspm->max_channels_out);
5707 if (hdspm->channel_map_out[channel] < 0) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005708 dev_info(hdspm->card->dev,
5709 "snd_hdspm_channel_info: output channel %d mapped out\n",
Takashi Iwai44bb2652018-04-24 08:03:14 +02005710 channel);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005711 return -EINVAL;
5712 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005713
Takashi Iwai44bb2652018-04-24 08:03:14 +02005714 info->offset = hdspm->channel_map_out[channel] *
Adrian Knoth0dca1792011-01-26 19:32:14 +01005715 HDSPM_CHANNEL_BUFFER_BYTES;
5716 } else {
Takashi Iwai44bb2652018-04-24 08:03:14 +02005717 if (snd_BUG_ON(channel >= hdspm->max_channels_in)) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005718 dev_info(hdspm->card->dev,
5719 "snd_hdspm_channel_info: input channel out of range (%d)\n",
Takashi Iwai44bb2652018-04-24 08:03:14 +02005720 channel);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005721 return -EINVAL;
5722 }
5723
Takashi Iwai44bb2652018-04-24 08:03:14 +02005724 channel = array_index_nospec(channel, hdspm->max_channels_in);
5725 if (hdspm->channel_map_in[channel] < 0) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005726 dev_info(hdspm->card->dev,
5727 "snd_hdspm_channel_info: input channel %d mapped out\n",
Takashi Iwai44bb2652018-04-24 08:03:14 +02005728 channel);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005729 return -EINVAL;
5730 }
5731
Takashi Iwai44bb2652018-04-24 08:03:14 +02005732 info->offset = hdspm->channel_map_in[channel] *
Adrian Knoth0dca1792011-01-26 19:32:14 +01005733 HDSPM_CHANNEL_BUFFER_BYTES;
5734 }
5735
Takashi Iwai763f3562005-06-03 11:25:34 +02005736 info->first = 0;
5737 info->step = 32;
5738 return 0;
5739}
5740
Adrian Knoth0dca1792011-01-26 19:32:14 +01005741
Takashi Iwai98274f02005-11-17 14:52:34 +01005742static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005743 unsigned int cmd, void *arg)
Takashi Iwai763f3562005-06-03 11:25:34 +02005744{
5745 switch (cmd) {
5746 case SNDRV_PCM_IOCTL1_RESET:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005747 return snd_hdspm_reset(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005748
5749 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Adrian Knoth0dca1792011-01-26 19:32:14 +01005750 {
5751 struct snd_pcm_channel_info *info = arg;
5752 return snd_hdspm_channel_info(substream, info);
5753 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005754 default:
5755 break;
5756 }
5757
5758 return snd_pcm_lib_ioctl(substream, cmd, arg);
5759}
5760
Takashi Iwai98274f02005-11-17 14:52:34 +01005761static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
Takashi Iwai763f3562005-06-03 11:25:34 +02005762{
Takashi Iwai98274f02005-11-17 14:52:34 +01005763 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5764 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005765 int running;
5766
5767 spin_lock(&hdspm->lock);
5768 running = hdspm->running;
5769 switch (cmd) {
5770 case SNDRV_PCM_TRIGGER_START:
5771 running |= 1 << substream->stream;
5772 break;
5773 case SNDRV_PCM_TRIGGER_STOP:
5774 running &= ~(1 << substream->stream);
5775 break;
5776 default:
5777 snd_BUG();
5778 spin_unlock(&hdspm->lock);
5779 return -EINVAL;
5780 }
5781 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5782 other = hdspm->capture_substream;
5783 else
5784 other = hdspm->playback_substream;
5785
5786 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005787 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01005788 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005789 if (s == other) {
5790 snd_pcm_trigger_done(s, substream);
5791 if (cmd == SNDRV_PCM_TRIGGER_START)
5792 running |= 1 << s->stream;
5793 else
5794 running &= ~(1 << s->stream);
5795 goto _ok;
5796 }
5797 }
5798 if (cmd == SNDRV_PCM_TRIGGER_START) {
5799 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005800 && substream->stream ==
5801 SNDRV_PCM_STREAM_CAPTURE)
Takashi Iwai763f3562005-06-03 11:25:34 +02005802 hdspm_silence_playback(hdspm);
5803 } else {
5804 if (running &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01005805 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Takashi Iwai763f3562005-06-03 11:25:34 +02005806 hdspm_silence_playback(hdspm);
5807 }
5808 } else {
5809 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
5810 hdspm_silence_playback(hdspm);
5811 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005812_ok:
Takashi Iwai763f3562005-06-03 11:25:34 +02005813 snd_pcm_trigger_done(substream, substream);
5814 if (!hdspm->running && running)
5815 hdspm_start_audio(hdspm);
5816 else if (hdspm->running && !running)
5817 hdspm_stop_audio(hdspm);
5818 hdspm->running = running;
5819 spin_unlock(&hdspm->lock);
5820
5821 return 0;
5822}
5823
Takashi Iwai98274f02005-11-17 14:52:34 +01005824static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005825{
5826 return 0;
5827}
5828
Takashi Iwai98274f02005-11-17 14:52:34 +01005829static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005830 .info = (SNDRV_PCM_INFO_MMAP |
5831 SNDRV_PCM_INFO_MMAP_VALID |
5832 SNDRV_PCM_INFO_NONINTERLEAVED |
5833 SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
5834 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5835 .rates = (SNDRV_PCM_RATE_32000 |
5836 SNDRV_PCM_RATE_44100 |
5837 SNDRV_PCM_RATE_48000 |
5838 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005839 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5840 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ),
Takashi Iwai763f3562005-06-03 11:25:34 +02005841 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005842 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005843 .channels_min = 1,
5844 .channels_max = HDSPM_MAX_CHANNELS,
5845 .buffer_bytes_max =
5846 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
Adrian Knoth1b6fa102011-08-15 00:22:51 +02005847 .period_bytes_min = (32 * 4),
Takashi Iwai52e6fb42011-08-15 10:40:59 +02005848 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005849 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005850 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005851 .fifo_size = 0
5852};
5853
Takashi Iwai98274f02005-11-17 14:52:34 +01005854static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005855 .info = (SNDRV_PCM_INFO_MMAP |
5856 SNDRV_PCM_INFO_MMAP_VALID |
5857 SNDRV_PCM_INFO_NONINTERLEAVED |
5858 SNDRV_PCM_INFO_SYNC_START),
5859 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5860 .rates = (SNDRV_PCM_RATE_32000 |
5861 SNDRV_PCM_RATE_44100 |
5862 SNDRV_PCM_RATE_48000 |
5863 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005864 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5865 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
Takashi Iwai763f3562005-06-03 11:25:34 +02005866 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005867 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005868 .channels_min = 1,
5869 .channels_max = HDSPM_MAX_CHANNELS,
5870 .buffer_bytes_max =
5871 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
Adrian Knoth1b6fa102011-08-15 00:22:51 +02005872 .period_bytes_min = (32 * 4),
Takashi Iwai52e6fb42011-08-15 10:40:59 +02005873 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005874 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005875 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005876 .fifo_size = 0
5877};
5878
Adrian Knoth0dca1792011-01-26 19:32:14 +01005879static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
5880 struct snd_pcm_hw_rule *rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005881{
Takashi Iwai98274f02005-11-17 14:52:34 +01005882 struct hdspm *hdspm = rule->private;
5883 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005884 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005885 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005886 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5887
Adrian Knoth0dca1792011-01-26 19:32:14 +01005888 if (r->min > 96000 && r->max <= 192000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005889 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005890 .min = hdspm->qs_in_channels,
5891 .max = hdspm->qs_in_channels,
5892 .integer = 1,
5893 };
5894 return snd_interval_refine(c, &t);
5895 } else if (r->min > 48000 && r->max <= 96000) {
5896 struct snd_interval t = {
5897 .min = hdspm->ds_in_channels,
5898 .max = hdspm->ds_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005899 .integer = 1,
5900 };
5901 return snd_interval_refine(c, &t);
5902 } else if (r->max < 64000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005903 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005904 .min = hdspm->ss_in_channels,
5905 .max = hdspm->ss_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005906 .integer = 1,
5907 };
5908 return snd_interval_refine(c, &t);
5909 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005910
Takashi Iwai763f3562005-06-03 11:25:34 +02005911 return 0;
5912}
5913
Adrian Knoth0dca1792011-01-26 19:32:14 +01005914static int snd_hdspm_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
Takashi Iwai98274f02005-11-17 14:52:34 +01005915 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005916{
Takashi Iwai98274f02005-11-17 14:52:34 +01005917 struct hdspm *hdspm = rule->private;
5918 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005919 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005920 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005921 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5922
Adrian Knoth0dca1792011-01-26 19:32:14 +01005923 if (r->min > 96000 && r->max <= 192000) {
5924 struct snd_interval t = {
5925 .min = hdspm->qs_out_channels,
5926 .max = hdspm->qs_out_channels,
5927 .integer = 1,
5928 };
5929 return snd_interval_refine(c, &t);
5930 } else if (r->min > 48000 && r->max <= 96000) {
5931 struct snd_interval t = {
5932 .min = hdspm->ds_out_channels,
5933 .max = hdspm->ds_out_channels,
5934 .integer = 1,
5935 };
5936 return snd_interval_refine(c, &t);
5937 } else if (r->max < 64000) {
5938 struct snd_interval t = {
5939 .min = hdspm->ss_out_channels,
5940 .max = hdspm->ss_out_channels,
5941 .integer = 1,
5942 };
5943 return snd_interval_refine(c, &t);
5944 } else {
5945 }
5946 return 0;
5947}
5948
5949static int snd_hdspm_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
5950 struct snd_pcm_hw_rule * rule)
5951{
5952 struct hdspm *hdspm = rule->private;
5953 struct snd_interval *c =
5954 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5955 struct snd_interval *r =
5956 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5957
5958 if (c->min >= hdspm->ss_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005959 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005960 .min = 32000,
5961 .max = 48000,
5962 .integer = 1,
5963 };
5964 return snd_interval_refine(r, &t);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005965 } else if (c->max <= hdspm->qs_in_channels) {
5966 struct snd_interval t = {
5967 .min = 128000,
5968 .max = 192000,
5969 .integer = 1,
5970 };
5971 return snd_interval_refine(r, &t);
5972 } else if (c->max <= hdspm->ds_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005973 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005974 .min = 64000,
5975 .max = 96000,
5976 .integer = 1,
5977 };
Takashi Iwai763f3562005-06-03 11:25:34 +02005978 return snd_interval_refine(r, &t);
5979 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005980
5981 return 0;
5982}
5983static int snd_hdspm_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
5984 struct snd_pcm_hw_rule *rule)
5985{
5986 struct hdspm *hdspm = rule->private;
5987 struct snd_interval *c =
5988 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5989 struct snd_interval *r =
5990 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5991
5992 if (c->min >= hdspm->ss_out_channels) {
5993 struct snd_interval t = {
5994 .min = 32000,
5995 .max = 48000,
5996 .integer = 1,
5997 };
5998 return snd_interval_refine(r, &t);
5999 } else if (c->max <= hdspm->qs_out_channels) {
6000 struct snd_interval t = {
6001 .min = 128000,
6002 .max = 192000,
6003 .integer = 1,
6004 };
6005 return snd_interval_refine(r, &t);
6006 } else if (c->max <= hdspm->ds_out_channels) {
6007 struct snd_interval t = {
6008 .min = 64000,
6009 .max = 96000,
6010 .integer = 1,
6011 };
6012 return snd_interval_refine(r, &t);
6013 }
6014
Takashi Iwai763f3562005-06-03 11:25:34 +02006015 return 0;
6016}
6017
Adrian Knoth0dca1792011-01-26 19:32:14 +01006018static int snd_hdspm_hw_rule_in_channels(struct snd_pcm_hw_params *params,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006019 struct snd_pcm_hw_rule *rule)
6020{
6021 unsigned int list[3];
6022 struct hdspm *hdspm = rule->private;
6023 struct snd_interval *c = hw_param_interval(params,
6024 SNDRV_PCM_HW_PARAM_CHANNELS);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006025
6026 list[0] = hdspm->qs_in_channels;
6027 list[1] = hdspm->ds_in_channels;
6028 list[2] = hdspm->ss_in_channels;
6029 return snd_interval_list(c, 3, list, 0);
6030}
6031
6032static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params,
6033 struct snd_pcm_hw_rule *rule)
6034{
6035 unsigned int list[3];
6036 struct hdspm *hdspm = rule->private;
6037 struct snd_interval *c = hw_param_interval(params,
6038 SNDRV_PCM_HW_PARAM_CHANNELS);
6039
6040 list[0] = hdspm->qs_out_channels;
6041 list[1] = hdspm->ds_out_channels;
6042 list[2] = hdspm->ss_out_channels;
6043 return snd_interval_list(c, 3, list, 0);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006044}
6045
6046
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006047static unsigned int hdspm_aes32_sample_rates[] = {
6048 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000
6049};
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006050
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006051static struct snd_pcm_hw_constraint_list
6052hdspm_hw_constraints_aes32_sample_rates = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006053 .count = ARRAY_SIZE(hdspm_aes32_sample_rates),
6054 .list = hdspm_aes32_sample_rates,
6055 .mask = 0
6056};
6057
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006058static int snd_hdspm_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02006059{
Takashi Iwai98274f02005-11-17 14:52:34 +01006060 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
6061 struct snd_pcm_runtime *runtime = substream->runtime;
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006062 bool playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
Takashi Iwai763f3562005-06-03 11:25:34 +02006063
Takashi Iwai763f3562005-06-03 11:25:34 +02006064 spin_lock_irq(&hdspm->lock);
Takashi Iwai763f3562005-06-03 11:25:34 +02006065 snd_pcm_set_sync(substream);
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006066 runtime->hw = (playback) ? snd_hdspm_playback_subinfo :
6067 snd_hdspm_capture_subinfo;
Takashi Iwai763f3562005-06-03 11:25:34 +02006068
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006069 if (playback) {
6070 if (hdspm->capture_substream == NULL)
6071 hdspm_stop_audio(hdspm);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006072
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006073 hdspm->playback_pid = current->pid;
6074 hdspm->playback_substream = substream;
6075 } else {
6076 if (hdspm->playback_substream == NULL)
6077 hdspm_stop_audio(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006078
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006079 hdspm->capture_pid = current->pid;
6080 hdspm->capture_substream = substream;
6081 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006082
6083 spin_unlock_irq(&hdspm->lock);
6084
6085 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Takashi Iwaid8776812011-08-15 10:45:42 +02006086 snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02006087
Adrian Knoth0dca1792011-01-26 19:32:14 +01006088 switch (hdspm->io_type) {
6089 case AIO:
6090 case RayDAT:
Takashi Iwaid8776812011-08-15 10:45:42 +02006091 snd_pcm_hw_constraint_minmax(runtime,
6092 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
6093 32, 4096);
6094 /* RayDAT & AIO have a fixed buffer of 16384 samples per channel */
Lars-Peter Clausenb4ffc1b2015-10-18 15:39:21 +02006095 snd_pcm_hw_constraint_single(runtime,
Takashi Iwaid8776812011-08-15 10:45:42 +02006096 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
Lars-Peter Clausenb4ffc1b2015-10-18 15:39:21 +02006097 16384);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006098 break;
6099
6100 default:
Takashi Iwaid8776812011-08-15 10:45:42 +02006101 snd_pcm_hw_constraint_minmax(runtime,
6102 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
6103 64, 8192);
Lars-Peter Clausenb4ffc1b2015-10-18 15:39:21 +02006104 snd_pcm_hw_constraint_single(runtime,
6105 SNDRV_PCM_HW_PARAM_PERIODS, 2);
Takashi Iwaid8776812011-08-15 10:45:42 +02006106 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006107 }
6108
6109 if (AES32 == hdspm->io_type) {
Takashi Iwai3fa9e3d2011-08-15 10:42:23 +02006110 runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006111 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
6112 &hdspm_hw_constraints_aes32_sample_rates);
6113 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006114 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006115 (playback ?
6116 snd_hdspm_hw_rule_rate_out_channels :
6117 snd_hdspm_hw_rule_rate_in_channels), hdspm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006118 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006119 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01006120
6121 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006122 (playback ? snd_hdspm_hw_rule_out_channels :
6123 snd_hdspm_hw_rule_in_channels), hdspm,
Adrian Knoth88fabbf2011-02-23 11:43:10 +01006124 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
6125
6126 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006127 (playback ? snd_hdspm_hw_rule_out_channels_rate :
6128 snd_hdspm_hw_rule_in_channels_rate), hdspm,
Adrian Knoth88fabbf2011-02-23 11:43:10 +01006129 SNDRV_PCM_HW_PARAM_RATE, -1);
6130
Takashi Iwai763f3562005-06-03 11:25:34 +02006131 return 0;
6132}
6133
Adrian Knoth8b73b862015-02-17 00:05:05 +01006134static int snd_hdspm_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02006135{
Takashi Iwai98274f02005-11-17 14:52:34 +01006136 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Adrian Knoth8b73b862015-02-17 00:05:05 +01006137 bool playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
Takashi Iwai763f3562005-06-03 11:25:34 +02006138
6139 spin_lock_irq(&hdspm->lock);
6140
Adrian Knoth8b73b862015-02-17 00:05:05 +01006141 if (playback) {
6142 hdspm->playback_pid = -1;
6143 hdspm->playback_substream = NULL;
6144 } else {
6145 hdspm->capture_pid = -1;
6146 hdspm->capture_substream = NULL;
6147 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006148
6149 spin_unlock_irq(&hdspm->lock);
6150
6151 return 0;
6152}
6153
Adrian Knoth0dca1792011-01-26 19:32:14 +01006154static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
Takashi Iwai763f3562005-06-03 11:25:34 +02006155{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006156 /* we have nothing to initialize but the call is required */
6157 return 0;
6158}
6159
6160static inline int copy_u32_le(void __user *dest, void __iomem *src)
6161{
6162 u32 val = readl(src);
6163 return copy_to_user(dest, &val, 4);
6164}
6165
6166static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006167 unsigned int cmd, unsigned long arg)
Adrian Knoth0dca1792011-01-26 19:32:14 +01006168{
6169 void __user *argp = (void __user *)arg;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006170 struct hdspm *hdspm = hw->private_data;
Takashi Iwai98274f02005-11-17 14:52:34 +01006171 struct hdspm_mixer_ioctl mixer;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006172 struct hdspm_config info;
6173 struct hdspm_status status;
Takashi Iwai98274f02005-11-17 14:52:34 +01006174 struct hdspm_version hdspm_version;
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006175 struct hdspm_peak_rms *levels;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006176 struct hdspm_ltc ltc;
6177 unsigned int statusregister;
6178 long unsigned int s;
6179 int i = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02006180
6181 switch (cmd) {
6182
Takashi Iwai763f3562005-06-03 11:25:34 +02006183 case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006184 levels = &hdspm->peak_rms;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006185 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006186 levels->input_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006187 readl(hdspm->iobase +
6188 HDSPM_MADI_INPUT_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006189 levels->playback_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006190 readl(hdspm->iobase +
6191 HDSPM_MADI_PLAYBACK_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006192 levels->output_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006193 readl(hdspm->iobase +
6194 HDSPM_MADI_OUTPUT_PEAK + i*4);
6195
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006196 levels->input_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006197 ((uint64_t) readl(hdspm->iobase +
6198 HDSPM_MADI_INPUT_RMS_H + i*4) << 32) |
6199 (uint64_t) readl(hdspm->iobase +
6200 HDSPM_MADI_INPUT_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006201 levels->playback_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006202 ((uint64_t)readl(hdspm->iobase +
6203 HDSPM_MADI_PLAYBACK_RMS_H+i*4) << 32) |
6204 (uint64_t)readl(hdspm->iobase +
6205 HDSPM_MADI_PLAYBACK_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006206 levels->output_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006207 ((uint64_t)readl(hdspm->iobase +
6208 HDSPM_MADI_OUTPUT_RMS_H + i*4) << 32) |
6209 (uint64_t)readl(hdspm->iobase +
6210 HDSPM_MADI_OUTPUT_RMS_L + i*4);
6211 }
6212
6213 if (hdspm->system_sample_rate > 96000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006214 levels->speed = qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006215 } else if (hdspm->system_sample_rate > 48000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006216 levels->speed = ds;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006217 } else {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006218 levels->speed = ss;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006219 }
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006220 levels->status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006221
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006222 s = copy_to_user(argp, levels, sizeof(struct hdspm_peak_rms));
Adrian Knoth0dca1792011-01-26 19:32:14 +01006223 if (0 != s) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006224 /* dev_err(hdspm->card->dev, "copy_to_user(.., .., %lu): %lu
Adrian Knoth0dca1792011-01-26 19:32:14 +01006225 [Levels]\n", sizeof(struct hdspm_peak_rms), s);
6226 */
Takashi Iwai763f3562005-06-03 11:25:34 +02006227 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006228 }
6229 break;
6230
6231 case SNDRV_HDSPM_IOCTL_GET_LTC:
6232 ltc.ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
6233 i = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
6234 if (i & HDSPM_TCO1_LTC_Input_valid) {
6235 switch (i & (HDSPM_TCO1_LTC_Format_LSB |
6236 HDSPM_TCO1_LTC_Format_MSB)) {
6237 case 0:
6238 ltc.format = fps_24;
6239 break;
6240 case HDSPM_TCO1_LTC_Format_LSB:
6241 ltc.format = fps_25;
6242 break;
6243 case HDSPM_TCO1_LTC_Format_MSB:
6244 ltc.format = fps_2997;
6245 break;
6246 default:
Adrian Knoth17d2f002013-08-19 17:20:30 +02006247 ltc.format = fps_30;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006248 break;
6249 }
6250 if (i & HDSPM_TCO1_set_drop_frame_flag) {
6251 ltc.frame = drop_frame;
6252 } else {
6253 ltc.frame = full_frame;
6254 }
6255 } else {
6256 ltc.format = format_invalid;
6257 ltc.frame = frame_invalid;
6258 }
6259 if (i & HDSPM_TCO1_Video_Input_Format_NTSC) {
6260 ltc.input_format = ntsc;
6261 } else if (i & HDSPM_TCO1_Video_Input_Format_PAL) {
6262 ltc.input_format = pal;
6263 } else {
6264 ltc.input_format = no_video;
6265 }
6266
6267 s = copy_to_user(argp, &ltc, sizeof(struct hdspm_ltc));
6268 if (0 != s) {
6269 /*
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006270 dev_err(hdspm->card->dev, "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */
Takashi Iwai763f3562005-06-03 11:25:34 +02006271 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006272 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006273
6274 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02006275
Adrian Knoth0dca1792011-01-26 19:32:14 +01006276 case SNDRV_HDSPM_IOCTL_GET_CONFIG:
Takashi Iwai763f3562005-06-03 11:25:34 +02006277
Adrian Knoth4ab69a22011-02-23 11:43:14 +01006278 memset(&info, 0, sizeof(info));
Takashi Iwai763f3562005-06-03 11:25:34 +02006279 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006280 info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
6281 info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006282
6283 info.system_sample_rate = hdspm->system_sample_rate;
6284 info.autosync_sample_rate =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006285 hdspm_external_sample_rate(hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006286 info.system_clock_mode = hdspm_system_clock_mode(hdspm);
6287 info.clock_source = hdspm_clock_source(hdspm);
6288 info.autosync_ref = hdspm_autosync_ref(hdspm);
Adrian Knothc9e16682012-12-03 14:55:50 +01006289 info.line_out = hdspm_toggle_setting(hdspm, HDSPM_LineOut);
Takashi Iwai763f3562005-06-03 11:25:34 +02006290 info.passthru = 0;
6291 spin_unlock_irq(&hdspm->lock);
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006292 if (copy_to_user(argp, &info, sizeof(info)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006293 return -EFAULT;
6294 break;
6295
Adrian Knoth0dca1792011-01-26 19:32:14 +01006296 case SNDRV_HDSPM_IOCTL_GET_STATUS:
Dan Carpenter643d6bb2011-09-23 09:24:21 +03006297 memset(&status, 0, sizeof(status));
6298
Adrian Knoth0dca1792011-01-26 19:32:14 +01006299 status.card_type = hdspm->io_type;
6300
6301 status.autosync_source = hdspm_autosync_ref(hdspm);
6302
6303 status.card_clock = 110069313433624ULL;
6304 status.master_period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
6305
6306 switch (hdspm->io_type) {
6307 case MADI:
6308 case MADIface:
6309 status.card_specific.madi.sync_wc =
6310 hdspm_wc_sync_check(hdspm);
6311 status.card_specific.madi.sync_madi =
6312 hdspm_madi_sync_check(hdspm);
6313 status.card_specific.madi.sync_tco =
6314 hdspm_tco_sync_check(hdspm);
6315 status.card_specific.madi.sync_in =
6316 hdspm_sync_in_sync_check(hdspm);
6317
6318 statusregister =
6319 hdspm_read(hdspm, HDSPM_statusRegister);
6320 status.card_specific.madi.madi_input =
6321 (statusregister & HDSPM_AB_int) ? 1 : 0;
6322 status.card_specific.madi.channel_format =
Adrian Knoth9e6ff522011-10-27 21:57:52 +02006323 (statusregister & HDSPM_RX_64ch) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006324 /* TODO: Mac driver sets it when f_s>48kHz */
6325 status.card_specific.madi.frame_format = 0;
6326
6327 default:
6328 break;
6329 }
6330
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006331 if (copy_to_user(argp, &status, sizeof(status)))
Adrian Knoth0dca1792011-01-26 19:32:14 +01006332 return -EFAULT;
6333
6334
6335 break;
6336
Takashi Iwai763f3562005-06-03 11:25:34 +02006337 case SNDRV_HDSPM_IOCTL_GET_VERSION:
Dan Carpenter643d6bb2011-09-23 09:24:21 +03006338 memset(&hdspm_version, 0, sizeof(hdspm_version));
6339
Adrian Knoth0dca1792011-01-26 19:32:14 +01006340 hdspm_version.card_type = hdspm->io_type;
Takashi Iwai57a44512013-10-29 15:26:12 +01006341 strlcpy(hdspm_version.cardname, hdspm->card_name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006342 sizeof(hdspm_version.cardname));
Adrian Knoth7d53a632012-01-04 14:31:16 +01006343 hdspm_version.serial = hdspm->serial;
Takashi Iwai763f3562005-06-03 11:25:34 +02006344 hdspm_version.firmware_rev = hdspm->firmware_rev;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006345 hdspm_version.addons = 0;
6346 if (hdspm->tco)
6347 hdspm_version.addons |= HDSPM_ADDON_TCO;
6348
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006349 if (copy_to_user(argp, &hdspm_version,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006350 sizeof(hdspm_version)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006351 return -EFAULT;
6352 break;
6353
6354 case SNDRV_HDSPM_IOCTL_GET_MIXER:
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006355 if (copy_from_user(&mixer, argp, sizeof(mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006356 return -EFAULT;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006357 if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006358 sizeof(struct hdspm_mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006359 return -EFAULT;
6360 break;
6361
6362 default:
6363 return -EINVAL;
6364 }
6365 return 0;
6366}
6367
Julia Lawall6769e982016-09-02 00:13:10 +02006368static const struct snd_pcm_ops snd_hdspm_ops = {
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006369 .open = snd_hdspm_open,
Adrian Knoth8b73b862015-02-17 00:05:05 +01006370 .close = snd_hdspm_release,
Takashi Iwai763f3562005-06-03 11:25:34 +02006371 .ioctl = snd_hdspm_ioctl,
6372 .hw_params = snd_hdspm_hw_params,
6373 .hw_free = snd_hdspm_hw_free,
6374 .prepare = snd_hdspm_prepare,
6375 .trigger = snd_hdspm_trigger,
6376 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006377 .page = snd_pcm_sgbuf_ops_page,
6378};
6379
Bill Pembertone23e7a12012-12-06 12:35:10 -05006380static int snd_hdspm_create_hwdep(struct snd_card *card,
6381 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006382{
Takashi Iwai98274f02005-11-17 14:52:34 +01006383 struct snd_hwdep *hw;
Takashi Iwai763f3562005-06-03 11:25:34 +02006384 int err;
6385
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006386 err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw);
6387 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006388 return err;
6389
6390 hdspm->hwdep = hw;
6391 hw->private_data = hdspm;
6392 strcpy(hw->name, "HDSPM hwdep interface");
6393
Adrian Knoth0dca1792011-01-26 19:32:14 +01006394 hw->ops.open = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006395 hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
Adrian Knoth8de5d6f2012-03-08 15:38:04 +01006396 hw->ops.ioctl_compat = snd_hdspm_hwdep_ioctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006397 hw->ops.release = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006398
6399 return 0;
6400}
6401
6402
6403/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01006404 memory interface
Takashi Iwai763f3562005-06-03 11:25:34 +02006405 ------------------------------------------------------------*/
Bill Pembertone23e7a12012-12-06 12:35:10 -05006406static int snd_hdspm_preallocate_memory(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006407{
6408 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01006409 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006410 size_t wanted;
6411
6412 pcm = hdspm->pcm;
6413
Remy Bruno3cee5a62006-10-16 12:46:32 +02006414 wanted = HDSPM_DMA_AREA_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02006415
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006416 err =
Takashi Iwai763f3562005-06-03 11:25:34 +02006417 snd_pcm_lib_preallocate_pages_for_all(pcm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006418 SNDRV_DMA_TYPE_DEV_SG,
Takashi Iwai763f3562005-06-03 11:25:34 +02006419 snd_dma_pci_data(hdspm->pci),
6420 wanted,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006421 wanted);
6422 if (err < 0) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006423 dev_dbg(hdspm->card->dev,
6424 "Could not preallocate %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006425
6426 return err;
6427 } else
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006428 dev_dbg(hdspm->card->dev,
6429 " Preallocated %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006430
6431 return 0;
6432}
6433
Adrian Knoth0dca1792011-01-26 19:32:14 +01006434
6435static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +02006436 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02006437 unsigned int reg, int channels)
6438{
6439 int i;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006440
6441 /* continuous memory segment */
Takashi Iwai763f3562005-06-03 11:25:34 +02006442 for (i = 0; i < (channels * 16); i++)
6443 hdspm_write(hdspm, reg + 4 * i,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006444 snd_pcm_sgbuf_get_addr(substream, 4096 * i));
Takashi Iwai763f3562005-06-03 11:25:34 +02006445}
6446
Adrian Knoth0dca1792011-01-26 19:32:14 +01006447
Takashi Iwai763f3562005-06-03 11:25:34 +02006448/* ------------- ALSA Devices ---------------------------- */
Bill Pembertone23e7a12012-12-06 12:35:10 -05006449static int snd_hdspm_create_pcm(struct snd_card *card,
6450 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006451{
Takashi Iwai98274f02005-11-17 14:52:34 +01006452 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006453 int err;
6454
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006455 err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm);
6456 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006457 return err;
6458
6459 hdspm->pcm = pcm;
6460 pcm->private_data = hdspm;
6461 strcpy(pcm->name, hdspm->card_name);
6462
6463 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
Adrian Knoth0c8d9482015-02-17 00:05:06 +01006464 &snd_hdspm_ops);
Takashi Iwai763f3562005-06-03 11:25:34 +02006465 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
Adrian Knoth0c8d9482015-02-17 00:05:06 +01006466 &snd_hdspm_ops);
Takashi Iwai763f3562005-06-03 11:25:34 +02006467
6468 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
6469
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006470 err = snd_hdspm_preallocate_memory(hdspm);
6471 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006472 return err;
6473
6474 return 0;
6475}
6476
Takashi Iwai98274f02005-11-17 14:52:34 +01006477static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006478{
Adrian Knoth7c7102b2011-02-28 15:14:50 +01006479 int i;
6480
6481 for (i = 0; i < hdspm->midiPorts; i++)
6482 snd_hdspm_flush_midi_input(hdspm, i);
Takashi Iwai763f3562005-06-03 11:25:34 +02006483}
6484
Bill Pembertone23e7a12012-12-06 12:35:10 -05006485static int snd_hdspm_create_alsa_devices(struct snd_card *card,
6486 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006487{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006488 int err, i;
Takashi Iwai763f3562005-06-03 11:25:34 +02006489
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006490 dev_dbg(card->dev, "Create card...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006491 err = snd_hdspm_create_pcm(card, hdspm);
6492 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006493 return err;
6494
Adrian Knoth0dca1792011-01-26 19:32:14 +01006495 i = 0;
6496 while (i < hdspm->midiPorts) {
6497 err = snd_hdspm_create_midi(card, hdspm, i);
6498 if (err < 0) {
6499 return err;
6500 }
6501 i++;
6502 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006503
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006504 err = snd_hdspm_create_controls(card, hdspm);
6505 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006506 return err;
6507
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006508 err = snd_hdspm_create_hwdep(card, hdspm);
6509 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006510 return err;
6511
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006512 dev_dbg(card->dev, "proc init...\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02006513 snd_hdspm_proc_init(hdspm);
6514
6515 hdspm->system_sample_rate = -1;
6516 hdspm->last_external_sample_rate = -1;
6517 hdspm->last_internal_sample_rate = -1;
6518 hdspm->playback_pid = -1;
6519 hdspm->capture_pid = -1;
6520 hdspm->capture_substream = NULL;
6521 hdspm->playback_substream = NULL;
6522
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006523 dev_dbg(card->dev, "Set defaults...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006524 err = snd_hdspm_set_defaults(hdspm);
6525 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006526 return err;
6527
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006528 dev_dbg(card->dev, "Update mixer controls...\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02006529 hdspm_update_simple_mixer_controls(hdspm);
6530
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006531 dev_dbg(card->dev, "Initializeing complete ???\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02006532
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006533 err = snd_card_register(card);
6534 if (err < 0) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006535 dev_err(card->dev, "error registering card\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02006536 return err;
6537 }
6538
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006539 dev_dbg(card->dev, "... yes now\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02006540
6541 return 0;
6542}
6543
Bill Pembertone23e7a12012-12-06 12:35:10 -05006544static int snd_hdspm_create(struct snd_card *card,
6545 struct hdspm *hdspm)
6546{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006547
Takashi Iwai763f3562005-06-03 11:25:34 +02006548 struct pci_dev *pci = hdspm->pci;
6549 int err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006550 unsigned long io_extent;
6551
6552 hdspm->irq = -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02006553 hdspm->card = card;
6554
6555 spin_lock_init(&hdspm->lock);
6556
Takashi Iwai763f3562005-06-03 11:25:34 +02006557 pci_read_config_word(hdspm->pci,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006558 PCI_CLASS_REVISION, &hdspm->firmware_rev);
Remy Bruno3cee5a62006-10-16 12:46:32 +02006559
Takashi Iwai763f3562005-06-03 11:25:34 +02006560 strcpy(card->mixername, "Xilinx FPGA");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006561 strcpy(card->driver, "HDSPM");
6562
6563 switch (hdspm->firmware_rev) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01006564 case HDSPM_RAYDAT_REV:
6565 hdspm->io_type = RayDAT;
6566 hdspm->card_name = "RME RayDAT";
6567 hdspm->midiPorts = 2;
6568 break;
6569 case HDSPM_AIO_REV:
6570 hdspm->io_type = AIO;
6571 hdspm->card_name = "RME AIO";
6572 hdspm->midiPorts = 1;
6573 break;
6574 case HDSPM_MADIFACE_REV:
6575 hdspm->io_type = MADIface;
6576 hdspm->card_name = "RME MADIface";
6577 hdspm->midiPorts = 1;
6578 break;
Adrian Knoth5027f342011-02-28 15:14:49 +01006579 default:
Adrian Knothc09403d2011-10-27 21:57:54 +02006580 if ((hdspm->firmware_rev == 0xf0) ||
6581 ((hdspm->firmware_rev >= 0xe6) &&
6582 (hdspm->firmware_rev <= 0xea))) {
6583 hdspm->io_type = AES32;
6584 hdspm->card_name = "RME AES32";
6585 hdspm->midiPorts = 2;
Adrian Knoth05c7cc92011-11-21 16:15:36 +01006586 } else if ((hdspm->firmware_rev == 0xd2) ||
Adrian Knothc09403d2011-10-27 21:57:54 +02006587 ((hdspm->firmware_rev >= 0xc8) &&
6588 (hdspm->firmware_rev <= 0xcf))) {
6589 hdspm->io_type = MADI;
6590 hdspm->card_name = "RME MADI";
6591 hdspm->midiPorts = 3;
6592 } else {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006593 dev_err(card->dev,
6594 "unknown firmware revision %x\n",
Adrian Knoth5027f342011-02-28 15:14:49 +01006595 hdspm->firmware_rev);
Adrian Knothc09403d2011-10-27 21:57:54 +02006596 return -ENODEV;
6597 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02006598 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006599
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006600 err = pci_enable_device(pci);
6601 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006602 return err;
6603
6604 pci_set_master(hdspm->pci);
6605
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006606 err = pci_request_regions(pci, "hdspm");
6607 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006608 return err;
6609
6610 hdspm->port = pci_resource_start(pci, 0);
6611 io_extent = pci_resource_len(pci, 0);
6612
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006613 dev_dbg(card->dev, "grabbed memory region 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006614 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006615
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006616 hdspm->iobase = ioremap_nocache(hdspm->port, io_extent);
6617 if (!hdspm->iobase) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006618 dev_err(card->dev, "unable to remap region 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006619 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006620 return -EBUSY;
6621 }
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006622 dev_dbg(card->dev, "remapped region (0x%lx) 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006623 (unsigned long)hdspm->iobase, hdspm->port,
6624 hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006625
6626 if (request_irq(pci->irq, snd_hdspm_interrupt,
Takashi Iwai934c2b62011-06-10 16:36:37 +02006627 IRQF_SHARED, KBUILD_MODNAME, hdspm)) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006628 dev_err(card->dev, "unable to use IRQ %d\n", pci->irq);
Takashi Iwai763f3562005-06-03 11:25:34 +02006629 return -EBUSY;
6630 }
6631
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006632 dev_dbg(card->dev, "use IRQ %d\n", pci->irq);
Takashi Iwai763f3562005-06-03 11:25:34 +02006633
6634 hdspm->irq = pci->irq;
Takashi Iwai763f3562005-06-03 11:25:34 +02006635
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006636 dev_dbg(card->dev, "kmalloc Mixer memory of %zd Bytes\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006637 sizeof(struct hdspm_mixer));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006638 hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL);
6639 if (!hdspm->mixer) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006640 dev_err(card->dev,
6641 "unable to kmalloc Mixer memory of %d Bytes\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006642 (int)sizeof(struct hdspm_mixer));
Julia Lawallb17cbdd2012-08-19 09:02:54 +02006643 return -ENOMEM;
Takashi Iwai763f3562005-06-03 11:25:34 +02006644 }
6645
Adrian Knoth0dca1792011-01-26 19:32:14 +01006646 hdspm->port_names_in = NULL;
6647 hdspm->port_names_out = NULL;
6648
6649 switch (hdspm->io_type) {
6650 case AES32:
Adrian Knothd2d10a22011-02-28 15:14:47 +01006651 hdspm->ss_in_channels = hdspm->ss_out_channels = AES32_CHANNELS;
6652 hdspm->ds_in_channels = hdspm->ds_out_channels = AES32_CHANNELS;
6653 hdspm->qs_in_channels = hdspm->qs_out_channels = AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006654
6655 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6656 channel_map_aes32;
6657 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6658 channel_map_aes32;
6659 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6660 channel_map_aes32;
6661 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6662 texts_ports_aes32;
6663 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6664 texts_ports_aes32;
6665 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6666 texts_ports_aes32;
6667
Adrian Knothd2d10a22011-02-28 15:14:47 +01006668 hdspm->max_channels_out = hdspm->max_channels_in =
6669 AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006670 hdspm->port_names_in = hdspm->port_names_out =
6671 texts_ports_aes32;
6672 hdspm->channel_map_in = hdspm->channel_map_out =
6673 channel_map_aes32;
6674
Adrian Knoth0dca1792011-01-26 19:32:14 +01006675 break;
6676
6677 case MADI:
6678 case MADIface:
6679 hdspm->ss_in_channels = hdspm->ss_out_channels =
6680 MADI_SS_CHANNELS;
6681 hdspm->ds_in_channels = hdspm->ds_out_channels =
6682 MADI_DS_CHANNELS;
6683 hdspm->qs_in_channels = hdspm->qs_out_channels =
6684 MADI_QS_CHANNELS;
6685
6686 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6687 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006688 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006689 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006690 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006691 channel_map_unity_ss;
6692
6693 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6694 texts_ports_madi;
6695 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6696 texts_ports_madi;
6697 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6698 texts_ports_madi;
6699 break;
6700
6701 case AIO:
Adrian Knoth0dca1792011-01-26 19:32:14 +01006702 hdspm->ss_in_channels = AIO_IN_SS_CHANNELS;
6703 hdspm->ds_in_channels = AIO_IN_DS_CHANNELS;
6704 hdspm->qs_in_channels = AIO_IN_QS_CHANNELS;
6705 hdspm->ss_out_channels = AIO_OUT_SS_CHANNELS;
6706 hdspm->ds_out_channels = AIO_OUT_DS_CHANNELS;
6707 hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS;
6708
Adrian Knoth3de9db22013-07-05 11:28:02 +02006709 if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006710 dev_info(card->dev, "AEB input board found\n");
Adrian Knoth3de9db22013-07-05 11:28:02 +02006711 hdspm->ss_in_channels += 4;
6712 hdspm->ds_in_channels += 4;
6713 hdspm->qs_in_channels += 4;
6714 }
6715
6716 if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBO_D)) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006717 dev_info(card->dev, "AEB output board found\n");
Adrian Knoth3de9db22013-07-05 11:28:02 +02006718 hdspm->ss_out_channels += 4;
6719 hdspm->ds_out_channels += 4;
6720 hdspm->qs_out_channels += 4;
6721 }
6722
Adrian Knoth0dca1792011-01-26 19:32:14 +01006723 hdspm->channel_map_out_ss = channel_map_aio_out_ss;
6724 hdspm->channel_map_out_ds = channel_map_aio_out_ds;
6725 hdspm->channel_map_out_qs = channel_map_aio_out_qs;
6726
6727 hdspm->channel_map_in_ss = channel_map_aio_in_ss;
6728 hdspm->channel_map_in_ds = channel_map_aio_in_ds;
6729 hdspm->channel_map_in_qs = channel_map_aio_in_qs;
6730
6731 hdspm->port_names_in_ss = texts_ports_aio_in_ss;
6732 hdspm->port_names_out_ss = texts_ports_aio_out_ss;
6733 hdspm->port_names_in_ds = texts_ports_aio_in_ds;
6734 hdspm->port_names_out_ds = texts_ports_aio_out_ds;
6735 hdspm->port_names_in_qs = texts_ports_aio_in_qs;
6736 hdspm->port_names_out_qs = texts_ports_aio_out_qs;
6737
6738 break;
6739
6740 case RayDAT:
6741 hdspm->ss_in_channels = hdspm->ss_out_channels =
6742 RAYDAT_SS_CHANNELS;
6743 hdspm->ds_in_channels = hdspm->ds_out_channels =
6744 RAYDAT_DS_CHANNELS;
6745 hdspm->qs_in_channels = hdspm->qs_out_channels =
6746 RAYDAT_QS_CHANNELS;
6747
6748 hdspm->max_channels_in = RAYDAT_SS_CHANNELS;
6749 hdspm->max_channels_out = RAYDAT_SS_CHANNELS;
6750
6751 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6752 channel_map_raydat_ss;
6753 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6754 channel_map_raydat_ds;
6755 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6756 channel_map_raydat_qs;
6757 hdspm->channel_map_in = hdspm->channel_map_out =
6758 channel_map_raydat_ss;
6759
6760 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6761 texts_ports_raydat_ss;
6762 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6763 texts_ports_raydat_ds;
6764 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6765 texts_ports_raydat_qs;
6766
6767
6768 break;
6769
6770 }
6771
6772 /* TCO detection */
6773 switch (hdspm->io_type) {
6774 case AIO:
6775 case RayDAT:
6776 if (hdspm_read(hdspm, HDSPM_statusRegister2) &
6777 HDSPM_s2_tco_detect) {
6778 hdspm->midiPorts++;
6779 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6780 GFP_KERNEL);
6781 if (NULL != hdspm->tco) {
6782 hdspm_tco_write(hdspm);
6783 }
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006784 dev_info(card->dev, "AIO/RayDAT TCO module found\n");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006785 } else {
6786 hdspm->tco = NULL;
6787 }
6788 break;
6789
6790 case MADI:
Adrian Knoth0dc831b2013-07-05 11:28:19 +02006791 case AES32:
Adrian Knoth0dca1792011-01-26 19:32:14 +01006792 if (hdspm_read(hdspm, HDSPM_statusRegister) & HDSPM_tco_detect) {
6793 hdspm->midiPorts++;
6794 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6795 GFP_KERNEL);
6796 if (NULL != hdspm->tco) {
6797 hdspm_tco_write(hdspm);
6798 }
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006799 dev_info(card->dev, "MADI/AES TCO module found\n");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006800 } else {
6801 hdspm->tco = NULL;
6802 }
6803 break;
6804
6805 default:
6806 hdspm->tco = NULL;
6807 }
6808
6809 /* texts */
6810 switch (hdspm->io_type) {
6811 case AES32:
6812 if (hdspm->tco) {
6813 hdspm->texts_autosync = texts_autosync_aes_tco;
Adrian Knothe71b95a2013-07-05 11:28:06 +02006814 hdspm->texts_autosync_items =
6815 ARRAY_SIZE(texts_autosync_aes_tco);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006816 } else {
6817 hdspm->texts_autosync = texts_autosync_aes;
Adrian Knothe71b95a2013-07-05 11:28:06 +02006818 hdspm->texts_autosync_items =
6819 ARRAY_SIZE(texts_autosync_aes);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006820 }
6821 break;
6822
6823 case MADI:
6824 if (hdspm->tco) {
6825 hdspm->texts_autosync = texts_autosync_madi_tco;
6826 hdspm->texts_autosync_items = 4;
6827 } else {
6828 hdspm->texts_autosync = texts_autosync_madi;
6829 hdspm->texts_autosync_items = 3;
6830 }
6831 break;
6832
6833 case MADIface:
6834
6835 break;
6836
6837 case RayDAT:
6838 if (hdspm->tco) {
6839 hdspm->texts_autosync = texts_autosync_raydat_tco;
6840 hdspm->texts_autosync_items = 9;
6841 } else {
6842 hdspm->texts_autosync = texts_autosync_raydat;
6843 hdspm->texts_autosync_items = 8;
6844 }
6845 break;
6846
6847 case AIO:
6848 if (hdspm->tco) {
6849 hdspm->texts_autosync = texts_autosync_aio_tco;
6850 hdspm->texts_autosync_items = 6;
6851 } else {
6852 hdspm->texts_autosync = texts_autosync_aio;
6853 hdspm->texts_autosync_items = 5;
6854 }
6855 break;
6856
6857 }
6858
6859 tasklet_init(&hdspm->midi_tasklet,
6860 hdspm_midi_tasklet, (unsigned long) hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006861
Adrian Knothf7de8ba2012-01-10 20:58:40 +01006862
6863 if (hdspm->io_type != MADIface) {
6864 hdspm->serial = (hdspm_read(hdspm,
6865 HDSPM_midiStatusIn0)>>8) & 0xFFFFFF;
6866 /* id contains either a user-provided value or the default
6867 * NULL. If it's the default, we're safe to
6868 * fill card->id with the serial number.
6869 *
6870 * If the serial number is 0xFFFFFF, then we're dealing with
6871 * an old PCI revision that comes without a sane number. In
6872 * this case, we don't set card->id to avoid collisions
6873 * when running with multiple cards.
6874 */
6875 if (NULL == id[hdspm->dev] && hdspm->serial != 0xFFFFFF) {
6876 sprintf(card->id, "HDSPMx%06x", hdspm->serial);
6877 snd_card_set_id(card, card->id);
6878 }
6879 }
6880
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006881 dev_dbg(card->dev, "create alsa devices.\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006882 err = snd_hdspm_create_alsa_devices(card, hdspm);
6883 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006884 return err;
6885
6886 snd_hdspm_initialize_midi_flush(hdspm);
6887
6888 return 0;
6889}
6890
Adrian Knoth0dca1792011-01-26 19:32:14 +01006891
Takashi Iwai98274f02005-11-17 14:52:34 +01006892static int snd_hdspm_free(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006893{
6894
6895 if (hdspm->port) {
6896
6897 /* stop th audio, and cancel all interrupts */
6898 hdspm->control_register &=
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006899 ~(HDSPM_Start | HDSPM_AudioInterruptEnable |
Adrian Knoth0dca1792011-01-26 19:32:14 +01006900 HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable |
6901 HDSPM_Midi2InterruptEnable | HDSPM_Midi3InterruptEnable);
Takashi Iwai763f3562005-06-03 11:25:34 +02006902 hdspm_write(hdspm, HDSPM_controlRegister,
6903 hdspm->control_register);
6904 }
6905
6906 if (hdspm->irq >= 0)
6907 free_irq(hdspm->irq, (void *) hdspm);
6908
Jesper Juhlfc584222005-10-24 15:11:28 +02006909 kfree(hdspm->mixer);
Markus Elfringff6defa2015-01-03 22:55:54 +01006910 iounmap(hdspm->iobase);
Takashi Iwai763f3562005-06-03 11:25:34 +02006911
Takashi Iwai763f3562005-06-03 11:25:34 +02006912 if (hdspm->port)
6913 pci_release_regions(hdspm->pci);
6914
6915 pci_disable_device(hdspm->pci);
6916 return 0;
6917}
6918
Adrian Knoth0dca1792011-01-26 19:32:14 +01006919
Takashi Iwai98274f02005-11-17 14:52:34 +01006920static void snd_hdspm_card_free(struct snd_card *card)
Takashi Iwai763f3562005-06-03 11:25:34 +02006921{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006922 struct hdspm *hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006923
6924 if (hdspm)
6925 snd_hdspm_free(hdspm);
6926}
6927
Adrian Knoth0dca1792011-01-26 19:32:14 +01006928
Bill Pembertone23e7a12012-12-06 12:35:10 -05006929static int snd_hdspm_probe(struct pci_dev *pci,
6930 const struct pci_device_id *pci_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02006931{
6932 static int dev;
Takashi Iwai98274f02005-11-17 14:52:34 +01006933 struct hdspm *hdspm;
6934 struct snd_card *card;
Takashi Iwai763f3562005-06-03 11:25:34 +02006935 int err;
6936
6937 if (dev >= SNDRV_CARDS)
6938 return -ENODEV;
6939 if (!enable[dev]) {
6940 dev++;
6941 return -ENOENT;
6942 }
6943
Takashi Iwai60c57722014-01-29 14:20:19 +01006944 err = snd_card_new(&pci->dev, index[dev], id[dev],
6945 THIS_MODULE, sizeof(struct hdspm), &card);
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006946 if (err < 0)
6947 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006948
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006949 hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006950 card->private_free = snd_hdspm_card_free;
6951 hdspm->dev = dev;
6952 hdspm->pci = pci;
6953
Adrian Knoth0dca1792011-01-26 19:32:14 +01006954 err = snd_hdspm_create(card, hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006955 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006956 snd_card_free(card);
6957 return err;
6958 }
6959
Adrian Knoth0dca1792011-01-26 19:32:14 +01006960 if (hdspm->io_type != MADIface) {
6961 sprintf(card->shortname, "%s_%x",
6962 hdspm->card_name,
Adrian Knoth7d53a632012-01-04 14:31:16 +01006963 hdspm->serial);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006964 sprintf(card->longname, "%s S/N 0x%x at 0x%lx, irq %d",
6965 hdspm->card_name,
Adrian Knoth7d53a632012-01-04 14:31:16 +01006966 hdspm->serial,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006967 hdspm->port, hdspm->irq);
6968 } else {
6969 sprintf(card->shortname, "%s", hdspm->card_name);
6970 sprintf(card->longname, "%s at 0x%lx, irq %d",
6971 hdspm->card_name, hdspm->port, hdspm->irq);
6972 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006973
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006974 err = snd_card_register(card);
6975 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006976 snd_card_free(card);
6977 return err;
6978 }
6979
6980 pci_set_drvdata(pci, card);
6981
6982 dev++;
6983 return 0;
6984}
6985
Bill Pembertone23e7a12012-12-06 12:35:10 -05006986static void snd_hdspm_remove(struct pci_dev *pci)
Takashi Iwai763f3562005-06-03 11:25:34 +02006987{
6988 snd_card_free(pci_get_drvdata(pci));
Takashi Iwai763f3562005-06-03 11:25:34 +02006989}
6990
Takashi Iwaie9f66d92012-04-24 12:25:00 +02006991static struct pci_driver hdspm_driver = {
Takashi Iwai3733e422011-06-10 16:20:20 +02006992 .name = KBUILD_MODNAME,
Takashi Iwai763f3562005-06-03 11:25:34 +02006993 .id_table = snd_hdspm_ids,
6994 .probe = snd_hdspm_probe,
Bill Pembertone23e7a12012-12-06 12:35:10 -05006995 .remove = snd_hdspm_remove,
Takashi Iwai763f3562005-06-03 11:25:34 +02006996};
6997
Takashi Iwaie9f66d92012-04-24 12:25:00 +02006998module_pci_driver(hdspm_driver);