blob: 8d900c132f0f4434c9b7ea41944c894b444db49c [file] [log] [blame]
Thomas Gleixner1a59d1b82019-05-27 08:55:05 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002/*
Takashi Iwai763f3562005-06-03 11:25:34 +02003 * ALSA driver for RME Hammerfall DSP MADI audio interface(s)
4 *
5 * Copyright (c) 2003 Winfried Ritsch (IEM)
6 * code based on hdsp.c Paul Davis
7 * Marcus Andersson
8 * Thomas Charbonnel
Remy Bruno3cee5a62006-10-16 12:46:32 +02009 * Modified 2006-06-01 for AES32 support by Remy Bruno
10 * <remy.bruno@trinnov.com>
Takashi Iwai763f3562005-06-03 11:25:34 +020011 *
Adrian Knoth0dca1792011-01-26 19:32:14 +010012 * Modified 2009-04-13 for proper metering by Florian Faber
13 * <faber@faberman.de>
14 *
15 * Modified 2009-04-14 for native float support by Florian Faber
16 * <faber@faberman.de>
17 *
18 * Modified 2009-04-26 fixed bug in rms metering by Florian Faber
19 * <faber@faberman.de>
20 *
21 * Modified 2009-04-30 added hw serial number support by Florian Faber
22 *
23 * Modified 2011-01-14 added S/PDIF input on RayDATs by Adrian Knoth
24 *
25 * Modified 2011-01-25 variable period sizes on RayDAT/AIO by Adrian Knoth
26 *
Philippe Bekaerte4e07c62019-05-23 23:56:49 +020027 * Modified 2019-05-23 fix AIO single speed ADAT capture and playback
28 * by Philippe.Bekaert@uhasselt.be
Takashi Iwai763f3562005-06-03 11:25:34 +020029 */
Martin Dausel69358fc2013-07-05 11:28:23 +020030
31/* ************* Register Documentation *******************************************************
32 *
33 * Work in progress! Documentation is based on the code in this file.
34 *
35 * --------- HDSPM_controlRegister ---------
36 * :7654.3210:7654.3210:7654.3210:7654.3210: bit number per byte
37 * :||||.||||:||||.||||:||||.||||:||||.||||:
38 * :3322.2222:2222.1111:1111.1100:0000.0000: bit number
39 * :1098.7654:3210.9876:5432.1098:7654.3210: 0..31
40 * :||||.||||:||||.||||:||||.||||:||||.||||:
41 * :8421.8421:8421.8421:8421.8421:8421.8421: hex digit
42 * : . : . : . : x . : HDSPM_AudioInterruptEnable \_ setting both bits
43 * : . : . : . : . x: HDSPM_Start / enables audio IO
44 * : . : . : . : x. : HDSPM_ClockModeMaster - 1: Master, 0: Slave
45 * : . : . : . : .210 : HDSPM_LatencyMask - 3 Bit value for latency
46 * : . : . : . : . : 0:64, 1:128, 2:256, 3:512,
47 * : . : . : . : . : 4:1024, 5:2048, 6:4096, 7:8192
48 * :x . : . : . x:xx . : HDSPM_FrequencyMask
49 * : . : . : . :10 . : HDSPM_Frequency1|HDSPM_Frequency0: 1=32K,2=44.1K,3=48K,0=??
50 * : . : . : . x: . : <MADI> HDSPM_DoubleSpeed
51 * :x . : . : . : . : <MADI> HDSPM_QuadSpeed
52 * : . 3 : . 10: 2 . : . : HDSPM_SyncRefMask :
53 * : . : . x: . : . : HDSPM_SyncRef0
54 * : . : . x : . : . : HDSPM_SyncRef1
55 * : . : . : x . : . : <AES32> HDSPM_SyncRef2
56 * : . x : . : . : . : <AES32> HDSPM_SyncRef3
57 * : . : . 10: . : . : <MADI> sync ref: 0:WC, 1:Madi, 2:TCO, 3:SyncIn
58 * : . 3 : . 10: 2 . : . : <AES32> 0:WC, 1:AES1 ... 8:AES8, 9: TCO, 10:SyncIn?
59 * : . x : . : . : . : <MADIe> HDSPe_FLOAT_FORMAT
60 * : . : . : x . : . : <MADI> HDSPM_InputSelect0 : 0=optical,1=coax
61 * : . : . :x . : . : <MADI> HDSPM_InputSelect1
62 * : . : .x : . : . : <MADI> HDSPM_clr_tms
63 * : . : . : . x : . : <MADI> HDSPM_TX_64ch
64 * : . : . : . x : . : <AES32> HDSPM_Emphasis
65 * : . : . : .x : . : <MADI> HDSPM_AutoInp
66 * : . : . x : . : . : <MADI> HDSPM_SMUX
67 * : . : .x : . : . : <MADI> HDSPM_clr_tms
68 * : . : x. : . : . : <MADI> HDSPM_taxi_reset
69 * : . x: . : . : . : <MADI> HDSPM_LineOut
70 * : . x: . : . : . : <AES32> ??????????????????
71 * : . : x. : . : . : <AES32> HDSPM_WCK48
72 * : . : . : .x : . : <AES32> HDSPM_Dolby
73 * : . : x . : . : . : HDSPM_Midi0InterruptEnable
74 * : . :x . : . : . : HDSPM_Midi1InterruptEnable
75 * : . : x . : . : . : HDSPM_Midi2InterruptEnable
76 * : . x : . : . : . : <MADI> HDSPM_Midi3InterruptEnable
77 * : . x : . : . : . : <AES32> HDSPM_DS_DoubleWire
78 * : .x : . : . : . : <AES32> HDSPM_QS_DoubleWire
79 * : x. : . : . : . : <AES32> HDSPM_QS_QuadWire
80 * : . : . : . x : . : <AES32> HDSPM_Professional
81 * : x . : . : . : . : HDSPM_wclk_sel
82 * : . : . : . : . :
83 * :7654.3210:7654.3210:7654.3210:7654.3210: bit number per byte
84 * :||||.||||:||||.||||:||||.||||:||||.||||:
85 * :3322.2222:2222.1111:1111.1100:0000.0000: bit number
86 * :1098.7654:3210.9876:5432.1098:7654.3210: 0..31
87 * :||||.||||:||||.||||:||||.||||:||||.||||:
88 * :8421.8421:8421.8421:8421.8421:8421.8421:hex digit
89 *
90 *
91 *
92 * AIO / RayDAT only
93 *
94 * ------------ HDSPM_WR_SETTINGS ----------
95 * :3322.2222:2222.1111:1111.1100:0000.0000: bit number per byte
96 * :1098.7654:3210.9876:5432.1098:7654.3210:
97 * :||||.||||:||||.||||:||||.||||:||||.||||: bit number
98 * :7654.3210:7654.3210:7654.3210:7654.3210: 0..31
99 * :||||.||||:||||.||||:||||.||||:||||.||||:
100 * :8421.8421:8421.8421:8421.8421:8421.8421: hex digit
101 * : . : . : . : . x: HDSPM_c0Master 1: Master, 0: Slave
102 * : . : . : . : . x : HDSPM_c0_SyncRef0
103 * : . : . : . : . x : HDSPM_c0_SyncRef1
104 * : . : . : . : .x : HDSPM_c0_SyncRef2
105 * : . : . : . : x. : HDSPM_c0_SyncRef3
106 * : . : . : . : 3.210 : HDSPM_c0_SyncRefMask:
107 * : . : . : . : . : RayDat: 0:WC, 1:AES, 2:SPDIF, 3..6: ADAT1..4,
108 * : . : . : . : . : 9:TCO, 10:SyncIn
109 * : . : . : . : . : AIO: 0:WC, 1:AES, 2: SPDIF, 3: ATAT,
110 * : . : . : . : . : 9:TCO, 10:SyncIn
111 * : . : . : . : . :
112 * : . : . : . : . :
113 * :3322.2222:2222.1111:1111.1100:0000.0000: bit number per byte
114 * :1098.7654:3210.9876:5432.1098:7654.3210:
115 * :||||.||||:||||.||||:||||.||||:||||.||||: bit number
116 * :7654.3210:7654.3210:7654.3210:7654.3210: 0..31
117 * :||||.||||:||||.||||:||||.||||:||||.||||:
118 * :8421.8421:8421.8421:8421.8421:8421.8421: hex digit
119 *
120 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200121#include <linux/init.h>
122#include <linux/delay.h>
123#include <linux/interrupt.h>
Paul Gortmaker65a77212011-07-15 13:13:37 -0400124#include <linux/module.h>
Takashi Iwai763f3562005-06-03 11:25:34 +0200125#include <linux/slab.h>
126#include <linux/pci.h>
Takashi Iwai3f7440a2009-06-05 17:40:04 +0200127#include <linux/math64.h>
Takashi Iwai6cbbfe12015-01-28 16:49:33 +0100128#include <linux/io.h>
Takashi Iwai10513142018-04-24 08:03:14 +0200129#include <linux/nospec.h>
Takashi Iwai763f3562005-06-03 11:25:34 +0200130
131#include <sound/core.h>
132#include <sound/control.h>
133#include <sound/pcm.h>
Adrian Knoth0dca1792011-01-26 19:32:14 +0100134#include <sound/pcm_params.h>
Takashi Iwai763f3562005-06-03 11:25:34 +0200135#include <sound/info.h>
136#include <sound/asoundef.h>
137#include <sound/rawmidi.h>
138#include <sound/hwdep.h>
139#include <sound/initval.h>
140
141#include <sound/hdspm.h>
142
143static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
144static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
Rusty Russella67ff6a2011-12-15 13:49:36 +1030145static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
Takashi Iwai763f3562005-06-03 11:25:34 +0200146
Takashi Iwai763f3562005-06-03 11:25:34 +0200147module_param_array(index, int, NULL, 0444);
148MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");
149
150module_param_array(id, charp, NULL, 0444);
151MODULE_PARM_DESC(id, "ID string for RME HDSPM interface.");
152
153module_param_array(enable, bool, NULL, 0444);
154MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");
155
Takashi Iwai763f3562005-06-03 11:25:34 +0200156
157MODULE_AUTHOR
Adrian Knoth0dca1792011-01-26 19:32:14 +0100158(
159 "Winfried Ritsch <ritsch_AT_iem.at>, "
160 "Paul Davis <paul@linuxaudiosystems.com>, "
161 "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, "
162 "Remy Bruno <remy.bruno@trinnov.com>, "
163 "Florian Faber <faberman@linuxproaudio.org>, "
164 "Adrian Knoth <adi@drcomp.erfurt.thur.de>"
165);
Takashi Iwai763f3562005-06-03 11:25:34 +0200166MODULE_DESCRIPTION("RME HDSPM");
167MODULE_LICENSE("GPL");
Takashi Iwai763f3562005-06-03 11:25:34 +0200168
Adrian Knoth0dca1792011-01-26 19:32:14 +0100169/* --- Write registers. ---
Takashi Iwai763f3562005-06-03 11:25:34 +0200170 These are defined as byte-offsets from the iobase value. */
171
Adrian Knoth0dca1792011-01-26 19:32:14 +0100172#define HDSPM_WR_SETTINGS 0
173#define HDSPM_outputBufferAddress 32
174#define HDSPM_inputBufferAddress 36
Takashi Iwai763f3562005-06-03 11:25:34 +0200175#define HDSPM_controlRegister 64
176#define HDSPM_interruptConfirmation 96
177#define HDSPM_control2Reg 256 /* not in specs ???????? */
Martin Dausel69358fc2013-07-05 11:28:23 +0200178#define HDSPM_freqReg 256 /* for setting arbitrary clock values (DDS feature) */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100179#define HDSPM_midiDataOut0 352 /* just believe in old code */
180#define HDSPM_midiDataOut1 356
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100181#define HDSPM_eeprom_wr 384 /* for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200182
183/* DMA enable for 64 channels, only Bit 0 is relevant */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100184#define HDSPM_outputEnableBase 512 /* 512-767 input DMA */
Takashi Iwai763f3562005-06-03 11:25:34 +0200185#define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */
186
Adrian Knoth0dca1792011-01-26 19:32:14 +0100187/* 16 page addresses for each of the 64 channels DMA buffer in and out
Takashi Iwai763f3562005-06-03 11:25:34 +0200188 (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */
189#define HDSPM_pageAddressBufferOut 8192
190#define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4)
191
192#define HDSPM_MADI_mixerBase 32768 /* 32768-65535 for 2x64x64 Fader */
193
194#define HDSPM_MATRIX_MIXER_SIZE 8192 /* = 2*64*64 * 4 Byte => 32kB */
195
196/* --- Read registers. ---
197 These are defined as byte-offsets from the iobase value */
198#define HDSPM_statusRegister 0
Remy Bruno3cee5a62006-10-16 12:46:32 +0200199/*#define HDSPM_statusRegister2 96 */
200/* after RME Windows driver sources, status2 is 4-byte word # 48 = word at
201 * offset 192, for AES32 *and* MADI
202 * => need to check that offset 192 is working on MADI */
203#define HDSPM_statusRegister2 192
204#define HDSPM_timecodeRegister 128
Takashi Iwai763f3562005-06-03 11:25:34 +0200205
Adrian Knoth0dca1792011-01-26 19:32:14 +0100206/* AIO, RayDAT */
207#define HDSPM_RD_STATUS_0 0
208#define HDSPM_RD_STATUS_1 64
209#define HDSPM_RD_STATUS_2 128
210#define HDSPM_RD_STATUS_3 192
211
212#define HDSPM_RD_TCO 256
213#define HDSPM_RD_PLL_FREQ 512
214#define HDSPM_WR_TCO 128
215
216#define HDSPM_TCO1_TCO_lock 0x00000001
217#define HDSPM_TCO1_WCK_Input_Range_LSB 0x00000002
218#define HDSPM_TCO1_WCK_Input_Range_MSB 0x00000004
219#define HDSPM_TCO1_LTC_Input_valid 0x00000008
220#define HDSPM_TCO1_WCK_Input_valid 0x00000010
221#define HDSPM_TCO1_Video_Input_Format_NTSC 0x00000020
222#define HDSPM_TCO1_Video_Input_Format_PAL 0x00000040
223
224#define HDSPM_TCO1_set_TC 0x00000100
225#define HDSPM_TCO1_set_drop_frame_flag 0x00000200
226#define HDSPM_TCO1_LTC_Format_LSB 0x00000400
227#define HDSPM_TCO1_LTC_Format_MSB 0x00000800
228
229#define HDSPM_TCO2_TC_run 0x00010000
230#define HDSPM_TCO2_WCK_IO_ratio_LSB 0x00020000
231#define HDSPM_TCO2_WCK_IO_ratio_MSB 0x00040000
232#define HDSPM_TCO2_set_num_drop_frames_LSB 0x00080000
233#define HDSPM_TCO2_set_num_drop_frames_MSB 0x00100000
234#define HDSPM_TCO2_set_jam_sync 0x00200000
235#define HDSPM_TCO2_set_flywheel 0x00400000
236
237#define HDSPM_TCO2_set_01_4 0x01000000
238#define HDSPM_TCO2_set_pull_down 0x02000000
239#define HDSPM_TCO2_set_pull_up 0x04000000
240#define HDSPM_TCO2_set_freq 0x08000000
241#define HDSPM_TCO2_set_term_75R 0x10000000
242#define HDSPM_TCO2_set_input_LSB 0x20000000
243#define HDSPM_TCO2_set_input_MSB 0x40000000
244#define HDSPM_TCO2_set_freq_from_app 0x80000000
245
246
247#define HDSPM_midiDataOut0 352
248#define HDSPM_midiDataOut1 356
249#define HDSPM_midiDataOut2 368
250
Takashi Iwai763f3562005-06-03 11:25:34 +0200251#define HDSPM_midiDataIn0 360
252#define HDSPM_midiDataIn1 364
Adrian Knoth0dca1792011-01-26 19:32:14 +0100253#define HDSPM_midiDataIn2 372
254#define HDSPM_midiDataIn3 376
Takashi Iwai763f3562005-06-03 11:25:34 +0200255
256/* status is data bytes in MIDI-FIFO (0-128) */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100257#define HDSPM_midiStatusOut0 384
258#define HDSPM_midiStatusOut1 388
259#define HDSPM_midiStatusOut2 400
260
261#define HDSPM_midiStatusIn0 392
262#define HDSPM_midiStatusIn1 396
263#define HDSPM_midiStatusIn2 404
264#define HDSPM_midiStatusIn3 408
Takashi Iwai763f3562005-06-03 11:25:34 +0200265
266
267/* the meters are regular i/o-mapped registers, but offset
268 considerably from the rest. the peak registers are reset
Adrian Knoth0dca1792011-01-26 19:32:14 +0100269 when read; the least-significant 4 bits are full-scale counters;
Takashi Iwai763f3562005-06-03 11:25:34 +0200270 the actual peak value is in the most-significant 24 bits.
271*/
Adrian Knoth0dca1792011-01-26 19:32:14 +0100272
273#define HDSPM_MADI_INPUT_PEAK 4096
274#define HDSPM_MADI_PLAYBACK_PEAK 4352
275#define HDSPM_MADI_OUTPUT_PEAK 4608
276
277#define HDSPM_MADI_INPUT_RMS_L 6144
278#define HDSPM_MADI_PLAYBACK_RMS_L 6400
279#define HDSPM_MADI_OUTPUT_RMS_L 6656
280
281#define HDSPM_MADI_INPUT_RMS_H 7168
282#define HDSPM_MADI_PLAYBACK_RMS_H 7424
283#define HDSPM_MADI_OUTPUT_RMS_H 7680
Takashi Iwai763f3562005-06-03 11:25:34 +0200284
285/* --- Control Register bits --------- */
286#define HDSPM_Start (1<<0) /* start engine */
287
288#define HDSPM_Latency0 (1<<1) /* buffer size = 2^n */
289#define HDSPM_Latency1 (1<<2) /* where n is defined */
290#define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */
291
Adrian Knoth0dca1792011-01-26 19:32:14 +0100292#define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Autosync */
293#define HDSPM_c0Master 0x1 /* Master clock bit in settings
294 register [RayDAT, AIO] */
Takashi Iwai763f3562005-06-03 11:25:34 +0200295
296#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */
297
298#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */
299#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */
300#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200301#define HDSPM_QuadSpeed (1<<31) /* quad speed bit */
Takashi Iwai763f3562005-06-03 11:25:34 +0200302
Remy Bruno3cee5a62006-10-16 12:46:32 +0200303#define HDSPM_Professional (1<<9) /* Professional */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200304#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200305 56channelMODE=0 */ /* MADI ONLY*/
306#define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200307
Adrian Knoth0dca1792011-01-26 19:32:14 +0100308#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200309 0=off, 1=on */ /* MADI ONLY */
310#define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200311
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200312#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax
313 * -- MADI ONLY
314 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200315#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
316
Remy Bruno3cee5a62006-10-16 12:46:32 +0200317#define HDSPM_SyncRef2 (1<<13)
318#define HDSPM_SyncRef3 (1<<25)
Takashi Iwai763f3562005-06-03 11:25:34 +0200319
Remy Bruno3cee5a62006-10-16 12:46:32 +0200320#define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100321#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use
Takashi Iwai763f3562005-06-03 11:25:34 +0200322 AES additional bits in
323 lower 5 Audiodatabits ??? */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200324#define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */
325#define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200326
Adrian Knoth0dca1792011-01-26 19:32:14 +0100327#define HDSPM_Midi0InterruptEnable 0x0400000
328#define HDSPM_Midi1InterruptEnable 0x0800000
329#define HDSPM_Midi2InterruptEnable 0x0200000
330#define HDSPM_Midi3InterruptEnable 0x4000000
Takashi Iwai763f3562005-06-03 11:25:34 +0200331
332#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100333#define HDSPe_FLOAT_FORMAT 0x2000000
Takashi Iwai763f3562005-06-03 11:25:34 +0200334
Remy Bruno3cee5a62006-10-16 12:46:32 +0200335#define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */
336#define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */
337#define HDSPM_QS_QuadWire (1<<28) /* AES32 ONLY */
338
339#define HDSPM_wclk_sel (1<<30)
Takashi Iwai763f3562005-06-03 11:25:34 +0200340
Adrian Knoth384f7782013-07-05 11:27:53 +0200341/* additional control register bits for AIO*/
342#define HDSPM_c0_Wck48 0x20 /* also RayDAT */
343#define HDSPM_c0_Input0 0x1000
344#define HDSPM_c0_Input1 0x2000
345#define HDSPM_c0_Spdif_Opt 0x4000
346#define HDSPM_c0_Pro 0x8000
347#define HDSPM_c0_clr_tms 0x10000
348#define HDSPM_c0_AEB1 0x20000
349#define HDSPM_c0_AEB2 0x40000
350#define HDSPM_c0_LineOut 0x80000
351#define HDSPM_c0_AD_GAIN0 0x100000
352#define HDSPM_c0_AD_GAIN1 0x200000
353#define HDSPM_c0_DA_GAIN0 0x400000
354#define HDSPM_c0_DA_GAIN1 0x800000
355#define HDSPM_c0_PH_GAIN0 0x1000000
356#define HDSPM_c0_PH_GAIN1 0x2000000
357#define HDSPM_c0_Sym6db 0x4000000
358
359
Takashi Iwai763f3562005-06-03 11:25:34 +0200360/* --- bit helper defines */
361#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200362#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|\
363 HDSPM_DoubleSpeed|HDSPM_QuadSpeed)
Takashi Iwai763f3562005-06-03 11:25:34 +0200364#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1)
365#define HDSPM_InputOptical 0
366#define HDSPM_InputCoaxial (HDSPM_InputSelect0)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200367#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\
368 HDSPM_SyncRef2|HDSPM_SyncRef3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200369
Adrian Knoth0dca1792011-01-26 19:32:14 +0100370#define HDSPM_c0_SyncRef0 0x2
371#define HDSPM_c0_SyncRef1 0x4
372#define HDSPM_c0_SyncRef2 0x8
373#define HDSPM_c0_SyncRef3 0x10
374#define HDSPM_c0_SyncRefMask (HDSPM_c0_SyncRef0 | HDSPM_c0_SyncRef1 |\
375 HDSPM_c0_SyncRef2 | HDSPM_c0_SyncRef3)
376
377#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */
378#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */
379#define HDSPM_SYNC_FROM_TCO 2
380#define HDSPM_SYNC_FROM_SYNC_IN 3
Takashi Iwai763f3562005-06-03 11:25:34 +0200381
382#define HDSPM_Frequency32KHz HDSPM_Frequency0
383#define HDSPM_Frequency44_1KHz HDSPM_Frequency1
384#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0)
385#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0)
386#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200387#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|\
388 HDSPM_Frequency0)
Remy Bruno3cee5a62006-10-16 12:46:32 +0200389#define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0)
390#define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200391#define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\
392 HDSPM_Frequency0)
Takashi Iwai763f3562005-06-03 11:25:34 +0200393
Takashi Iwai763f3562005-06-03 11:25:34 +0200394
395/* Synccheck Status */
396#define HDSPM_SYNC_CHECK_NO_LOCK 0
397#define HDSPM_SYNC_CHECK_LOCK 1
398#define HDSPM_SYNC_CHECK_SYNC 2
399
400/* AutoSync References - used by "autosync_ref" control switch */
401#define HDSPM_AUTOSYNC_FROM_WORD 0
402#define HDSPM_AUTOSYNC_FROM_MADI 1
Adrian Knoth0dca1792011-01-26 19:32:14 +0100403#define HDSPM_AUTOSYNC_FROM_TCO 2
404#define HDSPM_AUTOSYNC_FROM_SYNC_IN 3
405#define HDSPM_AUTOSYNC_FROM_NONE 4
Takashi Iwai763f3562005-06-03 11:25:34 +0200406
407/* Possible sources of MADI input */
408#define HDSPM_OPTICAL 0 /* optical */
409#define HDSPM_COAXIAL 1 /* BNC */
410
411#define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask)
Adrian Knoth0dca1792011-01-26 19:32:14 +0100412#define hdspm_decode_latency(x) ((((x) & HDSPM_LatencyMask)>>1))
Takashi Iwai763f3562005-06-03 11:25:34 +0200413
414#define hdspm_encode_in(x) (((x)&0x3)<<14)
415#define hdspm_decode_in(x) (((x)>>14)&0x3)
416
417/* --- control2 register bits --- */
418#define HDSPM_TMS (1<<0)
419#define HDSPM_TCK (1<<1)
420#define HDSPM_TDI (1<<2)
421#define HDSPM_JTAG (1<<3)
422#define HDSPM_PWDN (1<<4)
423#define HDSPM_PROGRAM (1<<5)
424#define HDSPM_CONFIG_MODE_0 (1<<6)
425#define HDSPM_CONFIG_MODE_1 (1<<7)
426/*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/
427#define HDSPM_BIGENDIAN_MODE (1<<9)
428#define HDSPM_RD_MULTIPLE (1<<10)
429
Remy Bruno3cee5a62006-10-16 12:46:32 +0200430/* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200431 that do not conflict with specific bits for AES32 seem to be valid also
432 for the AES32
433 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200434#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200435#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn MODE=0 */
436#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1
437 * (like inp0)
438 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100439
Takashi Iwai763f3562005-06-03 11:25:34 +0200440#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100441#define HDSPM_madiSync (1<<18) /* MADI is in sync */
442
Adrian Knothb0bf5502013-07-05 11:28:05 +0200443#define HDSPM_tcoLockMadi 0x00000020 /* Optional TCO locked status for HDSPe MADI*/
444#define HDSPM_tcoSync 0x10000000 /* Optional TCO sync status for HDSPe MADI and AES32!*/
Adrian Knoth0dca1792011-01-26 19:32:14 +0100445
Adrian Knothb0bf5502013-07-05 11:28:05 +0200446#define HDSPM_syncInLock 0x00010000 /* Sync In lock status for HDSPe MADI! */
447#define HDSPM_syncInSync 0x00020000 /* Sync In sync status for HDSPe MADI! */
Takashi Iwai763f3562005-06-03 11:25:34 +0200448
449#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100450 /* since 64byte accurate, last 6 bits are not used */
Takashi Iwai763f3562005-06-03 11:25:34 +0200451
Adrian Knoth0dca1792011-01-26 19:32:14 +0100452
453
Takashi Iwai763f3562005-06-03 11:25:34 +0200454#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */
455
456#define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */
457#define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */
458#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */
459#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */
460
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200461#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with
462 * Interrupt
463 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100464#define HDSPM_tco_detect 0x08000000
Adrian Knothb0bf5502013-07-05 11:28:05 +0200465#define HDSPM_tcoLockAes 0x20000000 /* Optional TCO locked status for HDSPe AES */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100466
467#define HDSPM_s2_tco_detect 0x00000040
468#define HDSPM_s2_AEBO_D 0x00000080
469#define HDSPM_s2_AEBI_D 0x00000100
470
471
472#define HDSPM_midi0IRQPending 0x40000000
473#define HDSPM_midi1IRQPending 0x80000000
474#define HDSPM_midi2IRQPending 0x20000000
475#define HDSPM_midi2IRQPendingAES 0x00000020
476#define HDSPM_midi3IRQPending 0x00200000
Takashi Iwai763f3562005-06-03 11:25:34 +0200477
478/* --- status bit helpers */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200479#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\
480 HDSPM_madiFreq2|HDSPM_madiFreq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200481#define HDSPM_madiFreq32 (HDSPM_madiFreq0)
482#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1)
483#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1)
484#define HDSPM_madiFreq64 (HDSPM_madiFreq2)
485#define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2)
486#define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2)
487#define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2)
488#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
489#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0)
490
Remy Bruno3cee5a62006-10-16 12:46:32 +0200491/* Status2 Register bits */ /* MADI ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200492
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300493#define HDSPM_version0 (1<<0) /* not really defined but I guess */
Takashi Iwai763f3562005-06-03 11:25:34 +0200494#define HDSPM_version1 (1<<1) /* in former cards it was ??? */
495#define HDSPM_version2 (1<<2)
496
497#define HDSPM_wcLock (1<<3) /* Wordclock is detected and locked */
498#define HDSPM_wcSync (1<<4) /* Wordclock is in sync with systemclock */
499
500#define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */
501#define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */
Adrian Knotha8cd7142013-05-31 12:57:09 +0200502#define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, 111=128 */
503#define HDSPM_wc_freq3 0x800 /* 1000=176.4, 1001=192 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200504
Adrian Knoth0dca1792011-01-26 19:32:14 +0100505#define HDSPM_SyncRef0 0x10000 /* Sync Reference */
506#define HDSPM_SyncRef1 0x20000
507
508#define HDSPM_SelSyncRef0 (1<<8) /* AutoSync Source */
Takashi Iwai763f3562005-06-03 11:25:34 +0200509#define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */
510#define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */
511
512#define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync)
513
Adrian Knotha8cd7142013-05-31 12:57:09 +0200514#define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2|\
515 HDSPM_wc_freq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200516#define HDSPM_wcFreq32 (HDSPM_wc_freq0)
517#define HDSPM_wcFreq44_1 (HDSPM_wc_freq1)
518#define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1)
519#define HDSPM_wcFreq64 (HDSPM_wc_freq2)
520#define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2)
521#define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2)
Adrian Knotha8cd7142013-05-31 12:57:09 +0200522#define HDSPM_wcFreq128 (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2)
523#define HDSPM_wcFreq176_4 (HDSPM_wc_freq3)
524#define HDSPM_wcFreq192 (HDSPM_wc_freq0|HDSPM_wc_freq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200525
Adrian Knoth0dca1792011-01-26 19:32:14 +0100526#define HDSPM_status1_F_0 0x0400000
527#define HDSPM_status1_F_1 0x0800000
528#define HDSPM_status1_F_2 0x1000000
529#define HDSPM_status1_F_3 0x2000000
530#define HDSPM_status1_freqMask (HDSPM_status1_F_0|HDSPM_status1_F_1|HDSPM_status1_F_2|HDSPM_status1_F_3)
531
Takashi Iwai763f3562005-06-03 11:25:34 +0200532
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200533#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
534 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200535#define HDSPM_SelSyncRef_WORD 0
536#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0)
Adrian Knoth0dca1792011-01-26 19:32:14 +0100537#define HDSPM_SelSyncRef_TCO (HDSPM_SelSyncRef1)
538#define HDSPM_SelSyncRef_SyncIn (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200539#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
540 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200541
Remy Bruno3cee5a62006-10-16 12:46:32 +0200542/*
543 For AES32, bits for status, status2 and timecode are different
544*/
545/* status */
546#define HDSPM_AES32_wcLock 0x0200000
Andre Schramm56bde0f2013-01-09 14:40:18 +0100547#define HDSPM_AES32_wcSync 0x0100000
Remy Bruno3cee5a62006-10-16 12:46:32 +0200548#define HDSPM_AES32_wcFreq_bit 22
Adrian Knoth0dca1792011-01-26 19:32:14 +0100549/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function
Remy Bruno3cee5a62006-10-16 12:46:32 +0200550 HDSPM_bit2freq */
551#define HDSPM_AES32_syncref_bit 16
552/* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */
553
554#define HDSPM_AES32_AUTOSYNC_FROM_WORD 0
555#define HDSPM_AES32_AUTOSYNC_FROM_AES1 1
556#define HDSPM_AES32_AUTOSYNC_FROM_AES2 2
557#define HDSPM_AES32_AUTOSYNC_FROM_AES3 3
558#define HDSPM_AES32_AUTOSYNC_FROM_AES4 4
559#define HDSPM_AES32_AUTOSYNC_FROM_AES5 5
560#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6
561#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7
562#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8
Adrian Knothb0bf5502013-07-05 11:28:05 +0200563#define HDSPM_AES32_AUTOSYNC_FROM_TCO 9
564#define HDSPM_AES32_AUTOSYNC_FROM_SYNC_IN 10
565#define HDSPM_AES32_AUTOSYNC_FROM_NONE 11
Remy Bruno3cee5a62006-10-16 12:46:32 +0200566
567/* status2 */
568/* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */
569#define HDSPM_LockAES 0x80
570#define HDSPM_LockAES1 0x80
571#define HDSPM_LockAES2 0x40
572#define HDSPM_LockAES3 0x20
573#define HDSPM_LockAES4 0x10
574#define HDSPM_LockAES5 0x8
575#define HDSPM_LockAES6 0x4
576#define HDSPM_LockAES7 0x2
577#define HDSPM_LockAES8 0x1
578/*
579 Timecode
580 After windows driver sources, bits 4*i to 4*i+3 give the input frequency on
581 AES i+1
582 bits 3210
583 0001 32kHz
584 0010 44.1kHz
585 0011 48kHz
586 0100 64kHz
587 0101 88.2kHz
588 0110 96kHz
589 0111 128kHz
590 1000 176.4kHz
591 1001 192kHz
592 NB: Timecode register doesn't seem to work on AES32 card revision 230
593*/
594
Takashi Iwai763f3562005-06-03 11:25:34 +0200595/* Mixer Values */
596#define UNITY_GAIN 32768 /* = 65536/2 */
597#define MINUS_INFINITY_GAIN 0
598
Takashi Iwai763f3562005-06-03 11:25:34 +0200599/* Number of channels for different Speed Modes */
600#define MADI_SS_CHANNELS 64
601#define MADI_DS_CHANNELS 32
602#define MADI_QS_CHANNELS 16
603
Adrian Knoth0dca1792011-01-26 19:32:14 +0100604#define RAYDAT_SS_CHANNELS 36
605#define RAYDAT_DS_CHANNELS 20
606#define RAYDAT_QS_CHANNELS 12
607
608#define AIO_IN_SS_CHANNELS 14
609#define AIO_IN_DS_CHANNELS 10
610#define AIO_IN_QS_CHANNELS 8
611#define AIO_OUT_SS_CHANNELS 16
612#define AIO_OUT_DS_CHANNELS 12
613#define AIO_OUT_QS_CHANNELS 10
614
Adrian Knothd2d10a22011-02-28 15:14:47 +0100615#define AES32_CHANNELS 16
616
Takashi Iwai763f3562005-06-03 11:25:34 +0200617/* the size of a substream (1 mono data stream) */
618#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024)
619#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
620
621/* the size of the area we need to allocate for DMA transfers. the
622 size is the same regardless of the number of channels, and
Adrian Knoth0dca1792011-01-26 19:32:14 +0100623 also the latency to use.
Takashi Iwai763f3562005-06-03 11:25:34 +0200624 for one direction !!!
625*/
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100626#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
Takashi Iwai763f3562005-06-03 11:25:34 +0200627#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
628
Adrian Knoth0dca1792011-01-26 19:32:14 +0100629#define HDSPM_RAYDAT_REV 211
630#define HDSPM_AIO_REV 212
631#define HDSPM_MADIFACE_REV 213
Remy Bruno3cee5a62006-10-16 12:46:32 +0200632
Remy Bruno65345992007-08-31 12:21:08 +0200633/* speed factor modes */
634#define HDSPM_SPEED_SINGLE 0
635#define HDSPM_SPEED_DOUBLE 1
636#define HDSPM_SPEED_QUAD 2
Adrian Knoth0dca1792011-01-26 19:32:14 +0100637
Remy Bruno65345992007-08-31 12:21:08 +0200638/* names for speed modes */
Takashi Iwaie315cc32020-01-05 15:47:34 +0100639static const char * const hdspm_speed_names[] = { "single", "double", "quad" };
Remy Bruno65345992007-08-31 12:21:08 +0200640
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200641static const char *const texts_autosync_aes_tco[] = { "Word Clock",
Adrian Knoth0dca1792011-01-26 19:32:14 +0100642 "AES1", "AES2", "AES3", "AES4",
643 "AES5", "AES6", "AES7", "AES8",
Adrian Knothdb2d1a92013-07-05 11:28:08 +0200644 "TCO", "Sync In"
645};
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200646static const char *const texts_autosync_aes[] = { "Word Clock",
Adrian Knoth0dca1792011-01-26 19:32:14 +0100647 "AES1", "AES2", "AES3", "AES4",
Adrian Knothdb2d1a92013-07-05 11:28:08 +0200648 "AES5", "AES6", "AES7", "AES8",
649 "Sync In"
650};
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200651static const char *const texts_autosync_madi_tco[] = { "Word Clock",
Adrian Knoth0dca1792011-01-26 19:32:14 +0100652 "MADI", "TCO", "Sync In" };
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200653static const char *const texts_autosync_madi[] = { "Word Clock",
Adrian Knoth0dca1792011-01-26 19:32:14 +0100654 "MADI", "Sync In" };
655
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200656static const char *const texts_autosync_raydat_tco[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100657 "Word Clock",
658 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
659 "AES", "SPDIF", "TCO", "Sync In"
660};
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200661static const char *const texts_autosync_raydat[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100662 "Word Clock",
663 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
664 "AES", "SPDIF", "Sync In"
665};
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200666static const char *const texts_autosync_aio_tco[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100667 "Word Clock",
668 "ADAT", "AES", "SPDIF", "TCO", "Sync In"
669};
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200670static const char *const texts_autosync_aio[] = { "Word Clock",
Adrian Knoth0dca1792011-01-26 19:32:14 +0100671 "ADAT", "AES", "SPDIF", "Sync In" };
672
Adrian Knoth38816542013-07-05 11:28:20 +0200673static const char *const texts_freq[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100674 "No Lock",
675 "32 kHz",
676 "44.1 kHz",
677 "48 kHz",
678 "64 kHz",
679 "88.2 kHz",
680 "96 kHz",
681 "128 kHz",
682 "176.4 kHz",
683 "192 kHz"
684};
685
Takashi Iwaie315cc32020-01-05 15:47:34 +0100686static const char * const texts_ports_madi[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100687 "MADI.1", "MADI.2", "MADI.3", "MADI.4", "MADI.5", "MADI.6",
688 "MADI.7", "MADI.8", "MADI.9", "MADI.10", "MADI.11", "MADI.12",
689 "MADI.13", "MADI.14", "MADI.15", "MADI.16", "MADI.17", "MADI.18",
690 "MADI.19", "MADI.20", "MADI.21", "MADI.22", "MADI.23", "MADI.24",
691 "MADI.25", "MADI.26", "MADI.27", "MADI.28", "MADI.29", "MADI.30",
692 "MADI.31", "MADI.32", "MADI.33", "MADI.34", "MADI.35", "MADI.36",
693 "MADI.37", "MADI.38", "MADI.39", "MADI.40", "MADI.41", "MADI.42",
694 "MADI.43", "MADI.44", "MADI.45", "MADI.46", "MADI.47", "MADI.48",
695 "MADI.49", "MADI.50", "MADI.51", "MADI.52", "MADI.53", "MADI.54",
696 "MADI.55", "MADI.56", "MADI.57", "MADI.58", "MADI.59", "MADI.60",
697 "MADI.61", "MADI.62", "MADI.63", "MADI.64",
698};
699
700
Takashi Iwaie315cc32020-01-05 15:47:34 +0100701static const char * const texts_ports_raydat_ss[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100702 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT1.5", "ADAT1.6",
703 "ADAT1.7", "ADAT1.8", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
704 "ADAT2.5", "ADAT2.6", "ADAT2.7", "ADAT2.8", "ADAT3.1", "ADAT3.2",
705 "ADAT3.3", "ADAT3.4", "ADAT3.5", "ADAT3.6", "ADAT3.7", "ADAT3.8",
706 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4", "ADAT4.5", "ADAT4.6",
707 "ADAT4.7", "ADAT4.8",
708 "AES.L", "AES.R",
709 "SPDIF.L", "SPDIF.R"
710};
711
Takashi Iwaie315cc32020-01-05 15:47:34 +0100712static const char * const texts_ports_raydat_ds[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100713 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4",
714 "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
715 "ADAT3.1", "ADAT3.2", "ADAT3.3", "ADAT3.4",
716 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4",
717 "AES.L", "AES.R",
718 "SPDIF.L", "SPDIF.R"
719};
720
Takashi Iwaie315cc32020-01-05 15:47:34 +0100721static const char * const texts_ports_raydat_qs[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100722 "ADAT1.1", "ADAT1.2",
723 "ADAT2.1", "ADAT2.2",
724 "ADAT3.1", "ADAT3.2",
725 "ADAT4.1", "ADAT4.2",
726 "AES.L", "AES.R",
727 "SPDIF.L", "SPDIF.R"
728};
729
730
Takashi Iwaie315cc32020-01-05 15:47:34 +0100731static const char * const texts_ports_aio_in_ss[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100732 "Analogue.L", "Analogue.R",
733 "AES.L", "AES.R",
734 "SPDIF.L", "SPDIF.R",
735 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200736 "ADAT.7", "ADAT.8",
737 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100738};
739
Takashi Iwaie315cc32020-01-05 15:47:34 +0100740static const char * const texts_ports_aio_out_ss[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100741 "Analogue.L", "Analogue.R",
742 "AES.L", "AES.R",
743 "SPDIF.L", "SPDIF.R",
744 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
745 "ADAT.7", "ADAT.8",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200746 "Phone.L", "Phone.R",
747 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100748};
749
Takashi Iwaie315cc32020-01-05 15:47:34 +0100750static const char * const texts_ports_aio_in_ds[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100751 "Analogue.L", "Analogue.R",
752 "AES.L", "AES.R",
753 "SPDIF.L", "SPDIF.R",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200754 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
755 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100756};
757
Takashi Iwaie315cc32020-01-05 15:47:34 +0100758static const char * const texts_ports_aio_out_ds[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100759 "Analogue.L", "Analogue.R",
760 "AES.L", "AES.R",
761 "SPDIF.L", "SPDIF.R",
762 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200763 "Phone.L", "Phone.R",
764 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100765};
766
Takashi Iwaie315cc32020-01-05 15:47:34 +0100767static const char * const texts_ports_aio_in_qs[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100768 "Analogue.L", "Analogue.R",
769 "AES.L", "AES.R",
770 "SPDIF.L", "SPDIF.R",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200771 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
772 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100773};
774
Takashi Iwaie315cc32020-01-05 15:47:34 +0100775static const char * const texts_ports_aio_out_qs[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100776 "Analogue.L", "Analogue.R",
777 "AES.L", "AES.R",
778 "SPDIF.L", "SPDIF.R",
779 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200780 "Phone.L", "Phone.R",
781 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100782};
783
Takashi Iwaie315cc32020-01-05 15:47:34 +0100784static const char * const texts_ports_aes32[] = {
Adrian Knoth432d2502011-02-23 11:43:08 +0100785 "AES.1", "AES.2", "AES.3", "AES.4", "AES.5", "AES.6", "AES.7",
786 "AES.8", "AES.9.", "AES.10", "AES.11", "AES.12", "AES.13", "AES.14",
787 "AES.15", "AES.16"
788};
789
Adrian Knoth55a57602011-01-27 11:23:15 +0100790/* These tables map the ALSA channels 1..N to the channels that we
791 need to use in order to find the relevant channel buffer. RME
792 refers to this kind of mapping as between "the ADAT channel and
793 the DMA channel." We index it using the logical audio channel,
794 and the value is the DMA channel (i.e. channel buffer number)
795 where the data for that channel can be read/written from/to.
796*/
797
Takashi Iwaie315cc32020-01-05 15:47:34 +0100798static const char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = {
Adrian Knoth55a57602011-01-27 11:23:15 +0100799 0, 1, 2, 3, 4, 5, 6, 7,
800 8, 9, 10, 11, 12, 13, 14, 15,
801 16, 17, 18, 19, 20, 21, 22, 23,
802 24, 25, 26, 27, 28, 29, 30, 31,
803 32, 33, 34, 35, 36, 37, 38, 39,
804 40, 41, 42, 43, 44, 45, 46, 47,
805 48, 49, 50, 51, 52, 53, 54, 55,
806 56, 57, 58, 59, 60, 61, 62, 63
807};
808
Takashi Iwaie315cc32020-01-05 15:47:34 +0100809static const char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = {
Adrian Knoth55a57602011-01-27 11:23:15 +0100810 4, 5, 6, 7, 8, 9, 10, 11, /* ADAT 1 */
811 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT 2 */
812 20, 21, 22, 23, 24, 25, 26, 27, /* ADAT 3 */
813 28, 29, 30, 31, 32, 33, 34, 35, /* ADAT 4 */
814 0, 1, /* AES */
815 2, 3, /* SPDIF */
816 -1, -1, -1, -1,
817 -1, -1, -1, -1, -1, -1, -1, -1,
818 -1, -1, -1, -1, -1, -1, -1, -1,
819 -1, -1, -1, -1, -1, -1, -1, -1,
820};
821
Takashi Iwaie315cc32020-01-05 15:47:34 +0100822static const char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = {
Adrian Knoth55a57602011-01-27 11:23:15 +0100823 4, 5, 6, 7, /* ADAT 1 */
824 8, 9, 10, 11, /* ADAT 2 */
825 12, 13, 14, 15, /* ADAT 3 */
826 16, 17, 18, 19, /* ADAT 4 */
827 0, 1, /* AES */
828 2, 3, /* SPDIF */
829 -1, -1, -1, -1,
830 -1, -1, -1, -1, -1, -1, -1, -1,
831 -1, -1, -1, -1, -1, -1, -1, -1,
832 -1, -1, -1, -1, -1, -1, -1, -1,
833 -1, -1, -1, -1, -1, -1, -1, -1,
834 -1, -1, -1, -1, -1, -1, -1, -1,
835};
836
Takashi Iwaie315cc32020-01-05 15:47:34 +0100837static const char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = {
Adrian Knoth55a57602011-01-27 11:23:15 +0100838 4, 5, /* ADAT 1 */
839 6, 7, /* ADAT 2 */
840 8, 9, /* ADAT 3 */
841 10, 11, /* ADAT 4 */
842 0, 1, /* AES */
843 2, 3, /* SPDIF */
844 -1, -1, -1, -1,
845 -1, -1, -1, -1, -1, -1, -1, -1,
846 -1, -1, -1, -1, -1, -1, -1, -1,
847 -1, -1, -1, -1, -1, -1, -1, -1,
848 -1, -1, -1, -1, -1, -1, -1, -1,
849 -1, -1, -1, -1, -1, -1, -1, -1,
850 -1, -1, -1, -1, -1, -1, -1, -1,
851};
852
Takashi Iwaie315cc32020-01-05 15:47:34 +0100853static const char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = {
Adrian Knoth55a57602011-01-27 11:23:15 +0100854 0, 1, /* line in */
855 8, 9, /* aes in, */
856 10, 11, /* spdif in */
857 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT in */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200858 2, 3, 4, 5, /* AEB */
859 -1, -1, -1, -1, -1, -1,
Adrian Knoth55a57602011-01-27 11:23:15 +0100860 -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 -1, -1, -1, -1, -1, -1, -1, -1,
864 -1, -1, -1, -1, -1, -1, -1, -1,
865};
866
Takashi Iwaie315cc32020-01-05 15:47:34 +0100867static const char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = {
Adrian Knoth55a57602011-01-27 11:23:15 +0100868 0, 1, /* line out */
869 8, 9, /* aes out */
870 10, 11, /* spdif out */
871 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT out */
872 6, 7, /* phone out */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200873 2, 3, 4, 5, /* AEB */
874 -1, -1, -1, -1,
Adrian Knoth55a57602011-01-27 11:23:15 +0100875 -1, -1, -1, -1, -1, -1, -1, -1,
876 -1, -1, -1, -1, -1, -1, -1, -1,
877 -1, -1, -1, -1, -1, -1, -1, -1,
878 -1, -1, -1, -1, -1, -1, -1, -1,
879 -1, -1, -1, -1, -1, -1, -1, -1,
880};
881
Takashi Iwaie315cc32020-01-05 15:47:34 +0100882static const char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = {
Adrian Knoth55a57602011-01-27 11:23:15 +0100883 0, 1, /* line in */
884 8, 9, /* aes in */
885 10, 11, /* spdif in */
886 12, 14, 16, 18, /* adat in */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200887 2, 3, 4, 5, /* AEB */
888 -1, -1,
Adrian Knoth55a57602011-01-27 11:23:15 +0100889 -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 -1, -1, -1, -1, -1, -1, -1, -1,
893 -1, -1, -1, -1, -1, -1, -1, -1,
894 -1, -1, -1, -1, -1, -1, -1, -1
895};
896
Takashi Iwaie315cc32020-01-05 15:47:34 +0100897static const char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = {
Adrian Knoth55a57602011-01-27 11:23:15 +0100898 0, 1, /* line out */
899 8, 9, /* aes out */
900 10, 11, /* spdif out */
901 12, 14, 16, 18, /* adat out */
902 6, 7, /* phone out */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200903 2, 3, 4, 5, /* AEB */
Adrian Knoth55a57602011-01-27 11:23:15 +0100904 -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 -1, -1, -1, -1, -1, -1, -1, -1,
908 -1, -1, -1, -1, -1, -1, -1, -1,
909 -1, -1, -1, -1, -1, -1, -1, -1
910};
911
Takashi Iwaie315cc32020-01-05 15:47:34 +0100912static const char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = {
Adrian Knoth55a57602011-01-27 11:23:15 +0100913 0, 1, /* line in */
914 8, 9, /* aes in */
915 10, 11, /* spdif in */
916 12, 16, /* adat in */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200917 2, 3, 4, 5, /* AEB */
918 -1, -1, -1, -1,
Adrian Knoth55a57602011-01-27 11:23:15 +0100919 -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 -1, -1, -1, -1, -1, -1, -1, -1,
923 -1, -1, -1, -1, -1, -1, -1, -1,
924 -1, -1, -1, -1, -1, -1, -1, -1
925};
926
Takashi Iwaie315cc32020-01-05 15:47:34 +0100927static const char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = {
Adrian Knoth55a57602011-01-27 11:23:15 +0100928 0, 1, /* line out */
929 8, 9, /* aes out */
930 10, 11, /* spdif out */
931 12, 16, /* adat out */
932 6, 7, /* phone out */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200933 2, 3, 4, 5, /* AEB */
934 -1, -1,
Adrian Knoth55a57602011-01-27 11:23:15 +0100935 -1, -1, -1, -1, -1, -1, -1, -1,
936 -1, -1, -1, -1, -1, -1, -1, -1,
937 -1, -1, -1, -1, -1, -1, -1, -1,
938 -1, -1, -1, -1, -1, -1, -1, -1,
939 -1, -1, -1, -1, -1, -1, -1, -1,
940 -1, -1, -1, -1, -1, -1, -1, -1
941};
942
Takashi Iwaie315cc32020-01-05 15:47:34 +0100943static const char channel_map_aes32[HDSPM_MAX_CHANNELS] = {
Adrian Knoth432d2502011-02-23 11:43:08 +0100944 0, 1, 2, 3, 4, 5, 6, 7,
945 8, 9, 10, 11, 12, 13, 14, 15,
946 -1, -1, -1, -1, -1, -1, -1, -1,
947 -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};
953
Takashi Iwai98274f02005-11-17 14:52:34 +0100954struct hdspm_midi {
955 struct hdspm *hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +0200956 int id;
Takashi Iwai98274f02005-11-17 14:52:34 +0100957 struct snd_rawmidi *rmidi;
958 struct snd_rawmidi_substream *input;
959 struct snd_rawmidi_substream *output;
Takashi Iwai763f3562005-06-03 11:25:34 +0200960 char istimer; /* timer in use */
961 struct timer_list timer;
962 spinlock_t lock;
963 int pending;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100964 int dataIn;
965 int statusIn;
966 int dataOut;
967 int statusOut;
968 int ie;
969 int irq;
970};
971
972struct hdspm_tco {
Martin Dausel69358fc2013-07-05 11:28:23 +0200973 int input; /* 0: LTC, 1:Video, 2: WC*/
974 int framerate; /* 0=24, 1=25, 2=29.97, 3=29.97d, 4=30, 5=30d */
975 int wordclock; /* 0=1:1, 1=44.1->48, 2=48->44.1 */
976 int samplerate; /* 0=44.1, 1=48, 2= freq from app */
977 int pull; /* 0=0, 1=+0.1%, 2=-0.1%, 3=+4%, 4=-4%*/
Adrian Knoth0dca1792011-01-26 19:32:14 +0100978 int term; /* 0 = off, 1 = on */
Takashi Iwai763f3562005-06-03 11:25:34 +0200979};
980
Takashi Iwai98274f02005-11-17 14:52:34 +0100981struct hdspm {
Takashi Iwai763f3562005-06-03 11:25:34 +0200982 spinlock_t lock;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200983 /* only one playback and/or capture stream */
984 struct snd_pcm_substream *capture_substream;
985 struct snd_pcm_substream *playback_substream;
Takashi Iwai763f3562005-06-03 11:25:34 +0200986
987 char *card_name; /* for procinfo */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200988 unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
989
Adrian Knoth0dca1792011-01-26 19:32:14 +0100990 uint8_t io_type;
Takashi Iwai763f3562005-06-03 11:25:34 +0200991
Takashi Iwai763f3562005-06-03 11:25:34 +0200992 int monitor_outs; /* set up monitoring outs init flag */
993
994 u32 control_register; /* cached value */
995 u32 control2_register; /* cached value */
Martin Dausel69358fc2013-07-05 11:28:23 +0200996 u32 settings_register; /* cached value for AIO / RayDat (sync reference, master/slave) */
Takashi Iwai763f3562005-06-03 11:25:34 +0200997
Adrian Knoth0dca1792011-01-26 19:32:14 +0100998 struct hdspm_midi midi[4];
Takashi Iwaia2e527c2020-09-03 12:41:27 +0200999 struct work_struct midi_work;
Takashi Iwai763f3562005-06-03 11:25:34 +02001000
1001 size_t period_bytes;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001002 unsigned char ss_in_channels;
1003 unsigned char ds_in_channels;
1004 unsigned char qs_in_channels;
1005 unsigned char ss_out_channels;
1006 unsigned char ds_out_channels;
1007 unsigned char qs_out_channels;
1008
1009 unsigned char max_channels_in;
1010 unsigned char max_channels_out;
1011
Takashi Iwaie315cc32020-01-05 15:47:34 +01001012 const signed char *channel_map_in;
1013 const signed char *channel_map_out;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001014
Takashi Iwaie315cc32020-01-05 15:47:34 +01001015 const signed char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs;
1016 const signed char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001017
Takashi Iwaie315cc32020-01-05 15:47:34 +01001018 const char * const *port_names_in;
1019 const char * const *port_names_out;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001020
Takashi Iwaie315cc32020-01-05 15:47:34 +01001021 const char * const *port_names_in_ss;
1022 const char * const *port_names_in_ds;
1023 const char * const *port_names_in_qs;
1024 const char * const *port_names_out_ss;
1025 const char * const *port_names_out_ds;
1026 const char * const *port_names_out_qs;
Takashi Iwai763f3562005-06-03 11:25:34 +02001027
1028 unsigned char *playback_buffer; /* suitably aligned address */
1029 unsigned char *capture_buffer; /* suitably aligned address */
1030
1031 pid_t capture_pid; /* process id which uses capture */
1032 pid_t playback_pid; /* process id which uses capture */
1033 int running; /* running status */
1034
1035 int last_external_sample_rate; /* samplerate mystic ... */
1036 int last_internal_sample_rate;
1037 int system_sample_rate;
1038
Takashi Iwai763f3562005-06-03 11:25:34 +02001039 int dev; /* Hardware vars... */
1040 int irq;
1041 unsigned long port;
1042 void __iomem *iobase;
1043
1044 int irq_count; /* for debug */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001045 int midiPorts;
Takashi Iwai763f3562005-06-03 11:25:34 +02001046
Takashi Iwai98274f02005-11-17 14:52:34 +01001047 struct snd_card *card; /* one card */
1048 struct snd_pcm *pcm; /* has one pcm */
1049 struct snd_hwdep *hwdep; /* and a hwdep for additional ioctl */
Takashi Iwai763f3562005-06-03 11:25:34 +02001050 struct pci_dev *pci; /* and an pci info */
1051
1052 /* Mixer vars */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001053 /* fast alsa mixer */
1054 struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS];
1055 /* but input to much, so not used */
1056 struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS];
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001057 /* full mixer accessible over mixer ioctl or hwdep-device */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001058 struct hdspm_mixer *mixer;
Takashi Iwai763f3562005-06-03 11:25:34 +02001059
Adrian Knoth0dca1792011-01-26 19:32:14 +01001060 struct hdspm_tco *tco; /* NULL if no TCO detected */
Takashi Iwai763f3562005-06-03 11:25:34 +02001061
Adrian Knotheb0d4db2013-07-05 11:28:21 +02001062 const char *const *texts_autosync;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001063 int texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +02001064
Adrian Knoth0dca1792011-01-26 19:32:14 +01001065 cycles_t last_interrupt;
Jaroslav Kysela730a5862011-01-27 13:03:15 +01001066
Adrian Knoth7d53a632012-01-04 14:31:16 +01001067 unsigned int serial;
1068
Jaroslav Kysela730a5862011-01-27 13:03:15 +01001069 struct hdspm_peak_rms peak_rms;
Takashi Iwai763f3562005-06-03 11:25:34 +02001070};
1071
Takashi Iwai763f3562005-06-03 11:25:34 +02001072
Benoit Taine9baa3c32014-08-08 15:56:03 +02001073static const struct pci_device_id snd_hdspm_ids[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02001074 {
1075 .vendor = PCI_VENDOR_ID_XILINX,
1076 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
1077 .subvendor = PCI_ANY_ID,
1078 .subdevice = PCI_ANY_ID,
1079 .class = 0,
1080 .class_mask = 0,
1081 .driver_data = 0},
1082 {0,}
1083};
1084
1085MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
1086
1087/* prototypes */
Bill Pembertone23e7a12012-12-06 12:35:10 -05001088static int snd_hdspm_create_alsa_devices(struct snd_card *card,
1089 struct hdspm *hdspm);
1090static int snd_hdspm_create_pcm(struct snd_card *card,
1091 struct hdspm *hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001092
Adrian Knoth0dca1792011-01-26 19:32:14 +01001093static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
Adrian Knoth3f7bf912013-03-10 00:37:21 +01001094static inline int hdspm_get_pll_freq(struct hdspm *hdspm);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001095static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
1096static int hdspm_autosync_ref(struct hdspm *hdspm);
Adrian Knoth34be7ebb2013-07-05 11:27:56 +02001097static int hdspm_set_toggle_setting(struct hdspm *hdspm, u32 regmask, int out);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001098static int snd_hdspm_set_defaults(struct hdspm *hdspm);
Adrian Knoth21a164d2012-10-19 17:42:23 +02001099static int hdspm_system_clock_mode(struct hdspm *hdspm);
Philippe Bekaerte4e07c62019-05-23 23:56:49 +02001100static void hdspm_set_channel_dma_addr(struct hdspm *hdspm,
1101 struct snd_pcm_substream *substream,
1102 unsigned int reg, int channels);
Takashi Iwai763f3562005-06-03 11:25:34 +02001103
Adrian Knoth5b266352013-07-05 11:28:10 +02001104static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx);
1105static int hdspm_wc_sync_check(struct hdspm *hdspm);
1106static int hdspm_tco_sync_check(struct hdspm *hdspm);
1107static int hdspm_sync_in_sync_check(struct hdspm *hdspm);
1108
1109static int hdspm_get_aes_sample_rate(struct hdspm *hdspm, int index);
1110static int hdspm_get_tco_sample_rate(struct hdspm *hdspm);
1111static int hdspm_get_wc_sample_rate(struct hdspm *hdspm);
1112
1113
1114
Remy Bruno3cee5a62006-10-16 12:46:32 +02001115static inline int HDSPM_bit2freq(int n)
1116{
Denys Vlasenko62cef822008-04-14 13:04:18 +02001117 static const int bit2freq_tab[] = {
1118 0, 32000, 44100, 48000, 64000, 88200,
Remy Bruno3cee5a62006-10-16 12:46:32 +02001119 96000, 128000, 176400, 192000 };
1120 if (n < 1 || n > 9)
1121 return 0;
1122 return bit2freq_tab[n];
1123}
1124
Adrian Knothb2ed6322013-07-05 11:27:54 +02001125static bool hdspm_is_raydat_or_aio(struct hdspm *hdspm)
1126{
1127 return ((AIO == hdspm->io_type) || (RayDAT == hdspm->io_type));
1128}
1129
1130
Adrian Knoth0dca1792011-01-26 19:32:14 +01001131/* Write/read to/from HDSPM with Adresses in Bytes
Takashi Iwai763f3562005-06-03 11:25:34 +02001132 not words but only 32Bit writes are allowed */
1133
Takashi Iwai98274f02005-11-17 14:52:34 +01001134static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
Takashi Iwai763f3562005-06-03 11:25:34 +02001135 unsigned int val)
1136{
1137 writel(val, hdspm->iobase + reg);
1138}
1139
Takashi Iwai98274f02005-11-17 14:52:34 +01001140static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
Takashi Iwai763f3562005-06-03 11:25:34 +02001141{
1142 return readl(hdspm->iobase + reg);
1143}
1144
Adrian Knoth0dca1792011-01-26 19:32:14 +01001145/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
1146 mixer is write only on hardware so we have to cache him for read
Takashi Iwai763f3562005-06-03 11:25:34 +02001147 each fader is a u32, but uses only the first 16 bit */
1148
Takashi Iwai98274f02005-11-17 14:52:34 +01001149static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001150 unsigned int in)
1151{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001152 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001153 return 0;
1154
1155 return hdspm->mixer->ch[chan].in[in];
1156}
1157
Takashi Iwai98274f02005-11-17 14:52:34 +01001158static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001159 unsigned int pb)
1160{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001161 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001162 return 0;
1163 return hdspm->mixer->ch[chan].pb[pb];
1164}
1165
Denys Vlasenko62cef822008-04-14 13:04:18 +02001166static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001167 unsigned int in, unsigned short data)
1168{
1169 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
1170 return -1;
1171
1172 hdspm_write(hdspm,
1173 HDSPM_MADI_mixerBase +
1174 ((in + 128 * chan) * sizeof(u32)),
1175 (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
1176 return 0;
1177}
1178
Denys Vlasenko62cef822008-04-14 13:04:18 +02001179static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001180 unsigned int pb, unsigned short data)
1181{
1182 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
1183 return -1;
1184
1185 hdspm_write(hdspm,
1186 HDSPM_MADI_mixerBase +
1187 ((64 + pb + 128 * chan) * sizeof(u32)),
1188 (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
1189 return 0;
1190}
1191
1192
1193/* enable DMA for specific channels, now available for DSP-MADI */
Takashi Iwai98274f02005-11-17 14:52:34 +01001194static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001195{
1196 hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
1197}
1198
Takashi Iwai98274f02005-11-17 14:52:34 +01001199static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001200{
1201 hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
1202}
1203
1204/* check if same process is writing and reading */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001205static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001206{
1207 unsigned long flags;
1208 int ret = 1;
1209
1210 spin_lock_irqsave(&hdspm->lock, flags);
1211 if ((hdspm->playback_pid != hdspm->capture_pid) &&
1212 (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
1213 ret = 0;
1214 }
1215 spin_unlock_irqrestore(&hdspm->lock, flags);
1216 return ret;
1217}
1218
Naoki Hayama7dcd5612020-10-08 17:47:44 +09001219/* round arbitrary sample rates to commonly known rates */
Adrian Knothfcdc4ba2013-03-10 00:37:22 +01001220static int hdspm_round_frequency(int rate)
1221{
1222 if (rate < 38050)
1223 return 32000;
1224 if (rate < 46008)
1225 return 44100;
1226 else
1227 return 48000;
1228}
1229
Adrian Knotha8a729f2013-05-31 12:57:10 +02001230/* QS and DS rates normally can not be detected
1231 * automatically by the card. Only exception is MADI
1232 * in 96k frame mode.
1233 *
1234 * So if we read SS values (32 .. 48k), check for
1235 * user-provided DS/QS bits in the control register
1236 * and multiply the base frequency accordingly.
1237 */
1238static int hdspm_rate_multiplier(struct hdspm *hdspm, int rate)
1239{
1240 if (rate <= 48000) {
1241 if (hdspm->control_register & HDSPM_QuadSpeed)
1242 return rate * 4;
1243 else if (hdspm->control_register &
1244 HDSPM_DoubleSpeed)
1245 return rate * 2;
Fengguang Wu68593c92013-07-15 21:41:32 +08001246 }
Adrian Knotha8a729f2013-05-31 12:57:10 +02001247 return rate;
1248}
1249
Adrian Knoth5b266352013-07-05 11:28:10 +02001250/* check for external sample rate, returns the sample rate in Hz*/
Denys Vlasenko62cef822008-04-14 13:04:18 +02001251static int hdspm_external_sample_rate(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001252{
Sudip Mukherjeedf57de12014-10-29 20:09:45 +05301253 unsigned int status, status2;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001254 int syncref, rate = 0, rate_bits;
Takashi Iwai763f3562005-06-03 11:25:34 +02001255
Adrian Knoth0dca1792011-01-26 19:32:14 +01001256 switch (hdspm->io_type) {
1257 case AES32:
1258 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1259 status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001260
1261 syncref = hdspm_autosync_ref(hdspm);
Adrian Knothdbae4a02013-07-05 11:28:14 +02001262 switch (syncref) {
1263 case HDSPM_AES32_AUTOSYNC_FROM_WORD:
1264 /* Check WC sync and get sample rate */
1265 if (hdspm_wc_sync_check(hdspm))
1266 return HDSPM_bit2freq(hdspm_get_wc_sample_rate(hdspm));
1267 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001268
Adrian Knothdbae4a02013-07-05 11:28:14 +02001269 case HDSPM_AES32_AUTOSYNC_FROM_AES1:
1270 case HDSPM_AES32_AUTOSYNC_FROM_AES2:
1271 case HDSPM_AES32_AUTOSYNC_FROM_AES3:
1272 case HDSPM_AES32_AUTOSYNC_FROM_AES4:
1273 case HDSPM_AES32_AUTOSYNC_FROM_AES5:
1274 case HDSPM_AES32_AUTOSYNC_FROM_AES6:
1275 case HDSPM_AES32_AUTOSYNC_FROM_AES7:
1276 case HDSPM_AES32_AUTOSYNC_FROM_AES8:
1277 /* Check AES sync and get sample rate */
1278 if (hdspm_aes_sync_check(hdspm, syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1))
1279 return HDSPM_bit2freq(hdspm_get_aes_sample_rate(hdspm,
1280 syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1));
1281 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001282
Adrian Knothdbae4a02013-07-05 11:28:14 +02001283
1284 case HDSPM_AES32_AUTOSYNC_FROM_TCO:
1285 /* Check TCO sync and get sample rate */
1286 if (hdspm_tco_sync_check(hdspm))
1287 return HDSPM_bit2freq(hdspm_get_tco_sample_rate(hdspm));
1288 break;
1289 default:
1290 return 0;
1291 } /* end switch(syncref) */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001292 break;
1293
1294 case MADIface:
1295 status = hdspm_read(hdspm, HDSPM_statusRegister);
1296
1297 if (!(status & HDSPM_madiLock)) {
1298 rate = 0; /* no lock */
1299 } else {
1300 switch (status & (HDSPM_status1_freqMask)) {
1301 case HDSPM_status1_F_0*1:
1302 rate = 32000; break;
1303 case HDSPM_status1_F_0*2:
1304 rate = 44100; break;
1305 case HDSPM_status1_F_0*3:
1306 rate = 48000; break;
1307 case HDSPM_status1_F_0*4:
1308 rate = 64000; break;
1309 case HDSPM_status1_F_0*5:
1310 rate = 88200; break;
1311 case HDSPM_status1_F_0*6:
1312 rate = 96000; break;
1313 case HDSPM_status1_F_0*7:
1314 rate = 128000; break;
1315 case HDSPM_status1_F_0*8:
1316 rate = 176400; break;
1317 case HDSPM_status1_F_0*9:
1318 rate = 192000; break;
1319 default:
1320 rate = 0; break;
1321 }
1322 }
1323
1324 break;
1325
1326 case MADI:
1327 case AIO:
1328 case RayDAT:
1329 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1330 status = hdspm_read(hdspm, HDSPM_statusRegister);
1331 rate = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02001332
Remy Bruno3cee5a62006-10-16 12:46:32 +02001333 /* if wordclock has synced freq and wordclock is valid */
1334 if ((status2 & HDSPM_wcLock) != 0 &&
Adrian Knothfedf1532011-06-12 17:26:18 +02001335 (status2 & HDSPM_SelSyncRef0) == 0) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02001336
1337 rate_bits = status2 & HDSPM_wcFreqMask;
1338
Adrian Knoth0dca1792011-01-26 19:32:14 +01001339
Remy Bruno3cee5a62006-10-16 12:46:32 +02001340 switch (rate_bits) {
1341 case HDSPM_wcFreq32:
1342 rate = 32000;
1343 break;
1344 case HDSPM_wcFreq44_1:
1345 rate = 44100;
1346 break;
1347 case HDSPM_wcFreq48:
1348 rate = 48000;
1349 break;
1350 case HDSPM_wcFreq64:
1351 rate = 64000;
1352 break;
1353 case HDSPM_wcFreq88_2:
1354 rate = 88200;
1355 break;
1356 case HDSPM_wcFreq96:
1357 rate = 96000;
1358 break;
Adrian Knotha8cd7142013-05-31 12:57:09 +02001359 case HDSPM_wcFreq128:
1360 rate = 128000;
1361 break;
1362 case HDSPM_wcFreq176_4:
1363 rate = 176400;
1364 break;
1365 case HDSPM_wcFreq192:
1366 rate = 192000;
1367 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001368 default:
1369 rate = 0;
1370 break;
1371 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001372 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001373
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001374 /* if rate detected and Syncref is Word than have it,
1375 * word has priority to MADI
1376 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001377 if (rate != 0 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001378 (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
Adrian Knoth7b559392013-05-31 12:57:11 +02001379 return hdspm_rate_multiplier(hdspm, rate);
Remy Bruno3cee5a62006-10-16 12:46:32 +02001380
Adrian Knoth0dca1792011-01-26 19:32:14 +01001381 /* maybe a madi input (which is taken if sel sync is madi) */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001382 if (status & HDSPM_madiLock) {
1383 rate_bits = status & HDSPM_madiFreqMask;
1384
1385 switch (rate_bits) {
1386 case HDSPM_madiFreq32:
1387 rate = 32000;
1388 break;
1389 case HDSPM_madiFreq44_1:
1390 rate = 44100;
1391 break;
1392 case HDSPM_madiFreq48:
1393 rate = 48000;
1394 break;
1395 case HDSPM_madiFreq64:
1396 rate = 64000;
1397 break;
1398 case HDSPM_madiFreq88_2:
1399 rate = 88200;
1400 break;
1401 case HDSPM_madiFreq96:
1402 rate = 96000;
1403 break;
1404 case HDSPM_madiFreq128:
1405 rate = 128000;
1406 break;
1407 case HDSPM_madiFreq176_4:
1408 rate = 176400;
1409 break;
1410 case HDSPM_madiFreq192:
1411 rate = 192000;
1412 break;
1413 default:
1414 rate = 0;
1415 break;
1416 }
Adrian Knothd12c51d2011-07-29 03:11:03 +02001417
Adrian Knothfcdc4ba2013-03-10 00:37:22 +01001418 } /* endif HDSPM_madiLock */
1419
1420 /* check sample rate from TCO or SYNC_IN */
1421 {
1422 bool is_valid_input = 0;
1423 bool has_sync = 0;
1424
1425 syncref = hdspm_autosync_ref(hdspm);
1426 if (HDSPM_AUTOSYNC_FROM_TCO == syncref) {
1427 is_valid_input = 1;
1428 has_sync = (HDSPM_SYNC_CHECK_SYNC ==
1429 hdspm_tco_sync_check(hdspm));
1430 } else if (HDSPM_AUTOSYNC_FROM_SYNC_IN == syncref) {
1431 is_valid_input = 1;
1432 has_sync = (HDSPM_SYNC_CHECK_SYNC ==
1433 hdspm_sync_in_sync_check(hdspm));
Adrian Knothd12c51d2011-07-29 03:11:03 +02001434 }
Adrian Knothfcdc4ba2013-03-10 00:37:22 +01001435
1436 if (is_valid_input && has_sync) {
1437 rate = hdspm_round_frequency(
1438 hdspm_get_pll_freq(hdspm));
1439 }
1440 }
1441
Adrian Knotha8a729f2013-05-31 12:57:10 +02001442 rate = hdspm_rate_multiplier(hdspm, rate);
1443
Adrian Knoth0dca1792011-01-26 19:32:14 +01001444 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001445 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001446
1447 return rate;
Takashi Iwai763f3562005-06-03 11:25:34 +02001448}
1449
Adrian Knoth7cb155f2011-08-15 00:22:53 +02001450/* return latency in samples per period */
1451static int hdspm_get_latency(struct hdspm *hdspm)
1452{
1453 int n;
1454
1455 n = hdspm_decode_latency(hdspm->control_register);
1456
1457 /* Special case for new RME cards with 32 samples period size.
1458 * The three latency bits in the control register
1459 * (HDSP_LatencyMask) encode latency values of 64 samples as
1460 * 0, 128 samples as 1 ... 4096 samples as 6. For old cards, 7
1461 * denotes 8192 samples, but on new cards like RayDAT or AIO,
1462 * it corresponds to 32 samples.
1463 */
1464 if ((7 == n) && (RayDAT == hdspm->io_type || AIO == hdspm->io_type))
1465 n = -1;
1466
1467 return 1 << (n + 6);
1468}
1469
Takashi Iwai763f3562005-06-03 11:25:34 +02001470/* Latency function */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001471static inline void hdspm_compute_period_size(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001472{
Adrian Knoth7cb155f2011-08-15 00:22:53 +02001473 hdspm->period_bytes = 4 * hdspm_get_latency(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001474}
1475
Adrian Knoth0dca1792011-01-26 19:32:14 +01001476
1477static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001478{
1479 int position;
1480
1481 position = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth483cee72011-02-23 11:43:09 +01001482
1483 switch (hdspm->io_type) {
1484 case RayDAT:
1485 case AIO:
1486 position &= HDSPM_BufferPositionMask;
1487 position /= 4; /* Bytes per sample */
1488 break;
1489 default:
1490 position = (position & HDSPM_BufferID) ?
1491 (hdspm->period_bytes / 4) : 0;
1492 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001493
1494 return position;
1495}
1496
1497
Takashi Iwai98274f02005-11-17 14:52:34 +01001498static inline void hdspm_start_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001499{
1500 s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
1501 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1502}
1503
Takashi Iwai98274f02005-11-17 14:52:34 +01001504static inline void hdspm_stop_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001505{
1506 s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
1507 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1508}
1509
1510/* should I silence all or only opened ones ? doit all for first even is 4MB*/
Denys Vlasenko62cef822008-04-14 13:04:18 +02001511static void hdspm_silence_playback(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001512{
1513 int i;
1514 int n = hdspm->period_bytes;
1515 void *buf = hdspm->playback_buffer;
1516
Markus Elfringda2ea372017-08-12 17:07:09 +02001517 if (!buf)
Remy Bruno3cee5a62006-10-16 12:46:32 +02001518 return;
Takashi Iwai763f3562005-06-03 11:25:34 +02001519
1520 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
1521 memset(buf, 0, n);
1522 buf += HDSPM_CHANNEL_BUFFER_BYTES;
1523 }
1524}
1525
Adrian Knoth0dca1792011-01-26 19:32:14 +01001526static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames)
Takashi Iwai763f3562005-06-03 11:25:34 +02001527{
1528 int n;
1529
1530 spin_lock_irq(&s->lock);
1531
Adrian Knoth2e610272011-08-15 00:22:54 +02001532 if (32 == frames) {
1533 /* Special case for new RME cards like RayDAT/AIO which
1534 * support period sizes of 32 samples. Since latency is
1535 * encoded in the three bits of HDSP_LatencyMask, we can only
1536 * have values from 0 .. 7. While 0 still means 64 samples and
1537 * 6 represents 4096 samples on all cards, 7 represents 8192
1538 * on older cards and 32 samples on new cards.
1539 *
1540 * In other words, period size in samples is calculated by
1541 * 2^(n+6) with n ranging from 0 .. 7.
1542 */
1543 n = 7;
1544 } else {
1545 frames >>= 7;
1546 n = 0;
1547 while (frames) {
1548 n++;
1549 frames >>= 1;
1550 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001551 }
Adrian Knoth2e610272011-08-15 00:22:54 +02001552
Takashi Iwai763f3562005-06-03 11:25:34 +02001553 s->control_register &= ~HDSPM_LatencyMask;
1554 s->control_register |= hdspm_encode_latency(n);
1555
1556 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1557
1558 hdspm_compute_period_size(s);
1559
1560 spin_unlock_irq(&s->lock);
1561
1562 return 0;
1563}
1564
Adrian Knoth0dca1792011-01-26 19:32:14 +01001565static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period)
1566{
1567 u64 freq_const;
1568
1569 if (period == 0)
1570 return 0;
1571
1572 switch (hdspm->io_type) {
1573 case MADI:
1574 case AES32:
1575 freq_const = 110069313433624ULL;
1576 break;
1577 case RayDAT:
1578 case AIO:
1579 freq_const = 104857600000000ULL;
1580 break;
1581 case MADIface:
1582 freq_const = 131072000000000ULL;
Takashi Iwai3d56c8e6b2011-08-05 12:30:12 +02001583 break;
1584 default:
1585 snd_BUG();
1586 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001587 }
1588
1589 return div_u64(freq_const, period);
1590}
1591
1592
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001593static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
1594{
1595 u64 n;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001596
Takashi Iwaic1099c32016-02-29 14:32:42 +01001597 if (snd_BUG_ON(rate <= 0))
1598 return;
1599
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001600 if (rate >= 112000)
1601 rate /= 4;
1602 else if (rate >= 56000)
1603 rate /= 2;
1604
Adrian Knoth0dca1792011-01-26 19:32:14 +01001605 switch (hdspm->io_type) {
1606 case MADIface:
Takashi Iwai3d56c8e6b2011-08-05 12:30:12 +02001607 n = 131072000000000ULL; /* 125 MHz */
1608 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001609 case MADI:
1610 case AES32:
Takashi Iwai3d56c8e6b2011-08-05 12:30:12 +02001611 n = 110069313433624ULL; /* 105 MHz */
1612 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001613 case RayDAT:
1614 case AIO:
Takashi Iwai3d56c8e6b2011-08-05 12:30:12 +02001615 n = 104857600000000ULL; /* 100 MHz */
1616 break;
1617 default:
1618 snd_BUG();
1619 return;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001620 }
1621
Takashi Iwai3f7440a2009-06-05 17:40:04 +02001622 n = div_u64(n, rate);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001623 /* n should be less than 2^32 for being written to FREQ register */
Takashi Iwaida3cec32008-08-08 17:12:14 +02001624 snd_BUG_ON(n >> 32);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001625 hdspm_write(hdspm, HDSPM_freqReg, (u32)n);
1626}
Takashi Iwai763f3562005-06-03 11:25:34 +02001627
1628/* dummy set rate lets see what happens */
Takashi Iwai98274f02005-11-17 14:52:34 +01001629static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
Takashi Iwai763f3562005-06-03 11:25:34 +02001630{
Takashi Iwai763f3562005-06-03 11:25:34 +02001631 int current_rate;
1632 int rate_bits;
1633 int not_set = 0;
Remy Bruno65345992007-08-31 12:21:08 +02001634 int current_speed, target_speed;
Takashi Iwai763f3562005-06-03 11:25:34 +02001635
1636 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
1637 it (e.g. during module initialization).
1638 */
1639
1640 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
1641
Adrian Knoth0dca1792011-01-26 19:32:14 +01001642 /* SLAVE --- */
Takashi Iwai763f3562005-06-03 11:25:34 +02001643 if (called_internally) {
1644
Adrian Knoth0dca1792011-01-26 19:32:14 +01001645 /* request from ctl or card initialization
1646 just make a warning an remember setting
1647 for future master mode switching */
1648
Takashi Iwaie3a471d62014-02-26 12:05:40 +01001649 dev_warn(hdspm->card->dev,
1650 "Warning: device is not running as a clock master.\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001651 not_set = 1;
1652 } else {
1653
1654 /* hw_param request while in AutoSync mode */
1655 int external_freq =
1656 hdspm_external_sample_rate(hdspm);
1657
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001658 if (hdspm_autosync_ref(hdspm) ==
1659 HDSPM_AUTOSYNC_FROM_NONE) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001660
Takashi Iwaie3a471d62014-02-26 12:05:40 +01001661 dev_warn(hdspm->card->dev,
Colin Ian King07cb3272016-08-22 12:50:02 +01001662 "Detected no External Sync\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001663 not_set = 1;
1664
1665 } else if (rate != external_freq) {
1666
Takashi Iwaie3a471d62014-02-26 12:05:40 +01001667 dev_warn(hdspm->card->dev,
1668 "Warning: No AutoSync source for requested rate\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001669 not_set = 1;
1670 }
1671 }
1672 }
1673
1674 current_rate = hdspm->system_sample_rate;
1675
1676 /* Changing between Singe, Double and Quad speed is not
1677 allowed if any substreams are open. This is because such a change
1678 causes a shift in the location of the DMA buffers and a reduction
1679 in the number of available buffers.
1680
1681 Note that a similar but essentially insoluble problem exists for
1682 externally-driven rate changes. All we can do is to flag rate
Adrian Knoth0dca1792011-01-26 19:32:14 +01001683 changes in the read/write routines.
Takashi Iwai763f3562005-06-03 11:25:34 +02001684 */
1685
Remy Bruno65345992007-08-31 12:21:08 +02001686 if (current_rate <= 48000)
1687 current_speed = HDSPM_SPEED_SINGLE;
1688 else if (current_rate <= 96000)
1689 current_speed = HDSPM_SPEED_DOUBLE;
1690 else
1691 current_speed = HDSPM_SPEED_QUAD;
1692
1693 if (rate <= 48000)
1694 target_speed = HDSPM_SPEED_SINGLE;
1695 else if (rate <= 96000)
1696 target_speed = HDSPM_SPEED_DOUBLE;
1697 else
1698 target_speed = HDSPM_SPEED_QUAD;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001699
Takashi Iwai763f3562005-06-03 11:25:34 +02001700 switch (rate) {
1701 case 32000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001702 rate_bits = HDSPM_Frequency32KHz;
1703 break;
1704 case 44100:
Takashi Iwai763f3562005-06-03 11:25:34 +02001705 rate_bits = HDSPM_Frequency44_1KHz;
1706 break;
1707 case 48000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001708 rate_bits = HDSPM_Frequency48KHz;
1709 break;
1710 case 64000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001711 rate_bits = HDSPM_Frequency64KHz;
1712 break;
1713 case 88200:
Takashi Iwai763f3562005-06-03 11:25:34 +02001714 rate_bits = HDSPM_Frequency88_2KHz;
1715 break;
1716 case 96000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001717 rate_bits = HDSPM_Frequency96KHz;
1718 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001719 case 128000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001720 rate_bits = HDSPM_Frequency128KHz;
1721 break;
1722 case 176400:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001723 rate_bits = HDSPM_Frequency176_4KHz;
1724 break;
1725 case 192000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001726 rate_bits = HDSPM_Frequency192KHz;
1727 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001728 default:
1729 return -EINVAL;
1730 }
1731
Remy Bruno65345992007-08-31 12:21:08 +02001732 if (current_speed != target_speed
Takashi Iwai763f3562005-06-03 11:25:34 +02001733 && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01001734 dev_err(hdspm->card->dev,
1735 "cannot change from %s speed to %s speed mode (capture PID = %d, playback PID = %d)\n",
1736 hdspm_speed_names[current_speed],
1737 hdspm_speed_names[target_speed],
1738 hdspm->capture_pid, hdspm->playback_pid);
Takashi Iwai763f3562005-06-03 11:25:34 +02001739 return -EBUSY;
1740 }
1741
1742 hdspm->control_register &= ~HDSPM_FrequencyMask;
1743 hdspm->control_register |= rate_bits;
1744 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1745
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001746 /* For AES32, need to set DDS value in FREQ register
1747 For MADI, also apparently */
1748 hdspm_set_dds_value(hdspm, rate);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001749
1750 if (AES32 == hdspm->io_type && rate != current_rate)
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001751 hdspm_write(hdspm, HDSPM_eeprom_wr, 0);
Takashi Iwai763f3562005-06-03 11:25:34 +02001752
1753 hdspm->system_sample_rate = rate;
1754
Adrian Knoth0dca1792011-01-26 19:32:14 +01001755 if (rate <= 48000) {
1756 hdspm->channel_map_in = hdspm->channel_map_in_ss;
1757 hdspm->channel_map_out = hdspm->channel_map_out_ss;
1758 hdspm->max_channels_in = hdspm->ss_in_channels;
1759 hdspm->max_channels_out = hdspm->ss_out_channels;
1760 hdspm->port_names_in = hdspm->port_names_in_ss;
1761 hdspm->port_names_out = hdspm->port_names_out_ss;
1762 } else if (rate <= 96000) {
1763 hdspm->channel_map_in = hdspm->channel_map_in_ds;
1764 hdspm->channel_map_out = hdspm->channel_map_out_ds;
1765 hdspm->max_channels_in = hdspm->ds_in_channels;
1766 hdspm->max_channels_out = hdspm->ds_out_channels;
1767 hdspm->port_names_in = hdspm->port_names_in_ds;
1768 hdspm->port_names_out = hdspm->port_names_out_ds;
1769 } else {
1770 hdspm->channel_map_in = hdspm->channel_map_in_qs;
1771 hdspm->channel_map_out = hdspm->channel_map_out_qs;
1772 hdspm->max_channels_in = hdspm->qs_in_channels;
1773 hdspm->max_channels_out = hdspm->qs_out_channels;
1774 hdspm->port_names_in = hdspm->port_names_in_qs;
1775 hdspm->port_names_out = hdspm->port_names_out_qs;
1776 }
1777
Takashi Iwai763f3562005-06-03 11:25:34 +02001778 if (not_set != 0)
1779 return -1;
1780
1781 return 0;
1782}
1783
1784/* mainly for init to 0 on load */
Takashi Iwai98274f02005-11-17 14:52:34 +01001785static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
Takashi Iwai763f3562005-06-03 11:25:34 +02001786{
1787 int i, j;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001788 unsigned int gain;
1789
1790 if (sgain > UNITY_GAIN)
1791 gain = UNITY_GAIN;
1792 else if (sgain < 0)
1793 gain = 0;
1794 else
1795 gain = sgain;
Takashi Iwai763f3562005-06-03 11:25:34 +02001796
1797 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
1798 for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
1799 hdspm_write_in_gain(hdspm, i, j, gain);
1800 hdspm_write_pb_gain(hdspm, i, j, gain);
1801 }
1802}
1803
1804/*----------------------------------------------------------------------------
1805 MIDI
1806 ----------------------------------------------------------------------------*/
1807
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001808static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm,
1809 int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001810{
1811 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001812 return hdspm_read(hdspm, hdspm->midi[id].dataIn);
Takashi Iwai763f3562005-06-03 11:25:34 +02001813}
1814
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001815static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
1816 int val)
Takashi Iwai763f3562005-06-03 11:25:34 +02001817{
1818 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001819 return hdspm_write(hdspm, hdspm->midi[id].dataOut, val);
Takashi Iwai763f3562005-06-03 11:25:34 +02001820}
1821
Takashi Iwai98274f02005-11-17 14:52:34 +01001822static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001823{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001824 return hdspm_read(hdspm, hdspm->midi[id].statusIn) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001825}
1826
Takashi Iwai98274f02005-11-17 14:52:34 +01001827static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001828{
1829 int fifo_bytes_used;
1830
Adrian Knoth0dca1792011-01-26 19:32:14 +01001831 fifo_bytes_used = hdspm_read(hdspm, hdspm->midi[id].statusOut) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001832
1833 if (fifo_bytes_used < 128)
1834 return 128 - fifo_bytes_used;
1835 else
1836 return 0;
1837}
1838
Denys Vlasenko62cef822008-04-14 13:04:18 +02001839static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001840{
1841 while (snd_hdspm_midi_input_available (hdspm, id))
1842 snd_hdspm_midi_read_byte (hdspm, id);
1843}
1844
Takashi Iwai98274f02005-11-17 14:52:34 +01001845static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001846{
1847 unsigned long flags;
1848 int n_pending;
1849 int to_write;
1850 int i;
1851 unsigned char buf[128];
1852
1853 /* Output is not interrupt driven */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001854
Takashi Iwai763f3562005-06-03 11:25:34 +02001855 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001856 if (hmidi->output &&
1857 !snd_rawmidi_transmit_empty (hmidi->output)) {
1858 n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm,
1859 hmidi->id);
1860 if (n_pending > 0) {
1861 if (n_pending > (int)sizeof (buf))
1862 n_pending = sizeof (buf);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001863
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001864 to_write = snd_rawmidi_transmit (hmidi->output, buf,
1865 n_pending);
1866 if (to_write > 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001867 for (i = 0; i < to_write; ++i)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001868 snd_hdspm_midi_write_byte (hmidi->hdspm,
1869 hmidi->id,
1870 buf[i]);
Takashi Iwai763f3562005-06-03 11:25:34 +02001871 }
1872 }
1873 }
1874 spin_unlock_irqrestore (&hmidi->lock, flags);
1875 return 0;
1876}
1877
Takashi Iwai98274f02005-11-17 14:52:34 +01001878static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001879{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001880 unsigned char buf[128]; /* this buffer is designed to match the MIDI
1881 * input FIFO size
1882 */
Takashi Iwai763f3562005-06-03 11:25:34 +02001883 unsigned long flags;
1884 int n_pending;
1885 int i;
1886
1887 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001888 n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id);
1889 if (n_pending > 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001890 if (hmidi->input) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001891 if (n_pending > (int)sizeof (buf))
Takashi Iwai763f3562005-06-03 11:25:34 +02001892 n_pending = sizeof (buf);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001893 for (i = 0; i < n_pending; ++i)
1894 buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm,
1895 hmidi->id);
1896 if (n_pending)
1897 snd_rawmidi_receive (hmidi->input, buf,
1898 n_pending);
Takashi Iwai763f3562005-06-03 11:25:34 +02001899 } else {
1900 /* flush the MIDI input FIFO */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001901 while (n_pending--)
1902 snd_hdspm_midi_read_byte (hmidi->hdspm,
1903 hmidi->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02001904 }
1905 }
1906 hmidi->pending = 0;
Adrian Knothc0da0012011-06-12 17:26:17 +02001907 spin_unlock_irqrestore(&hmidi->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001908
Adrian Knothc0da0012011-06-12 17:26:17 +02001909 spin_lock_irqsave(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001910 hmidi->hdspm->control_register |= hmidi->ie;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001911 hdspm_write(hmidi->hdspm, HDSPM_controlRegister,
1912 hmidi->hdspm->control_register);
Adrian Knothc0da0012011-06-12 17:26:17 +02001913 spin_unlock_irqrestore(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001914
Takashi Iwai763f3562005-06-03 11:25:34 +02001915 return snd_hdspm_midi_output_write (hmidi);
1916}
1917
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001918static void
1919snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001920{
Takashi Iwai98274f02005-11-17 14:52:34 +01001921 struct hdspm *hdspm;
1922 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001923 unsigned long flags;
Takashi Iwai763f3562005-06-03 11:25:34 +02001924
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001925 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001926 hdspm = hmidi->hdspm;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001927
Takashi Iwai763f3562005-06-03 11:25:34 +02001928 spin_lock_irqsave (&hdspm->lock, flags);
1929 if (up) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001930 if (!(hdspm->control_register & hmidi->ie)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001931 snd_hdspm_flush_midi_input (hdspm, hmidi->id);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001932 hdspm->control_register |= hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001933 }
1934 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001935 hdspm->control_register &= ~hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001936 }
1937
1938 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1939 spin_unlock_irqrestore (&hdspm->lock, flags);
1940}
1941
Kees Cook7211ec62017-10-25 08:09:27 -07001942static void snd_hdspm_midi_output_timer(struct timer_list *t)
Takashi Iwai763f3562005-06-03 11:25:34 +02001943{
Kees Cook7211ec62017-10-25 08:09:27 -07001944 struct hdspm_midi *hmidi = from_timer(hmidi, t, timer);
Takashi Iwai763f3562005-06-03 11:25:34 +02001945 unsigned long flags;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001946
Takashi Iwai763f3562005-06-03 11:25:34 +02001947 snd_hdspm_midi_output_write(hmidi);
1948 spin_lock_irqsave (&hmidi->lock, flags);
1949
1950 /* this does not bump hmidi->istimer, because the
1951 kernel automatically removed the timer when it
1952 expired, and we are now adding it back, thus
Adrian Knoth0dca1792011-01-26 19:32:14 +01001953 leaving istimer wherever it was set before.
Takashi Iwai763f3562005-06-03 11:25:34 +02001954 */
1955
Takashi Iwai04018e12015-01-19 11:34:45 +01001956 if (hmidi->istimer)
1957 mod_timer(&hmidi->timer, 1 + jiffies);
Takashi Iwai763f3562005-06-03 11:25:34 +02001958
1959 spin_unlock_irqrestore (&hmidi->lock, flags);
1960}
1961
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001962static void
1963snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001964{
Takashi Iwai98274f02005-11-17 14:52:34 +01001965 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001966 unsigned long flags;
1967
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001968 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001969 spin_lock_irqsave (&hmidi->lock, flags);
1970 if (up) {
1971 if (!hmidi->istimer) {
Kees Cook7211ec62017-10-25 08:09:27 -07001972 timer_setup(&hmidi->timer,
1973 snd_hdspm_midi_output_timer, 0);
Takashi Iwai04018e12015-01-19 11:34:45 +01001974 mod_timer(&hmidi->timer, 1 + jiffies);
Takashi Iwai763f3562005-06-03 11:25:34 +02001975 hmidi->istimer++;
1976 }
1977 } else {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001978 if (hmidi->istimer && --hmidi->istimer <= 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02001979 del_timer (&hmidi->timer);
Takashi Iwai763f3562005-06-03 11:25:34 +02001980 }
1981 spin_unlock_irqrestore (&hmidi->lock, flags);
1982 if (up)
1983 snd_hdspm_midi_output_write(hmidi);
1984}
1985
Takashi Iwai98274f02005-11-17 14:52:34 +01001986static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001987{
Takashi Iwai98274f02005-11-17 14:52:34 +01001988 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001989
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001990 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001991 spin_lock_irq (&hmidi->lock);
1992 snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
1993 hmidi->input = substream;
1994 spin_unlock_irq (&hmidi->lock);
1995
1996 return 0;
1997}
1998
Takashi Iwai98274f02005-11-17 14:52:34 +01001999static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02002000{
Takashi Iwai98274f02005-11-17 14:52:34 +01002001 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02002002
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002003 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02002004 spin_lock_irq (&hmidi->lock);
2005 hmidi->output = substream;
2006 spin_unlock_irq (&hmidi->lock);
2007
2008 return 0;
2009}
2010
Takashi Iwai98274f02005-11-17 14:52:34 +01002011static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02002012{
Takashi Iwai98274f02005-11-17 14:52:34 +01002013 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02002014
2015 snd_hdspm_midi_input_trigger (substream, 0);
2016
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002017 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02002018 spin_lock_irq (&hmidi->lock);
2019 hmidi->input = NULL;
2020 spin_unlock_irq (&hmidi->lock);
2021
2022 return 0;
2023}
2024
Takashi Iwai98274f02005-11-17 14:52:34 +01002025static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02002026{
Takashi Iwai98274f02005-11-17 14:52:34 +01002027 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02002028
2029 snd_hdspm_midi_output_trigger (substream, 0);
2030
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002031 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02002032 spin_lock_irq (&hmidi->lock);
2033 hmidi->output = NULL;
2034 spin_unlock_irq (&hmidi->lock);
2035
2036 return 0;
2037}
2038
Takashi Iwai485885b2017-01-05 17:29:31 +01002039static const struct snd_rawmidi_ops snd_hdspm_midi_output =
Takashi Iwai763f3562005-06-03 11:25:34 +02002040{
2041 .open = snd_hdspm_midi_output_open,
2042 .close = snd_hdspm_midi_output_close,
2043 .trigger = snd_hdspm_midi_output_trigger,
2044};
2045
Takashi Iwai485885b2017-01-05 17:29:31 +01002046static const struct snd_rawmidi_ops snd_hdspm_midi_input =
Takashi Iwai763f3562005-06-03 11:25:34 +02002047{
2048 .open = snd_hdspm_midi_input_open,
2049 .close = snd_hdspm_midi_input_close,
2050 .trigger = snd_hdspm_midi_input_trigger,
2051};
2052
Bill Pembertone23e7a12012-12-06 12:35:10 -05002053static int snd_hdspm_create_midi(struct snd_card *card,
2054 struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02002055{
2056 int err;
Arnd Bergmann7ad210a2017-07-18 13:48:09 +02002057 char buf[64];
Takashi Iwai763f3562005-06-03 11:25:34 +02002058
2059 hdspm->midi[id].id = id;
Takashi Iwai763f3562005-06-03 11:25:34 +02002060 hdspm->midi[id].hdspm = hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +02002061 spin_lock_init (&hdspm->midi[id].lock);
2062
Adrian Knoth0dca1792011-01-26 19:32:14 +01002063 if (0 == id) {
2064 if (MADIface == hdspm->io_type) {
2065 /* MIDI-over-MADI on HDSPe MADIface */
2066 hdspm->midi[0].dataIn = HDSPM_midiDataIn2;
2067 hdspm->midi[0].statusIn = HDSPM_midiStatusIn2;
2068 hdspm->midi[0].dataOut = HDSPM_midiDataOut2;
2069 hdspm->midi[0].statusOut = HDSPM_midiStatusOut2;
2070 hdspm->midi[0].ie = HDSPM_Midi2InterruptEnable;
2071 hdspm->midi[0].irq = HDSPM_midi2IRQPending;
2072 } else {
2073 hdspm->midi[0].dataIn = HDSPM_midiDataIn0;
2074 hdspm->midi[0].statusIn = HDSPM_midiStatusIn0;
2075 hdspm->midi[0].dataOut = HDSPM_midiDataOut0;
2076 hdspm->midi[0].statusOut = HDSPM_midiStatusOut0;
2077 hdspm->midi[0].ie = HDSPM_Midi0InterruptEnable;
2078 hdspm->midi[0].irq = HDSPM_midi0IRQPending;
2079 }
2080 } else if (1 == id) {
2081 hdspm->midi[1].dataIn = HDSPM_midiDataIn1;
2082 hdspm->midi[1].statusIn = HDSPM_midiStatusIn1;
2083 hdspm->midi[1].dataOut = HDSPM_midiDataOut1;
2084 hdspm->midi[1].statusOut = HDSPM_midiStatusOut1;
2085 hdspm->midi[1].ie = HDSPM_Midi1InterruptEnable;
2086 hdspm->midi[1].irq = HDSPM_midi1IRQPending;
2087 } else if ((2 == id) && (MADI == hdspm->io_type)) {
2088 /* MIDI-over-MADI on HDSPe MADI */
2089 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
2090 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
2091 hdspm->midi[2].dataOut = HDSPM_midiDataOut2;
2092 hdspm->midi[2].statusOut = HDSPM_midiStatusOut2;
2093 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
2094 hdspm->midi[2].irq = HDSPM_midi2IRQPending;
2095 } else if (2 == id) {
2096 /* TCO MTC, read only */
2097 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
2098 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
2099 hdspm->midi[2].dataOut = -1;
2100 hdspm->midi[2].statusOut = -1;
2101 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
2102 hdspm->midi[2].irq = HDSPM_midi2IRQPendingAES;
2103 } else if (3 == id) {
2104 /* TCO MTC on HDSPe MADI */
2105 hdspm->midi[3].dataIn = HDSPM_midiDataIn3;
2106 hdspm->midi[3].statusIn = HDSPM_midiStatusIn3;
2107 hdspm->midi[3].dataOut = -1;
2108 hdspm->midi[3].statusOut = -1;
2109 hdspm->midi[3].ie = HDSPM_Midi3InterruptEnable;
2110 hdspm->midi[3].irq = HDSPM_midi3IRQPending;
2111 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002112
Adrian Knoth0dca1792011-01-26 19:32:14 +01002113 if ((id < 2) || ((2 == id) && ((MADI == hdspm->io_type) ||
2114 (MADIface == hdspm->io_type)))) {
2115 if ((id == 0) && (MADIface == hdspm->io_type)) {
Arnd Bergmann7ad210a2017-07-18 13:48:09 +02002116 snprintf(buf, sizeof(buf), "%s MIDIoverMADI",
2117 card->shortname);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002118 } else if ((id == 2) && (MADI == hdspm->io_type)) {
Arnd Bergmann7ad210a2017-07-18 13:48:09 +02002119 snprintf(buf, sizeof(buf), "%s MIDIoverMADI",
2120 card->shortname);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002121 } else {
Arnd Bergmann7ad210a2017-07-18 13:48:09 +02002122 snprintf(buf, sizeof(buf), "%s MIDI %d",
2123 card->shortname, id+1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002124 }
2125 err = snd_rawmidi_new(card, buf, id, 1, 1,
2126 &hdspm->midi[id].rmidi);
2127 if (err < 0)
2128 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02002129
Arnd Bergmann7ad210a2017-07-18 13:48:09 +02002130 snprintf(hdspm->midi[id].rmidi->name,
2131 sizeof(hdspm->midi[id].rmidi->name),
2132 "%s MIDI %d", card->id, id+1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002133 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
Takashi Iwai763f3562005-06-03 11:25:34 +02002134
Adrian Knoth0dca1792011-01-26 19:32:14 +01002135 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
2136 SNDRV_RAWMIDI_STREAM_OUTPUT,
2137 &snd_hdspm_midi_output);
2138 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
2139 SNDRV_RAWMIDI_STREAM_INPUT,
2140 &snd_hdspm_midi_input);
2141
2142 hdspm->midi[id].rmidi->info_flags |=
2143 SNDRV_RAWMIDI_INFO_OUTPUT |
2144 SNDRV_RAWMIDI_INFO_INPUT |
2145 SNDRV_RAWMIDI_INFO_DUPLEX;
2146 } else {
2147 /* TCO MTC, read only */
Arnd Bergmann7ad210a2017-07-18 13:48:09 +02002148 snprintf(buf, sizeof(buf), "%s MTC %d",
2149 card->shortname, id+1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002150 err = snd_rawmidi_new(card, buf, id, 1, 1,
2151 &hdspm->midi[id].rmidi);
2152 if (err < 0)
2153 return err;
2154
Arnd Bergmann7ad210a2017-07-18 13:48:09 +02002155 snprintf(hdspm->midi[id].rmidi->name,
2156 sizeof(hdspm->midi[id].rmidi->name),
2157 "%s MTC %d", card->id, id+1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002158 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
2159
2160 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
2161 SNDRV_RAWMIDI_STREAM_INPUT,
2162 &snd_hdspm_midi_input);
2163
2164 hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
2165 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002166
2167 return 0;
2168}
2169
2170
Takashi Iwaia2e527c2020-09-03 12:41:27 +02002171static void hdspm_midi_work(struct work_struct *work)
Takashi Iwai763f3562005-06-03 11:25:34 +02002172{
Takashi Iwaia2e527c2020-09-03 12:41:27 +02002173 struct hdspm *hdspm = container_of(work, struct hdspm, midi_work);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002174 int i = 0;
2175
2176 while (i < hdspm->midiPorts) {
2177 if (hdspm->midi[i].pending)
2178 snd_hdspm_midi_input_read(&hdspm->midi[i]);
2179
2180 i++;
2181 }
2182}
Takashi Iwai763f3562005-06-03 11:25:34 +02002183
2184
2185/*-----------------------------------------------------------------------------
2186 Status Interface
2187 ----------------------------------------------------------------------------*/
2188
2189/* get the system sample rate which is set */
2190
Adrian Knoth0dca1792011-01-26 19:32:14 +01002191
Adrian Knoth3f7bf912013-03-10 00:37:21 +01002192static inline int hdspm_get_pll_freq(struct hdspm *hdspm)
2193{
2194 unsigned int period, rate;
2195
2196 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
2197 rate = hdspm_calc_dds_value(hdspm, period);
2198
2199 return rate;
2200}
2201
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002202/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002203 * Calculate the real sample rate from the
2204 * current DDS value.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002205 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002206static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
2207{
Adrian Knoth3f7bf912013-03-10 00:37:21 +01002208 unsigned int rate;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002209
Adrian Knoth3f7bf912013-03-10 00:37:21 +01002210 rate = hdspm_get_pll_freq(hdspm);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002211
Adrian Knotha97bda72012-05-30 14:23:18 +02002212 if (rate > 207000) {
Adrian Knoth21a164d2012-10-19 17:42:23 +02002213 /* Unreasonable high sample rate as seen on PCI MADI cards. */
2214 if (0 == hdspm_system_clock_mode(hdspm)) {
2215 /* master mode, return internal sample rate */
2216 rate = hdspm->system_sample_rate;
2217 } else {
2218 /* slave mode, return external sample rate */
2219 rate = hdspm_external_sample_rate(hdspm);
Takashi Iwaic1099c32016-02-29 14:32:42 +01002220 if (!rate)
2221 rate = hdspm->system_sample_rate;
Adrian Knoth21a164d2012-10-19 17:42:23 +02002222 }
Adrian Knotha97bda72012-05-30 14:23:18 +02002223 }
2224
Adrian Knoth0dca1792011-01-26 19:32:14 +01002225 return rate;
2226}
2227
2228
Takashi Iwai763f3562005-06-03 11:25:34 +02002229#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02002230{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2231 .name = xname, \
2232 .index = xindex, \
2233 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2234 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2235 .info = snd_hdspm_info_system_sample_rate, \
2236 .put = snd_hdspm_put_system_sample_rate, \
2237 .get = snd_hdspm_get_system_sample_rate \
Takashi Iwai763f3562005-06-03 11:25:34 +02002238}
2239
Takashi Iwai98274f02005-11-17 14:52:34 +01002240static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
2241 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002242{
2243 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2244 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002245 uinfo->value.integer.min = 27000;
2246 uinfo->value.integer.max = 207000;
2247 uinfo->value.integer.step = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002248 return 0;
2249}
2250
Adrian Knoth0dca1792011-01-26 19:32:14 +01002251
Takashi Iwai98274f02005-11-17 14:52:34 +01002252static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
2253 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002254 ucontrol)
2255{
Takashi Iwai98274f02005-11-17 14:52:34 +01002256 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002257
Adrian Knoth0dca1792011-01-26 19:32:14 +01002258 ucontrol->value.integer.value[0] = hdspm_get_system_sample_rate(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002259 return 0;
2260}
2261
Adrian Knoth41285a92012-10-19 17:42:22 +02002262static int snd_hdspm_put_system_sample_rate(struct snd_kcontrol *kcontrol,
2263 struct snd_ctl_elem_value *
2264 ucontrol)
2265{
2266 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwaic1099c32016-02-29 14:32:42 +01002267 int rate = ucontrol->value.integer.value[0];
Adrian Knoth41285a92012-10-19 17:42:22 +02002268
Takashi Iwaic1099c32016-02-29 14:32:42 +01002269 if (rate < 27000 || rate > 207000)
2270 return -EINVAL;
Takashi Iwai537e4812016-02-29 14:25:16 +01002271 hdspm_set_dds_value(hdspm, ucontrol->value.integer.value[0]);
Adrian Knoth41285a92012-10-19 17:42:22 +02002272 return 0;
2273}
2274
Adrian Knoth0dca1792011-01-26 19:32:14 +01002275
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002276/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002277 * Returns the WordClock sample rate class for the given card.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002278 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002279static int hdspm_get_wc_sample_rate(struct hdspm *hdspm)
2280{
2281 int status;
2282
2283 switch (hdspm->io_type) {
2284 case RayDAT:
2285 case AIO:
2286 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2287 return (status >> 16) & 0xF;
Adrian Knotha57fea82013-07-05 11:28:11 +02002288 case AES32:
2289 status = hdspm_read(hdspm, HDSPM_statusRegister);
2290 return (status >> HDSPM_AES32_wcFreq_bit) & 0xF;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002291 default:
2292 break;
2293 }
2294
2295
2296 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002297}
2298
Adrian Knoth0dca1792011-01-26 19:32:14 +01002299
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002300/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002301 * Returns the TCO sample rate class for the given card.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002302 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002303static int hdspm_get_tco_sample_rate(struct hdspm *hdspm)
2304{
2305 int status;
2306
2307 if (hdspm->tco) {
2308 switch (hdspm->io_type) {
2309 case RayDAT:
2310 case AIO:
2311 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2312 return (status >> 20) & 0xF;
Adrian Knoth051c44f2013-07-05 11:28:12 +02002313 case AES32:
2314 status = hdspm_read(hdspm, HDSPM_statusRegister);
2315 return (status >> 1) & 0xF;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002316 default:
2317 break;
2318 }
2319 }
2320
2321 return 0;
2322}
2323
2324
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002325/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002326 * Returns the SYNC_IN sample rate class for the given card.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002327 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002328static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm)
2329{
2330 int status;
2331
2332 if (hdspm->tco) {
2333 switch (hdspm->io_type) {
2334 case RayDAT:
2335 case AIO:
2336 status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2337 return (status >> 12) & 0xF;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002338 default:
2339 break;
2340 }
2341 }
2342
2343 return 0;
2344}
2345
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002346/*
Adrian Knothd3c36ed2013-07-05 11:28:09 +02002347 * Returns the AES sample rate class for the given card.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002348 */
Adrian Knothd3c36ed2013-07-05 11:28:09 +02002349static int hdspm_get_aes_sample_rate(struct hdspm *hdspm, int index)
2350{
2351 int timecode;
2352
2353 switch (hdspm->io_type) {
2354 case AES32:
2355 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
2356 return (timecode >> (4*index)) & 0xF;
Adrian Knothd3c36ed2013-07-05 11:28:09 +02002357 default:
2358 break;
2359 }
2360 return 0;
2361}
Adrian Knoth0dca1792011-01-26 19:32:14 +01002362
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002363/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002364 * Returns the sample rate class for input source <idx> for
2365 * 'new style' cards like the AIO and RayDAT.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002366 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002367static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
2368{
2369 int status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2370
2371 return (status >> (idx*4)) & 0xF;
2372}
2373
Adrian Knoth8cea5712013-07-05 11:27:59 +02002374#define ENUMERATED_CTL_INFO(info, texts) \
Adrian Knoth38816542013-07-05 11:28:20 +02002375 snd_ctl_enum_info(info, 1, ARRAY_SIZE(texts), texts)
Adrian Knoth8cea5712013-07-05 11:27:59 +02002376
Adrian Knoth0dca1792011-01-26 19:32:14 +01002377
Adrian Knoth23361422013-07-05 11:28:17 +02002378/* Helper function to query the external sample rate and return the
2379 * corresponding enum to be returned to userspace.
2380 */
2381static int hdspm_external_rate_to_enum(struct hdspm *hdspm)
2382{
2383 int rate = hdspm_external_sample_rate(hdspm);
2384 int i, selected_rate = 0;
2385 for (i = 1; i < 10; i++)
2386 if (HDSPM_bit2freq(i) == rate) {
2387 selected_rate = i;
2388 break;
2389 }
2390 return selected_rate;
2391}
2392
Adrian Knoth0dca1792011-01-26 19:32:14 +01002393
2394#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
2395{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2396 .name = xname, \
2397 .private_value = xindex, \
2398 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2399 .info = snd_hdspm_info_autosync_sample_rate, \
2400 .get = snd_hdspm_get_autosync_sample_rate \
2401}
2402
2403
Takashi Iwai98274f02005-11-17 14:52:34 +01002404static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2405 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002406{
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01002407 ENUMERATED_CTL_INFO(uinfo, texts_freq);
Takashi Iwai763f3562005-06-03 11:25:34 +02002408 return 0;
2409}
2410
Adrian Knoth0dca1792011-01-26 19:32:14 +01002411
Takashi Iwai98274f02005-11-17 14:52:34 +01002412static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2413 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002414 ucontrol)
2415{
Takashi Iwai98274f02005-11-17 14:52:34 +01002416 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002417
Adrian Knoth0dca1792011-01-26 19:32:14 +01002418 switch (hdspm->io_type) {
2419 case RayDAT:
2420 switch (kcontrol->private_value) {
2421 case 0:
2422 ucontrol->value.enumerated.item[0] =
2423 hdspm_get_wc_sample_rate(hdspm);
2424 break;
2425 case 7:
2426 ucontrol->value.enumerated.item[0] =
2427 hdspm_get_tco_sample_rate(hdspm);
2428 break;
2429 case 8:
2430 ucontrol->value.enumerated.item[0] =
2431 hdspm_get_sync_in_sample_rate(hdspm);
2432 break;
2433 default:
2434 ucontrol->value.enumerated.item[0] =
2435 hdspm_get_s1_sample_rate(hdspm,
2436 kcontrol->private_value-1);
2437 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002438 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002439
Adrian Knoth0dca1792011-01-26 19:32:14 +01002440 case AIO:
2441 switch (kcontrol->private_value) {
2442 case 0: /* WC */
2443 ucontrol->value.enumerated.item[0] =
2444 hdspm_get_wc_sample_rate(hdspm);
2445 break;
2446 case 4: /* TCO */
2447 ucontrol->value.enumerated.item[0] =
2448 hdspm_get_tco_sample_rate(hdspm);
2449 break;
2450 case 5: /* SYNC_IN */
2451 ucontrol->value.enumerated.item[0] =
2452 hdspm_get_sync_in_sample_rate(hdspm);
2453 break;
2454 default:
2455 ucontrol->value.enumerated.item[0] =
2456 hdspm_get_s1_sample_rate(hdspm,
Adrian Knoth1cb7dbf2013-07-05 11:28:03 +02002457 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002458 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002459 break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002460
2461 case AES32:
2462
2463 switch (kcontrol->private_value) {
2464 case 0: /* WC */
2465 ucontrol->value.enumerated.item[0] =
2466 hdspm_get_wc_sample_rate(hdspm);
2467 break;
2468 case 9: /* TCO */
2469 ucontrol->value.enumerated.item[0] =
2470 hdspm_get_tco_sample_rate(hdspm);
2471 break;
2472 case 10: /* SYNC_IN */
2473 ucontrol->value.enumerated.item[0] =
2474 hdspm_get_sync_in_sample_rate(hdspm);
2475 break;
Adrian Knoth2d63ec32013-07-05 11:28:18 +02002476 case 11: /* External Rate */
2477 ucontrol->value.enumerated.item[0] =
2478 hdspm_external_rate_to_enum(hdspm);
2479 break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002480 default: /* AES1 to AES8 */
2481 ucontrol->value.enumerated.item[0] =
Adrian Knoth2d63ec32013-07-05 11:28:18 +02002482 hdspm_get_aes_sample_rate(hdspm,
2483 kcontrol->private_value -
2484 HDSPM_AES32_AUTOSYNC_FROM_AES1);
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002485 break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002486 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002487 break;
Adrian Knothb8812c52012-10-19 17:42:26 +02002488
2489 case MADI:
2490 case MADIface:
Adrian Knoth23361422013-07-05 11:28:17 +02002491 ucontrol->value.enumerated.item[0] =
2492 hdspm_external_rate_to_enum(hdspm);
Adrian Knothb8812c52012-10-19 17:42:26 +02002493 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002494 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002495 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002496 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002497
Takashi Iwai763f3562005-06-03 11:25:34 +02002498 return 0;
2499}
2500
Adrian Knoth0dca1792011-01-26 19:32:14 +01002501
Takashi Iwai763f3562005-06-03 11:25:34 +02002502#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002503{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2504 .name = xname, \
2505 .index = xindex, \
2506 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2507 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2508 .info = snd_hdspm_info_system_clock_mode, \
2509 .get = snd_hdspm_get_system_clock_mode, \
2510 .put = snd_hdspm_put_system_clock_mode, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002511}
2512
2513
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002514/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002515 * Returns the system clock mode for the given card.
2516 * @returns 0 - master, 1 - slave
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002517 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002518static int hdspm_system_clock_mode(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002519{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002520 switch (hdspm->io_type) {
2521 case AIO:
2522 case RayDAT:
2523 if (hdspm->settings_register & HDSPM_c0Master)
2524 return 0;
2525 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002526
Adrian Knoth0dca1792011-01-26 19:32:14 +01002527 default:
2528 if (hdspm->control_register & HDSPM_ClockModeMaster)
2529 return 0;
2530 }
2531
Takashi Iwai763f3562005-06-03 11:25:34 +02002532 return 1;
2533}
2534
Adrian Knoth0dca1792011-01-26 19:32:14 +01002535
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002536/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002537 * Sets the system clock mode.
2538 * @param mode 0 - master, 1 - slave
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002539 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002540static void hdspm_set_system_clock_mode(struct hdspm *hdspm, int mode)
2541{
Adrian Knoth34be7ebb2013-07-05 11:27:56 +02002542 hdspm_set_toggle_setting(hdspm,
2543 (hdspm_is_raydat_or_aio(hdspm)) ?
2544 HDSPM_c0Master : HDSPM_ClockModeMaster,
2545 (0 == mode));
Adrian Knoth0dca1792011-01-26 19:32:14 +01002546}
2547
2548
Takashi Iwai98274f02005-11-17 14:52:34 +01002549static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
2550 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002551{
Adrian Knoth38816542013-07-05 11:28:20 +02002552 static const char *const texts[] = { "Master", "AutoSync" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01002553 ENUMERATED_CTL_INFO(uinfo, texts);
Takashi Iwai763f3562005-06-03 11:25:34 +02002554 return 0;
2555}
2556
Takashi Iwai98274f02005-11-17 14:52:34 +01002557static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
2558 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002559{
Takashi Iwai98274f02005-11-17 14:52:34 +01002560 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002561
Adrian Knoth0dca1792011-01-26 19:32:14 +01002562 ucontrol->value.enumerated.item[0] = hdspm_system_clock_mode(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002563 return 0;
2564}
2565
Adrian Knoth0dca1792011-01-26 19:32:14 +01002566static int snd_hdspm_put_system_clock_mode(struct snd_kcontrol *kcontrol,
2567 struct snd_ctl_elem_value *ucontrol)
2568{
2569 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2570 int val;
2571
2572 if (!snd_hdspm_use_is_exclusive(hdspm))
2573 return -EBUSY;
2574
2575 val = ucontrol->value.enumerated.item[0];
2576 if (val < 0)
2577 val = 0;
2578 else if (val > 1)
2579 val = 1;
2580
2581 hdspm_set_system_clock_mode(hdspm, val);
2582
2583 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002584}
2585
Adrian Knoth0dca1792011-01-26 19:32:14 +01002586
2587#define HDSPM_INTERNAL_CLOCK(xname, xindex) \
2588{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2589 .name = xname, \
2590 .index = xindex, \
2591 .info = snd_hdspm_info_clock_source, \
2592 .get = snd_hdspm_get_clock_source, \
2593 .put = snd_hdspm_put_clock_source \
2594}
2595
2596
Takashi Iwai98274f02005-11-17 14:52:34 +01002597static int hdspm_clock_source(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002598{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002599 switch (hdspm->system_sample_rate) {
2600 case 32000: return 0;
2601 case 44100: return 1;
2602 case 48000: return 2;
2603 case 64000: return 3;
2604 case 88200: return 4;
2605 case 96000: return 5;
2606 case 128000: return 6;
2607 case 176400: return 7;
2608 case 192000: return 8;
Takashi Iwai763f3562005-06-03 11:25:34 +02002609 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002610
2611 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002612}
2613
Takashi Iwai98274f02005-11-17 14:52:34 +01002614static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
Takashi Iwai763f3562005-06-03 11:25:34 +02002615{
2616 int rate;
2617 switch (mode) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002618 case 0:
2619 rate = 32000; break;
2620 case 1:
2621 rate = 44100; break;
2622 case 2:
2623 rate = 48000; break;
2624 case 3:
2625 rate = 64000; break;
2626 case 4:
2627 rate = 88200; break;
2628 case 5:
2629 rate = 96000; break;
2630 case 6:
2631 rate = 128000; break;
2632 case 7:
2633 rate = 176400; break;
2634 case 8:
2635 rate = 192000; break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002636 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002637 rate = 48000;
Takashi Iwai763f3562005-06-03 11:25:34 +02002638 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002639 hdspm_set_rate(hdspm, rate, 1);
2640 return 0;
2641}
2642
Takashi Iwai98274f02005-11-17 14:52:34 +01002643static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
2644 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002645{
Takashi Iwaic69a6372014-10-20 18:19:41 +02002646 return snd_ctl_enum_info(uinfo, 1, 9, texts_freq + 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02002647}
2648
Takashi Iwai98274f02005-11-17 14:52:34 +01002649static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
2650 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002651{
Takashi Iwai98274f02005-11-17 14:52:34 +01002652 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002653
2654 ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
2655 return 0;
2656}
2657
Takashi Iwai98274f02005-11-17 14:52:34 +01002658static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
2659 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002660{
Takashi Iwai98274f02005-11-17 14:52:34 +01002661 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002662 int change;
2663 int val;
2664
2665 if (!snd_hdspm_use_is_exclusive(hdspm))
2666 return -EBUSY;
2667 val = ucontrol->value.enumerated.item[0];
2668 if (val < 0)
2669 val = 0;
Remy Bruno65345992007-08-31 12:21:08 +02002670 if (val > 9)
2671 val = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002672 spin_lock_irq(&hdspm->lock);
2673 if (val != hdspm_clock_source(hdspm))
2674 change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
2675 else
2676 change = 0;
2677 spin_unlock_irq(&hdspm->lock);
2678 return change;
2679}
2680
Adrian Knoth0dca1792011-01-26 19:32:14 +01002681
Takashi Iwai763f3562005-06-03 11:25:34 +02002682#define HDSPM_PREF_SYNC_REF(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02002683{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002684 .name = xname, \
2685 .index = xindex, \
2686 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2687 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2688 .info = snd_hdspm_info_pref_sync_ref, \
2689 .get = snd_hdspm_get_pref_sync_ref, \
2690 .put = snd_hdspm_put_pref_sync_ref \
Takashi Iwai763f3562005-06-03 11:25:34 +02002691}
2692
Adrian Knoth0dca1792011-01-26 19:32:14 +01002693
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002694/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002695 * Returns the current preferred sync reference setting.
2696 * The semantics of the return value are depending on the
2697 * card, please see the comments for clarification.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002698 */
Takashi Iwai98274f02005-11-17 14:52:34 +01002699static int hdspm_pref_sync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002700{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002701 switch (hdspm->io_type) {
2702 case AES32:
Remy Bruno3cee5a62006-10-16 12:46:32 +02002703 switch (hdspm->control_register & HDSPM_SyncRefMask) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002704 case 0: return 0; /* WC */
2705 case HDSPM_SyncRef0: return 1; /* AES 1 */
2706 case HDSPM_SyncRef1: return 2; /* AES 2 */
2707 case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; /* AES 3 */
2708 case HDSPM_SyncRef2: return 4; /* AES 4 */
2709 case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; /* AES 5 */
2710 case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; /* AES 6 */
2711 case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0:
2712 return 7; /* AES 7 */
2713 case HDSPM_SyncRef3: return 8; /* AES 8 */
2714 case HDSPM_SyncRef3+HDSPM_SyncRef0: return 9; /* TCO */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002715 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002716 break;
2717
2718 case MADI:
2719 case MADIface:
2720 if (hdspm->tco) {
2721 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2722 case 0: return 0; /* WC */
2723 case HDSPM_SyncRef0: return 1; /* MADI */
2724 case HDSPM_SyncRef1: return 2; /* TCO */
2725 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2726 return 3; /* SYNC_IN */
2727 }
2728 } else {
2729 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2730 case 0: return 0; /* WC */
2731 case HDSPM_SyncRef0: return 1; /* MADI */
2732 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2733 return 2; /* SYNC_IN */
2734 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02002735 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002736 break;
2737
2738 case RayDAT:
2739 if (hdspm->tco) {
2740 switch ((hdspm->settings_register &
2741 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2742 case 0: return 0; /* WC */
2743 case 3: return 1; /* ADAT 1 */
2744 case 4: return 2; /* ADAT 2 */
2745 case 5: return 3; /* ADAT 3 */
2746 case 6: return 4; /* ADAT 4 */
2747 case 1: return 5; /* AES */
2748 case 2: return 6; /* SPDIF */
2749 case 9: return 7; /* TCO */
2750 case 10: return 8; /* SYNC_IN */
2751 }
2752 } else {
2753 switch ((hdspm->settings_register &
2754 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2755 case 0: return 0; /* WC */
2756 case 3: return 1; /* ADAT 1 */
2757 case 4: return 2; /* ADAT 2 */
2758 case 5: return 3; /* ADAT 3 */
2759 case 6: return 4; /* ADAT 4 */
2760 case 1: return 5; /* AES */
2761 case 2: return 6; /* SPDIF */
2762 case 10: return 7; /* SYNC_IN */
2763 }
2764 }
2765
2766 break;
2767
2768 case AIO:
2769 if (hdspm->tco) {
2770 switch ((hdspm->settings_register &
2771 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2772 case 0: return 0; /* WC */
2773 case 3: return 1; /* ADAT */
2774 case 1: return 2; /* AES */
2775 case 2: return 3; /* SPDIF */
2776 case 9: return 4; /* TCO */
2777 case 10: return 5; /* SYNC_IN */
2778 }
2779 } else {
2780 switch ((hdspm->settings_register &
2781 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2782 case 0: return 0; /* WC */
2783 case 3: return 1; /* ADAT */
2784 case 1: return 2; /* AES */
2785 case 2: return 3; /* SPDIF */
2786 case 10: return 4; /* SYNC_IN */
2787 }
2788 }
2789
2790 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002791 }
2792
Adrian Knoth0dca1792011-01-26 19:32:14 +01002793 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002794}
2795
Adrian Knoth0dca1792011-01-26 19:32:14 +01002796
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002797/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002798 * Set the preferred sync reference to <pref>. The semantics
2799 * of <pref> are depending on the card type, see the comments
2800 * for clarification.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002801 */
Takashi Iwai98274f02005-11-17 14:52:34 +01002802static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
Takashi Iwai763f3562005-06-03 11:25:34 +02002803{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002804 int p = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002805
Adrian Knoth0dca1792011-01-26 19:32:14 +01002806 switch (hdspm->io_type) {
2807 case AES32:
2808 hdspm->control_register &= ~HDSPM_SyncRefMask;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002809 switch (pref) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002810 case 0: /* WC */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002811 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002812 case 1: /* AES 1 */
2813 hdspm->control_register |= HDSPM_SyncRef0;
2814 break;
2815 case 2: /* AES 2 */
2816 hdspm->control_register |= HDSPM_SyncRef1;
2817 break;
2818 case 3: /* AES 3 */
2819 hdspm->control_register |=
2820 HDSPM_SyncRef1+HDSPM_SyncRef0;
2821 break;
2822 case 4: /* AES 4 */
2823 hdspm->control_register |= HDSPM_SyncRef2;
2824 break;
2825 case 5: /* AES 5 */
2826 hdspm->control_register |=
2827 HDSPM_SyncRef2+HDSPM_SyncRef0;
2828 break;
2829 case 6: /* AES 6 */
2830 hdspm->control_register |=
2831 HDSPM_SyncRef2+HDSPM_SyncRef1;
2832 break;
2833 case 7: /* AES 7 */
2834 hdspm->control_register |=
2835 HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
2836 break;
2837 case 8: /* AES 8 */
2838 hdspm->control_register |= HDSPM_SyncRef3;
2839 break;
2840 case 9: /* TCO */
2841 hdspm->control_register |=
2842 HDSPM_SyncRef3+HDSPM_SyncRef0;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002843 break;
2844 default:
2845 return -1;
2846 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002847
2848 break;
2849
2850 case MADI:
2851 case MADIface:
2852 hdspm->control_register &= ~HDSPM_SyncRefMask;
2853 if (hdspm->tco) {
2854 switch (pref) {
2855 case 0: /* WC */
2856 break;
2857 case 1: /* MADI */
2858 hdspm->control_register |= HDSPM_SyncRef0;
2859 break;
2860 case 2: /* TCO */
2861 hdspm->control_register |= HDSPM_SyncRef1;
2862 break;
2863 case 3: /* SYNC_IN */
2864 hdspm->control_register |=
2865 HDSPM_SyncRef0+HDSPM_SyncRef1;
2866 break;
2867 default:
2868 return -1;
2869 }
2870 } else {
2871 switch (pref) {
2872 case 0: /* WC */
2873 break;
2874 case 1: /* MADI */
2875 hdspm->control_register |= HDSPM_SyncRef0;
2876 break;
2877 case 2: /* SYNC_IN */
2878 hdspm->control_register |=
2879 HDSPM_SyncRef0+HDSPM_SyncRef1;
2880 break;
2881 default:
2882 return -1;
2883 }
2884 }
2885
2886 break;
2887
2888 case RayDAT:
2889 if (hdspm->tco) {
2890 switch (pref) {
2891 case 0: p = 0; break; /* WC */
2892 case 1: p = 3; break; /* ADAT 1 */
2893 case 2: p = 4; break; /* ADAT 2 */
2894 case 3: p = 5; break; /* ADAT 3 */
2895 case 4: p = 6; break; /* ADAT 4 */
2896 case 5: p = 1; break; /* AES */
2897 case 6: p = 2; break; /* SPDIF */
2898 case 7: p = 9; break; /* TCO */
2899 case 8: p = 10; break; /* SYNC_IN */
2900 default: return -1;
2901 }
2902 } else {
2903 switch (pref) {
2904 case 0: p = 0; break; /* WC */
2905 case 1: p = 3; break; /* ADAT 1 */
2906 case 2: p = 4; break; /* ADAT 2 */
2907 case 3: p = 5; break; /* ADAT 3 */
2908 case 4: p = 6; break; /* ADAT 4 */
2909 case 5: p = 1; break; /* AES */
2910 case 6: p = 2; break; /* SPDIF */
2911 case 7: p = 10; break; /* SYNC_IN */
2912 default: return -1;
2913 }
2914 }
2915 break;
2916
2917 case AIO:
2918 if (hdspm->tco) {
2919 switch (pref) {
2920 case 0: p = 0; break; /* WC */
2921 case 1: p = 3; break; /* ADAT */
2922 case 2: p = 1; break; /* AES */
2923 case 3: p = 2; break; /* SPDIF */
2924 case 4: p = 9; break; /* TCO */
2925 case 5: p = 10; break; /* SYNC_IN */
2926 default: return -1;
2927 }
2928 } else {
2929 switch (pref) {
2930 case 0: p = 0; break; /* WC */
2931 case 1: p = 3; break; /* ADAT */
2932 case 2: p = 1; break; /* AES */
2933 case 3: p = 2; break; /* SPDIF */
2934 case 4: p = 10; break; /* SYNC_IN */
2935 default: return -1;
2936 }
2937 }
2938 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002939 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002940
2941 switch (hdspm->io_type) {
2942 case RayDAT:
2943 case AIO:
2944 hdspm->settings_register &= ~HDSPM_c0_SyncRefMask;
2945 hdspm->settings_register |= HDSPM_c0_SyncRef0 * p;
2946 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2947 break;
2948
2949 case MADI:
2950 case MADIface:
2951 case AES32:
2952 hdspm_write(hdspm, HDSPM_controlRegister,
2953 hdspm->control_register);
2954 }
2955
Takashi Iwai763f3562005-06-03 11:25:34 +02002956 return 0;
2957}
2958
Adrian Knoth0dca1792011-01-26 19:32:14 +01002959
Takashi Iwai98274f02005-11-17 14:52:34 +01002960static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
2961 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002962{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002963 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002964
Adrian Knotheb0d4db2013-07-05 11:28:21 +02002965 snd_ctl_enum_info(uinfo, 1, hdspm->texts_autosync_items, hdspm->texts_autosync);
Remy Bruno3cee5a62006-10-16 12:46:32 +02002966
Takashi Iwai763f3562005-06-03 11:25:34 +02002967 return 0;
2968}
2969
Takashi Iwai98274f02005-11-17 14:52:34 +01002970static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
2971 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002972{
Takashi Iwai98274f02005-11-17 14:52:34 +01002973 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002974 int psf = hdspm_pref_sync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002975
Adrian Knoth0dca1792011-01-26 19:32:14 +01002976 if (psf >= 0) {
2977 ucontrol->value.enumerated.item[0] = psf;
2978 return 0;
2979 }
2980
2981 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002982}
2983
Takashi Iwai98274f02005-11-17 14:52:34 +01002984static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
2985 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002986{
Takashi Iwai98274f02005-11-17 14:52:34 +01002987 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002988 int val, change = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002989
2990 if (!snd_hdspm_use_is_exclusive(hdspm))
2991 return -EBUSY;
2992
Adrian Knoth0dca1792011-01-26 19:32:14 +01002993 val = ucontrol->value.enumerated.item[0];
2994
2995 if (val < 0)
2996 val = 0;
2997 else if (val >= hdspm->texts_autosync_items)
2998 val = hdspm->texts_autosync_items-1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002999
3000 spin_lock_irq(&hdspm->lock);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003001 if (val != hdspm_pref_sync_ref(hdspm))
3002 change = (0 == hdspm_set_pref_sync_ref(hdspm, val)) ? 1 : 0;
3003
Takashi Iwai763f3562005-06-03 11:25:34 +02003004 spin_unlock_irq(&hdspm->lock);
3005 return change;
3006}
3007
Adrian Knoth0dca1792011-01-26 19:32:14 +01003008
Takashi Iwai763f3562005-06-03 11:25:34 +02003009#define HDSPM_AUTOSYNC_REF(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003010{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3011 .name = xname, \
3012 .index = xindex, \
3013 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
3014 .info = snd_hdspm_info_autosync_ref, \
3015 .get = snd_hdspm_get_autosync_ref, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003016}
3017
Adrian Knoth0dca1792011-01-26 19:32:14 +01003018static int hdspm_autosync_ref(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003019{
Adrian Knoth2d60fc72013-07-05 11:28:15 +02003020 /* This looks at the autosync selected sync reference */
Adrian Knoth0dca1792011-01-26 19:32:14 +01003021 if (AES32 == hdspm->io_type) {
Takashi Iwai763f3562005-06-03 11:25:34 +02003022
Adrian Knoth2d60fc72013-07-05 11:28:15 +02003023 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
3024 unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) & 0xF;
Pierre-Louis Bossartab3ee092020-07-02 14:35:56 -05003025 /* syncref >= HDSPM_AES32_AUTOSYNC_FROM_WORD is always true */
3026 if (syncref <= HDSPM_AES32_AUTOSYNC_FROM_SYNC_IN) {
Adrian Knoth2d60fc72013-07-05 11:28:15 +02003027 return syncref;
3028 }
3029 return HDSPM_AES32_AUTOSYNC_FROM_NONE;
3030
3031 } else if (MADI == hdspm->io_type) {
3032
3033 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003034 switch (status2 & HDSPM_SelSyncRefMask) {
3035 case HDSPM_SelSyncRef_WORD:
3036 return HDSPM_AUTOSYNC_FROM_WORD;
3037 case HDSPM_SelSyncRef_MADI:
3038 return HDSPM_AUTOSYNC_FROM_MADI;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003039 case HDSPM_SelSyncRef_TCO:
3040 return HDSPM_AUTOSYNC_FROM_TCO;
3041 case HDSPM_SelSyncRef_SyncIn:
3042 return HDSPM_AUTOSYNC_FROM_SYNC_IN;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003043 case HDSPM_SelSyncRef_NVALID:
3044 return HDSPM_AUTOSYNC_FROM_NONE;
3045 default:
Adrian Knothe71b95a2013-07-05 11:28:06 +02003046 return HDSPM_AUTOSYNC_FROM_NONE;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003047 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003048
Takashi Iwai763f3562005-06-03 11:25:34 +02003049 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01003050 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02003051}
3052
Adrian Knoth0dca1792011-01-26 19:32:14 +01003053
Takashi Iwai98274f02005-11-17 14:52:34 +01003054static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
3055 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003056{
Remy Bruno3cee5a62006-10-16 12:46:32 +02003057 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003058
Adrian Knoth0dca1792011-01-26 19:32:14 +01003059 if (AES32 == hdspm->io_type) {
Adrian Knoth04659f92013-07-05 11:28:22 +02003060 static const char *const texts[] = { "WordClock", "AES1", "AES2", "AES3",
Adrian Knothdb2d1a92013-07-05 11:28:08 +02003061 "AES4", "AES5", "AES6", "AES7", "AES8", "TCO", "Sync In", "None"};
Remy Bruno3cee5a62006-10-16 12:46:32 +02003062
Adrian Knoth04659f92013-07-05 11:28:22 +02003063 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003064 } else if (MADI == hdspm->io_type) {
Adrian Knoth04659f92013-07-05 11:28:22 +02003065 static const char *const texts[] = {"Word Clock", "MADI", "TCO",
Adrian Knoth0dca1792011-01-26 19:32:14 +01003066 "Sync In", "None" };
Remy Bruno3cee5a62006-10-16 12:46:32 +02003067
Adrian Knoth04659f92013-07-05 11:28:22 +02003068 ENUMERATED_CTL_INFO(uinfo, texts);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003069 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003070 return 0;
3071}
3072
Takashi Iwai98274f02005-11-17 14:52:34 +01003073static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
3074 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003075{
Takashi Iwai98274f02005-11-17 14:52:34 +01003076 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003077
Remy Bruno65345992007-08-31 12:21:08 +02003078 ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02003079 return 0;
3080}
3081
Adrian Knothf99c7882013-03-10 00:37:26 +01003082
3083
3084#define HDSPM_TCO_VIDEO_INPUT_FORMAT(xname, xindex) \
3085{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3086 .name = xname, \
3087 .access = SNDRV_CTL_ELEM_ACCESS_READ |\
3088 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3089 .info = snd_hdspm_info_tco_video_input_format, \
3090 .get = snd_hdspm_get_tco_video_input_format, \
3091}
3092
3093static int snd_hdspm_info_tco_video_input_format(struct snd_kcontrol *kcontrol,
3094 struct snd_ctl_elem_info *uinfo)
3095{
Adrian Knoth38816542013-07-05 11:28:20 +02003096 static const char *const texts[] = {"No video", "NTSC", "PAL"};
Adrian Knothf99c7882013-03-10 00:37:26 +01003097 ENUMERATED_CTL_INFO(uinfo, texts);
3098 return 0;
3099}
3100
3101static int snd_hdspm_get_tco_video_input_format(struct snd_kcontrol *kcontrol,
3102 struct snd_ctl_elem_value *ucontrol)
3103{
3104 u32 status;
3105 int ret = 0;
3106
3107 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3108 status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
3109 switch (status & (HDSPM_TCO1_Video_Input_Format_NTSC |
3110 HDSPM_TCO1_Video_Input_Format_PAL)) {
3111 case HDSPM_TCO1_Video_Input_Format_NTSC:
3112 /* ntsc */
3113 ret = 1;
3114 break;
3115 case HDSPM_TCO1_Video_Input_Format_PAL:
3116 /* pal */
3117 ret = 2;
3118 break;
3119 default:
3120 /* no video */
3121 ret = 0;
3122 break;
3123 }
3124 ucontrol->value.enumerated.item[0] = ret;
3125 return 0;
3126}
3127
3128
3129
3130#define HDSPM_TCO_LTC_FRAMES(xname, xindex) \
3131{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3132 .name = xname, \
3133 .access = SNDRV_CTL_ELEM_ACCESS_READ |\
3134 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3135 .info = snd_hdspm_info_tco_ltc_frames, \
3136 .get = snd_hdspm_get_tco_ltc_frames, \
3137}
3138
3139static int snd_hdspm_info_tco_ltc_frames(struct snd_kcontrol *kcontrol,
3140 struct snd_ctl_elem_info *uinfo)
3141{
Adrian Knoth38816542013-07-05 11:28:20 +02003142 static const char *const texts[] = {"No lock", "24 fps", "25 fps", "29.97 fps",
Adrian Knothf99c7882013-03-10 00:37:26 +01003143 "30 fps"};
3144 ENUMERATED_CTL_INFO(uinfo, texts);
3145 return 0;
3146}
3147
3148static int hdspm_tco_ltc_frames(struct hdspm *hdspm)
3149{
3150 u32 status;
3151 int ret = 0;
3152
3153 status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
3154 if (status & HDSPM_TCO1_LTC_Input_valid) {
3155 switch (status & (HDSPM_TCO1_LTC_Format_LSB |
3156 HDSPM_TCO1_LTC_Format_MSB)) {
3157 case 0:
3158 /* 24 fps */
Adrian Knoth1568b882013-08-19 17:20:31 +02003159 ret = fps_24;
Adrian Knothf99c7882013-03-10 00:37:26 +01003160 break;
3161 case HDSPM_TCO1_LTC_Format_LSB:
3162 /* 25 fps */
Adrian Knoth1568b882013-08-19 17:20:31 +02003163 ret = fps_25;
Adrian Knothf99c7882013-03-10 00:37:26 +01003164 break;
3165 case HDSPM_TCO1_LTC_Format_MSB:
Adrian Knoth1568b882013-08-19 17:20:31 +02003166 /* 29.97 fps */
3167 ret = fps_2997;
Adrian Knothf99c7882013-03-10 00:37:26 +01003168 break;
3169 default:
3170 /* 30 fps */
Adrian Knoth1568b882013-08-19 17:20:31 +02003171 ret = fps_30;
Adrian Knothf99c7882013-03-10 00:37:26 +01003172 break;
3173 }
3174 }
3175
3176 return ret;
3177}
3178
3179static int snd_hdspm_get_tco_ltc_frames(struct snd_kcontrol *kcontrol,
3180 struct snd_ctl_elem_value *ucontrol)
3181{
3182 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3183
3184 ucontrol->value.enumerated.item[0] = hdspm_tco_ltc_frames(hdspm);
3185 return 0;
3186}
3187
Adrian Knothbf0ff872012-12-03 14:55:49 +01003188#define HDSPM_TOGGLE_SETTING(xname, xindex) \
3189{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3190 .name = xname, \
3191 .private_value = xindex, \
3192 .info = snd_hdspm_info_toggle_setting, \
3193 .get = snd_hdspm_get_toggle_setting, \
3194 .put = snd_hdspm_put_toggle_setting \
3195}
3196
3197static int hdspm_toggle_setting(struct hdspm *hdspm, u32 regmask)
3198{
Adrian Knothce13f3f2013-07-05 11:27:55 +02003199 u32 reg;
3200
3201 if (hdspm_is_raydat_or_aio(hdspm))
3202 reg = hdspm->settings_register;
3203 else
3204 reg = hdspm->control_register;
3205
3206 return (reg & regmask) ? 1 : 0;
Adrian Knothbf0ff872012-12-03 14:55:49 +01003207}
3208
3209static int hdspm_set_toggle_setting(struct hdspm *hdspm, u32 regmask, int out)
3210{
Adrian Knothce13f3f2013-07-05 11:27:55 +02003211 u32 *reg;
3212 u32 target_reg;
3213
3214 if (hdspm_is_raydat_or_aio(hdspm)) {
3215 reg = &(hdspm->settings_register);
3216 target_reg = HDSPM_WR_SETTINGS;
3217 } else {
3218 reg = &(hdspm->control_register);
3219 target_reg = HDSPM_controlRegister;
3220 }
3221
Adrian Knothbf0ff872012-12-03 14:55:49 +01003222 if (out)
Adrian Knothce13f3f2013-07-05 11:27:55 +02003223 *reg |= regmask;
Adrian Knothbf0ff872012-12-03 14:55:49 +01003224 else
Adrian Knothce13f3f2013-07-05 11:27:55 +02003225 *reg &= ~regmask;
3226
3227 hdspm_write(hdspm, target_reg, *reg);
Adrian Knothbf0ff872012-12-03 14:55:49 +01003228
3229 return 0;
3230}
3231
3232#define snd_hdspm_info_toggle_setting snd_ctl_boolean_mono_info
3233
3234static int snd_hdspm_get_toggle_setting(struct snd_kcontrol *kcontrol,
3235 struct snd_ctl_elem_value *ucontrol)
3236{
3237 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3238 u32 regmask = kcontrol->private_value;
3239
3240 spin_lock_irq(&hdspm->lock);
3241 ucontrol->value.integer.value[0] = hdspm_toggle_setting(hdspm, regmask);
3242 spin_unlock_irq(&hdspm->lock);
3243 return 0;
3244}
3245
3246static int snd_hdspm_put_toggle_setting(struct snd_kcontrol *kcontrol,
3247 struct snd_ctl_elem_value *ucontrol)
3248{
3249 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3250 u32 regmask = kcontrol->private_value;
3251 int change;
3252 unsigned int val;
3253
3254 if (!snd_hdspm_use_is_exclusive(hdspm))
3255 return -EBUSY;
3256 val = ucontrol->value.integer.value[0] & 1;
3257 spin_lock_irq(&hdspm->lock);
3258 change = (int) val != hdspm_toggle_setting(hdspm, regmask);
3259 hdspm_set_toggle_setting(hdspm, regmask, val);
3260 spin_unlock_irq(&hdspm->lock);
3261 return change;
3262}
3263
Takashi Iwai763f3562005-06-03 11:25:34 +02003264#define HDSPM_INPUT_SELECT(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003265{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3266 .name = xname, \
3267 .index = xindex, \
3268 .info = snd_hdspm_info_input_select, \
3269 .get = snd_hdspm_get_input_select, \
3270 .put = snd_hdspm_put_input_select \
Takashi Iwai763f3562005-06-03 11:25:34 +02003271}
3272
Takashi Iwai98274f02005-11-17 14:52:34 +01003273static int hdspm_input_select(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003274{
3275 return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
3276}
3277
Takashi Iwai98274f02005-11-17 14:52:34 +01003278static int hdspm_set_input_select(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02003279{
3280 if (out)
3281 hdspm->control_register |= HDSPM_InputSelect0;
3282 else
3283 hdspm->control_register &= ~HDSPM_InputSelect0;
3284 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3285
3286 return 0;
3287}
3288
Takashi Iwai98274f02005-11-17 14:52:34 +01003289static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
3290 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003291{
Adrian Knoth38816542013-07-05 11:28:20 +02003292 static const char *const texts[] = { "optical", "coaxial" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003293 ENUMERATED_CTL_INFO(uinfo, texts);
Takashi Iwai763f3562005-06-03 11:25:34 +02003294 return 0;
3295}
3296
Takashi Iwai98274f02005-11-17 14:52:34 +01003297static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
3298 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003299{
Takashi Iwai98274f02005-11-17 14:52:34 +01003300 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003301
3302 spin_lock_irq(&hdspm->lock);
3303 ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
3304 spin_unlock_irq(&hdspm->lock);
3305 return 0;
3306}
3307
Takashi Iwai98274f02005-11-17 14:52:34 +01003308static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
3309 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003310{
Takashi Iwai98274f02005-11-17 14:52:34 +01003311 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003312 int change;
3313 unsigned int val;
3314
3315 if (!snd_hdspm_use_is_exclusive(hdspm))
3316 return -EBUSY;
3317 val = ucontrol->value.integer.value[0] & 1;
3318 spin_lock_irq(&hdspm->lock);
3319 change = (int) val != hdspm_input_select(hdspm);
3320 hdspm_set_input_select(hdspm, val);
3321 spin_unlock_irq(&hdspm->lock);
3322 return change;
3323}
3324
Adrian Knoth0dca1792011-01-26 19:32:14 +01003325
Remy Bruno3cee5a62006-10-16 12:46:32 +02003326#define HDSPM_DS_WIRE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003327{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3328 .name = xname, \
3329 .index = xindex, \
3330 .info = snd_hdspm_info_ds_wire, \
3331 .get = snd_hdspm_get_ds_wire, \
3332 .put = snd_hdspm_put_ds_wire \
Remy Bruno3cee5a62006-10-16 12:46:32 +02003333}
3334
3335static int hdspm_ds_wire(struct hdspm * hdspm)
3336{
3337 return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
3338}
3339
3340static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
3341{
3342 if (ds)
3343 hdspm->control_register |= HDSPM_DS_DoubleWire;
3344 else
3345 hdspm->control_register &= ~HDSPM_DS_DoubleWire;
3346 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3347
3348 return 0;
3349}
3350
3351static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
3352 struct snd_ctl_elem_info *uinfo)
3353{
Adrian Knoth38816542013-07-05 11:28:20 +02003354 static const char *const texts[] = { "Single", "Double" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003355 ENUMERATED_CTL_INFO(uinfo, texts);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003356 return 0;
3357}
3358
3359static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
3360 struct snd_ctl_elem_value *ucontrol)
3361{
3362 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3363
3364 spin_lock_irq(&hdspm->lock);
3365 ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
3366 spin_unlock_irq(&hdspm->lock);
3367 return 0;
3368}
3369
3370static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
3371 struct snd_ctl_elem_value *ucontrol)
3372{
3373 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3374 int change;
3375 unsigned int val;
3376
3377 if (!snd_hdspm_use_is_exclusive(hdspm))
3378 return -EBUSY;
3379 val = ucontrol->value.integer.value[0] & 1;
3380 spin_lock_irq(&hdspm->lock);
3381 change = (int) val != hdspm_ds_wire(hdspm);
3382 hdspm_set_ds_wire(hdspm, val);
3383 spin_unlock_irq(&hdspm->lock);
3384 return change;
3385}
3386
Adrian Knoth0dca1792011-01-26 19:32:14 +01003387
Remy Bruno3cee5a62006-10-16 12:46:32 +02003388#define HDSPM_QS_WIRE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003389{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3390 .name = xname, \
3391 .index = xindex, \
3392 .info = snd_hdspm_info_qs_wire, \
3393 .get = snd_hdspm_get_qs_wire, \
3394 .put = snd_hdspm_put_qs_wire \
Remy Bruno3cee5a62006-10-16 12:46:32 +02003395}
3396
3397static int hdspm_qs_wire(struct hdspm * hdspm)
3398{
3399 if (hdspm->control_register & HDSPM_QS_DoubleWire)
3400 return 1;
3401 if (hdspm->control_register & HDSPM_QS_QuadWire)
3402 return 2;
3403 return 0;
3404}
3405
3406static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
3407{
3408 hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
3409 switch (mode) {
3410 case 0:
3411 break;
3412 case 1:
3413 hdspm->control_register |= HDSPM_QS_DoubleWire;
3414 break;
3415 case 2:
3416 hdspm->control_register |= HDSPM_QS_QuadWire;
3417 break;
3418 }
3419 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3420
3421 return 0;
3422}
3423
3424static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
3425 struct snd_ctl_elem_info *uinfo)
3426{
Adrian Knoth38816542013-07-05 11:28:20 +02003427 static const char *const texts[] = { "Single", "Double", "Quad" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003428 ENUMERATED_CTL_INFO(uinfo, texts);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003429 return 0;
3430}
3431
3432static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
3433 struct snd_ctl_elem_value *ucontrol)
3434{
3435 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3436
3437 spin_lock_irq(&hdspm->lock);
3438 ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
3439 spin_unlock_irq(&hdspm->lock);
3440 return 0;
3441}
3442
3443static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
3444 struct snd_ctl_elem_value *ucontrol)
3445{
3446 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3447 int change;
3448 int val;
3449
3450 if (!snd_hdspm_use_is_exclusive(hdspm))
3451 return -EBUSY;
3452 val = ucontrol->value.integer.value[0];
3453 if (val < 0)
3454 val = 0;
3455 if (val > 2)
3456 val = 2;
3457 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003458 change = val != hdspm_qs_wire(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003459 hdspm_set_qs_wire(hdspm, val);
3460 spin_unlock_irq(&hdspm->lock);
3461 return change;
3462}
3463
Adrian Knothacf14762013-07-05 11:28:00 +02003464#define HDSPM_CONTROL_TRISTATE(xname, xindex) \
3465{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3466 .name = xname, \
3467 .private_value = xindex, \
3468 .info = snd_hdspm_info_tristate, \
3469 .get = snd_hdspm_get_tristate, \
3470 .put = snd_hdspm_put_tristate \
3471}
3472
3473static int hdspm_tristate(struct hdspm *hdspm, u32 regmask)
3474{
3475 u32 reg = hdspm->settings_register & (regmask * 3);
3476 return reg / regmask;
3477}
3478
3479static int hdspm_set_tristate(struct hdspm *hdspm, int mode, u32 regmask)
3480{
3481 hdspm->settings_register &= ~(regmask * 3);
3482 hdspm->settings_register |= (regmask * mode);
3483 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
3484
3485 return 0;
3486}
3487
3488static int snd_hdspm_info_tristate(struct snd_kcontrol *kcontrol,
3489 struct snd_ctl_elem_info *uinfo)
3490{
3491 u32 regmask = kcontrol->private_value;
3492
Adrian Knoth38816542013-07-05 11:28:20 +02003493 static const char *const texts_spdif[] = { "Optical", "Coaxial", "Internal" };
3494 static const char *const texts_levels[] = { "Hi Gain", "+4 dBu", "-10 dBV" };
Adrian Knothacf14762013-07-05 11:28:00 +02003495
3496 switch (regmask) {
3497 case HDSPM_c0_Input0:
3498 ENUMERATED_CTL_INFO(uinfo, texts_spdif);
3499 break;
3500 default:
3501 ENUMERATED_CTL_INFO(uinfo, texts_levels);
3502 break;
3503 }
3504 return 0;
3505}
3506
3507static int snd_hdspm_get_tristate(struct snd_kcontrol *kcontrol,
3508 struct snd_ctl_elem_value *ucontrol)
3509{
3510 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3511 u32 regmask = kcontrol->private_value;
3512
3513 spin_lock_irq(&hdspm->lock);
3514 ucontrol->value.enumerated.item[0] = hdspm_tristate(hdspm, regmask);
3515 spin_unlock_irq(&hdspm->lock);
3516 return 0;
3517}
3518
3519static int snd_hdspm_put_tristate(struct snd_kcontrol *kcontrol,
3520 struct snd_ctl_elem_value *ucontrol)
3521{
3522 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3523 u32 regmask = kcontrol->private_value;
3524 int change;
3525 int val;
3526
3527 if (!snd_hdspm_use_is_exclusive(hdspm))
3528 return -EBUSY;
3529 val = ucontrol->value.integer.value[0];
3530 if (val < 0)
3531 val = 0;
3532 if (val > 2)
3533 val = 2;
3534
3535 spin_lock_irq(&hdspm->lock);
3536 change = val != hdspm_tristate(hdspm, regmask);
3537 hdspm_set_tristate(hdspm, val, regmask);
3538 spin_unlock_irq(&hdspm->lock);
3539 return change;
3540}
3541
Adrian Knoth700d1ef2011-07-29 03:11:02 +02003542#define HDSPM_MADI_SPEEDMODE(xname, xindex) \
3543{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3544 .name = xname, \
3545 .index = xindex, \
3546 .info = snd_hdspm_info_madi_speedmode, \
3547 .get = snd_hdspm_get_madi_speedmode, \
3548 .put = snd_hdspm_put_madi_speedmode \
3549}
3550
3551static int hdspm_madi_speedmode(struct hdspm *hdspm)
3552{
3553 if (hdspm->control_register & HDSPM_QuadSpeed)
3554 return 2;
3555 if (hdspm->control_register & HDSPM_DoubleSpeed)
3556 return 1;
3557 return 0;
3558}
3559
3560static int hdspm_set_madi_speedmode(struct hdspm *hdspm, int mode)
3561{
3562 hdspm->control_register &= ~(HDSPM_DoubleSpeed | HDSPM_QuadSpeed);
3563 switch (mode) {
3564 case 0:
3565 break;
3566 case 1:
3567 hdspm->control_register |= HDSPM_DoubleSpeed;
3568 break;
3569 case 2:
3570 hdspm->control_register |= HDSPM_QuadSpeed;
3571 break;
3572 }
3573 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3574
3575 return 0;
3576}
3577
3578static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol,
3579 struct snd_ctl_elem_info *uinfo)
3580{
Adrian Knoth38816542013-07-05 11:28:20 +02003581 static const char *const texts[] = { "Single", "Double", "Quad" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003582 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth700d1ef2011-07-29 03:11:02 +02003583 return 0;
3584}
3585
3586static int snd_hdspm_get_madi_speedmode(struct snd_kcontrol *kcontrol,
3587 struct snd_ctl_elem_value *ucontrol)
3588{
3589 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3590
3591 spin_lock_irq(&hdspm->lock);
3592 ucontrol->value.enumerated.item[0] = hdspm_madi_speedmode(hdspm);
3593 spin_unlock_irq(&hdspm->lock);
3594 return 0;
3595}
3596
3597static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol,
3598 struct snd_ctl_elem_value *ucontrol)
3599{
3600 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3601 int change;
3602 int val;
3603
3604 if (!snd_hdspm_use_is_exclusive(hdspm))
3605 return -EBUSY;
3606 val = ucontrol->value.integer.value[0];
3607 if (val < 0)
3608 val = 0;
3609 if (val > 2)
3610 val = 2;
3611 spin_lock_irq(&hdspm->lock);
3612 change = val != hdspm_madi_speedmode(hdspm);
3613 hdspm_set_madi_speedmode(hdspm, val);
3614 spin_unlock_irq(&hdspm->lock);
3615 return change;
3616}
Takashi Iwai763f3562005-06-03 11:25:34 +02003617
3618#define HDSPM_MIXER(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003619{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
3620 .name = xname, \
3621 .index = xindex, \
3622 .device = 0, \
3623 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
3624 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3625 .info = snd_hdspm_info_mixer, \
3626 .get = snd_hdspm_get_mixer, \
3627 .put = snd_hdspm_put_mixer \
Takashi Iwai763f3562005-06-03 11:25:34 +02003628}
3629
Takashi Iwai98274f02005-11-17 14:52:34 +01003630static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
3631 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003632{
3633 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3634 uinfo->count = 3;
3635 uinfo->value.integer.min = 0;
3636 uinfo->value.integer.max = 65535;
3637 uinfo->value.integer.step = 1;
3638 return 0;
3639}
3640
Takashi Iwai98274f02005-11-17 14:52:34 +01003641static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
3642 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003643{
Takashi Iwai98274f02005-11-17 14:52:34 +01003644 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003645 int source;
3646 int destination;
3647
3648 source = ucontrol->value.integer.value[0];
3649 if (source < 0)
3650 source = 0;
3651 else if (source >= 2 * HDSPM_MAX_CHANNELS)
3652 source = 2 * HDSPM_MAX_CHANNELS - 1;
3653
3654 destination = ucontrol->value.integer.value[1];
3655 if (destination < 0)
3656 destination = 0;
3657 else if (destination >= HDSPM_MAX_CHANNELS)
3658 destination = HDSPM_MAX_CHANNELS - 1;
3659
3660 spin_lock_irq(&hdspm->lock);
3661 if (source >= HDSPM_MAX_CHANNELS)
3662 ucontrol->value.integer.value[2] =
3663 hdspm_read_pb_gain(hdspm, destination,
3664 source - HDSPM_MAX_CHANNELS);
3665 else
3666 ucontrol->value.integer.value[2] =
3667 hdspm_read_in_gain(hdspm, destination, source);
3668
3669 spin_unlock_irq(&hdspm->lock);
3670
3671 return 0;
3672}
3673
Takashi Iwai98274f02005-11-17 14:52:34 +01003674static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
3675 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003676{
Takashi Iwai98274f02005-11-17 14:52:34 +01003677 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003678 int change;
3679 int source;
3680 int destination;
3681 int gain;
3682
3683 if (!snd_hdspm_use_is_exclusive(hdspm))
3684 return -EBUSY;
3685
3686 source = ucontrol->value.integer.value[0];
3687 destination = ucontrol->value.integer.value[1];
3688
3689 if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
3690 return -1;
3691 if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
3692 return -1;
3693
3694 gain = ucontrol->value.integer.value[2];
3695
3696 spin_lock_irq(&hdspm->lock);
3697
3698 if (source >= HDSPM_MAX_CHANNELS)
3699 change = gain != hdspm_read_pb_gain(hdspm, destination,
3700 source -
3701 HDSPM_MAX_CHANNELS);
3702 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003703 change = gain != hdspm_read_in_gain(hdspm, destination,
3704 source);
Takashi Iwai763f3562005-06-03 11:25:34 +02003705
3706 if (change) {
3707 if (source >= HDSPM_MAX_CHANNELS)
3708 hdspm_write_pb_gain(hdspm, destination,
3709 source - HDSPM_MAX_CHANNELS,
3710 gain);
3711 else
3712 hdspm_write_in_gain(hdspm, destination, source,
3713 gain);
3714 }
3715 spin_unlock_irq(&hdspm->lock);
3716
3717 return change;
3718}
3719
3720/* The simple mixer control(s) provide gain control for the
3721 basic 1:1 mappings of playback streams to output
Adrian Knoth0dca1792011-01-26 19:32:14 +01003722 streams.
Takashi Iwai763f3562005-06-03 11:25:34 +02003723*/
3724
3725#define HDSPM_PLAYBACK_MIXER \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003726{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3727 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
3728 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3729 .info = snd_hdspm_info_playback_mixer, \
3730 .get = snd_hdspm_get_playback_mixer, \
3731 .put = snd_hdspm_put_playback_mixer \
Takashi Iwai763f3562005-06-03 11:25:34 +02003732}
3733
Takashi Iwai98274f02005-11-17 14:52:34 +01003734static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
3735 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003736{
3737 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3738 uinfo->count = 1;
3739 uinfo->value.integer.min = 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003740 uinfo->value.integer.max = 64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003741 uinfo->value.integer.step = 1;
3742 return 0;
3743}
3744
Takashi Iwai98274f02005-11-17 14:52:34 +01003745static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
3746 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003747{
Takashi Iwai98274f02005-11-17 14:52:34 +01003748 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003749 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003750
3751 channel = ucontrol->id.index - 1;
3752
Takashi Iwaida3cec32008-08-08 17:12:14 +02003753 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3754 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003755
Takashi Iwai763f3562005-06-03 11:25:34 +02003756 spin_lock_irq(&hdspm->lock);
3757 ucontrol->value.integer.value[0] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003758 (hdspm_read_pb_gain(hdspm, channel, channel)*64)/UNITY_GAIN;
Takashi Iwai763f3562005-06-03 11:25:34 +02003759 spin_unlock_irq(&hdspm->lock);
3760
Takashi Iwai763f3562005-06-03 11:25:34 +02003761 return 0;
3762}
3763
Takashi Iwai98274f02005-11-17 14:52:34 +01003764static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
3765 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003766{
Takashi Iwai98274f02005-11-17 14:52:34 +01003767 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003768 int change;
3769 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003770 int gain;
3771
3772 if (!snd_hdspm_use_is_exclusive(hdspm))
3773 return -EBUSY;
3774
3775 channel = ucontrol->id.index - 1;
3776
Takashi Iwaida3cec32008-08-08 17:12:14 +02003777 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3778 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003779
Adrian Knoth0dca1792011-01-26 19:32:14 +01003780 gain = ucontrol->value.integer.value[0]*UNITY_GAIN/64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003781
3782 spin_lock_irq(&hdspm->lock);
3783 change =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003784 gain != hdspm_read_pb_gain(hdspm, channel,
3785 channel);
Takashi Iwai763f3562005-06-03 11:25:34 +02003786 if (change)
Adrian Knoth0dca1792011-01-26 19:32:14 +01003787 hdspm_write_pb_gain(hdspm, channel, channel,
Takashi Iwai763f3562005-06-03 11:25:34 +02003788 gain);
3789 spin_unlock_irq(&hdspm->lock);
3790 return change;
3791}
3792
Adrian Knoth0dca1792011-01-26 19:32:14 +01003793#define HDSPM_SYNC_CHECK(xname, xindex) \
3794{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3795 .name = xname, \
3796 .private_value = xindex, \
3797 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3798 .info = snd_hdspm_info_sync_check, \
3799 .get = snd_hdspm_get_sync_check \
Takashi Iwai763f3562005-06-03 11:25:34 +02003800}
3801
Adrian Knoth34542212013-03-10 00:37:25 +01003802#define HDSPM_TCO_LOCK_CHECK(xname, xindex) \
3803{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3804 .name = xname, \
3805 .private_value = xindex, \
3806 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3807 .info = snd_hdspm_tco_info_lock_check, \
3808 .get = snd_hdspm_get_sync_check \
3809}
3810
3811
Adrian Knoth0dca1792011-01-26 19:32:14 +01003812
Takashi Iwai98274f02005-11-17 14:52:34 +01003813static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
3814 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003815{
Adrian Knoth38816542013-07-05 11:28:20 +02003816 static const char *const texts[] = { "No Lock", "Lock", "Sync", "N/A" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003817 ENUMERATED_CTL_INFO(uinfo, texts);
Takashi Iwai763f3562005-06-03 11:25:34 +02003818 return 0;
3819}
3820
Adrian Knoth34542212013-03-10 00:37:25 +01003821static int snd_hdspm_tco_info_lock_check(struct snd_kcontrol *kcontrol,
3822 struct snd_ctl_elem_info *uinfo)
3823{
Adrian Knoth38816542013-07-05 11:28:20 +02003824 static const char *const texts[] = { "No Lock", "Lock" };
Adrian Knoth34542212013-03-10 00:37:25 +01003825 ENUMERATED_CTL_INFO(uinfo, texts);
3826 return 0;
3827}
3828
Adrian Knoth0dca1792011-01-26 19:32:14 +01003829static int hdspm_wc_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003830{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003831 int status, status2;
3832
3833 switch (hdspm->io_type) {
3834 case AES32:
3835 status = hdspm_read(hdspm, HDSPM_statusRegister);
Andre Schramm56bde0f2013-01-09 14:40:18 +01003836 if (status & HDSPM_AES32_wcLock) {
3837 if (status & HDSPM_AES32_wcSync)
3838 return 2;
3839 else
3840 return 1;
3841 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02003842 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003843
3844 case MADI:
3845 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003846 if (status2 & HDSPM_wcLock) {
3847 if (status2 & HDSPM_wcSync)
3848 return 2;
3849 else
3850 return 1;
3851 }
3852 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003853
3854 case RayDAT:
3855 case AIO:
3856 status = hdspm_read(hdspm, HDSPM_statusRegister);
3857
3858 if (status & 0x2000000)
3859 return 2;
3860 else if (status & 0x1000000)
3861 return 1;
3862 return 0;
3863
Adrian Knoth0dca1792011-01-26 19:32:14 +01003864 case MADIface:
3865 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02003866 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003867
Takashi Iwai763f3562005-06-03 11:25:34 +02003868
Adrian Knoth0dca1792011-01-26 19:32:14 +01003869 return 3;
Takashi Iwai763f3562005-06-03 11:25:34 +02003870}
3871
3872
Adrian Knoth0dca1792011-01-26 19:32:14 +01003873static int hdspm_madi_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003874{
3875 int status = hdspm_read(hdspm, HDSPM_statusRegister);
3876 if (status & HDSPM_madiLock) {
3877 if (status & HDSPM_madiSync)
3878 return 2;
3879 else
3880 return 1;
3881 }
3882 return 0;
3883}
3884
Adrian Knoth0dca1792011-01-26 19:32:14 +01003885
3886static int hdspm_s1_sync_check(struct hdspm *hdspm, int idx)
3887{
3888 int status, lock, sync;
3889
3890 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3891
3892 lock = (status & (0x1<<idx)) ? 1 : 0;
3893 sync = (status & (0x100<<idx)) ? 1 : 0;
3894
3895 if (lock && sync)
3896 return 2;
3897 else if (lock)
3898 return 1;
3899 return 0;
3900}
3901
3902
3903static int hdspm_sync_in_sync_check(struct hdspm *hdspm)
3904{
3905 int status, lock = 0, sync = 0;
3906
3907 switch (hdspm->io_type) {
3908 case RayDAT:
3909 case AIO:
3910 status = hdspm_read(hdspm, HDSPM_RD_STATUS_3);
3911 lock = (status & 0x400) ? 1 : 0;
3912 sync = (status & 0x800) ? 1 : 0;
3913 break;
3914
3915 case MADI:
Adrian Knoth2e0452f2012-10-19 17:42:27 +02003916 status = hdspm_read(hdspm, HDSPM_statusRegister);
3917 lock = (status & HDSPM_syncInLock) ? 1 : 0;
3918 sync = (status & HDSPM_syncInSync) ? 1 : 0;
3919 break;
3920
Adrian Knoth0dca1792011-01-26 19:32:14 +01003921 case AES32:
3922 status = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth9a215f42012-10-19 17:42:28 +02003923 lock = (status & 0x100000) ? 1 : 0;
3924 sync = (status & 0x200000) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003925 break;
3926
3927 case MADIface:
3928 break;
3929 }
3930
3931 if (lock && sync)
3932 return 2;
3933 else if (lock)
3934 return 1;
3935
3936 return 0;
3937}
3938
3939static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx)
3940{
3941 int status2, lock, sync;
3942 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
3943
3944 lock = (status2 & (0x0080 >> idx)) ? 1 : 0;
3945 sync = (status2 & (0x8000 >> idx)) ? 1 : 0;
3946
3947 if (sync)
3948 return 2;
3949 else if (lock)
3950 return 1;
3951 return 0;
3952}
3953
Adrian Knoth34542212013-03-10 00:37:25 +01003954static int hdspm_tco_input_check(struct hdspm *hdspm, u32 mask)
3955{
3956 u32 status;
3957 status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
3958
3959 return (status & mask) ? 1 : 0;
3960}
3961
Adrian Knoth0dca1792011-01-26 19:32:14 +01003962
3963static int hdspm_tco_sync_check(struct hdspm *hdspm)
3964{
3965 int status;
3966
3967 if (hdspm->tco) {
3968 switch (hdspm->io_type) {
3969 case MADI:
Adrian Knothb0bf5502013-07-05 11:28:05 +02003970 status = hdspm_read(hdspm, HDSPM_statusRegister);
3971 if (status & HDSPM_tcoLockMadi) {
3972 if (status & HDSPM_tcoSync)
3973 return 2;
3974 else
3975 return 1;
3976 }
3977 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003978 case AES32:
3979 status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knothb0bf5502013-07-05 11:28:05 +02003980 if (status & HDSPM_tcoLockAes) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01003981 if (status & HDSPM_tcoSync)
3982 return 2;
3983 else
3984 return 1;
3985 }
3986 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003987 case RayDAT:
3988 case AIO:
3989 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3990
3991 if (status & 0x8000000)
3992 return 2; /* Sync */
3993 if (status & 0x4000000)
3994 return 1; /* Lock */
3995 return 0; /* No signal */
Adrian Knoth0dca1792011-01-26 19:32:14 +01003996
3997 default:
3998 break;
3999 }
4000 }
4001
4002 return 3; /* N/A */
4003}
4004
4005
4006static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
4007 struct snd_ctl_elem_value *ucontrol)
4008{
4009 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4010 int val = -1;
4011
4012 switch (hdspm->io_type) {
4013 case RayDAT:
4014 switch (kcontrol->private_value) {
4015 case 0: /* WC */
4016 val = hdspm_wc_sync_check(hdspm); break;
4017 case 7: /* TCO */
4018 val = hdspm_tco_sync_check(hdspm); break;
4019 case 8: /* SYNC IN */
4020 val = hdspm_sync_in_sync_check(hdspm); break;
4021 default:
Adrian Knothd1a3c982012-11-07 18:00:09 +01004022 val = hdspm_s1_sync_check(hdspm,
4023 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004024 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02004025 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004026
4027 case AIO:
4028 switch (kcontrol->private_value) {
4029 case 0: /* WC */
4030 val = hdspm_wc_sync_check(hdspm); break;
4031 case 4: /* TCO */
4032 val = hdspm_tco_sync_check(hdspm); break;
4033 case 5: /* SYNC IN */
4034 val = hdspm_sync_in_sync_check(hdspm); break;
4035 default:
Adrian Knoth1cb7dbf2013-07-05 11:28:03 +02004036 val = hdspm_s1_sync_check(hdspm,
4037 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004038 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02004039 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004040
4041 case MADI:
4042 switch (kcontrol->private_value) {
4043 case 0: /* WC */
4044 val = hdspm_wc_sync_check(hdspm); break;
4045 case 1: /* MADI */
4046 val = hdspm_madi_sync_check(hdspm); break;
4047 case 2: /* TCO */
4048 val = hdspm_tco_sync_check(hdspm); break;
4049 case 3: /* SYNC_IN */
4050 val = hdspm_sync_in_sync_check(hdspm); break;
4051 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02004052 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004053
4054 case MADIface:
4055 val = hdspm_madi_sync_check(hdspm); /* MADI */
4056 break;
4057
4058 case AES32:
4059 switch (kcontrol->private_value) {
4060 case 0: /* WC */
4061 val = hdspm_wc_sync_check(hdspm); break;
4062 case 9: /* TCO */
4063 val = hdspm_tco_sync_check(hdspm); break;
4064 case 10 /* SYNC IN */:
4065 val = hdspm_sync_in_sync_check(hdspm); break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01004066 default: /* AES1 to AES8 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01004067 val = hdspm_aes_sync_check(hdspm,
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01004068 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004069 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02004070 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004071
4072 }
4073
Adrian Knoth34542212013-03-10 00:37:25 +01004074 if (hdspm->tco) {
4075 switch (kcontrol->private_value) {
4076 case 11:
4077 /* Check TCO for lock state of its current input */
4078 val = hdspm_tco_input_check(hdspm, HDSPM_TCO1_TCO_lock);
4079 break;
4080 case 12:
4081 /* Check TCO for valid time code on LTC input. */
4082 val = hdspm_tco_input_check(hdspm,
4083 HDSPM_TCO1_LTC_Input_valid);
4084 break;
4085 default:
4086 break;
4087 }
4088 }
4089
Adrian Knoth0dca1792011-01-26 19:32:14 +01004090 if (-1 == val)
4091 val = 3;
4092
4093 ucontrol->value.enumerated.item[0] = val;
4094 return 0;
4095}
4096
4097
4098
Takashi Iwaiddcecf62014-11-10 17:24:26 +01004099/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01004100 * TCO controls
Takashi Iwaiddcecf62014-11-10 17:24:26 +01004101 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01004102static void hdspm_tco_write(struct hdspm *hdspm)
4103{
4104 unsigned int tc[4] = { 0, 0, 0, 0};
4105
4106 switch (hdspm->tco->input) {
4107 case 0:
4108 tc[2] |= HDSPM_TCO2_set_input_MSB;
4109 break;
4110 case 1:
4111 tc[2] |= HDSPM_TCO2_set_input_LSB;
4112 break;
4113 default:
4114 break;
4115 }
4116
4117 switch (hdspm->tco->framerate) {
4118 case 1:
4119 tc[1] |= HDSPM_TCO1_LTC_Format_LSB;
4120 break;
4121 case 2:
4122 tc[1] |= HDSPM_TCO1_LTC_Format_MSB;
4123 break;
4124 case 3:
4125 tc[1] |= HDSPM_TCO1_LTC_Format_MSB +
4126 HDSPM_TCO1_set_drop_frame_flag;
4127 break;
4128 case 4:
4129 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
4130 HDSPM_TCO1_LTC_Format_MSB;
4131 break;
4132 case 5:
4133 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
4134 HDSPM_TCO1_LTC_Format_MSB +
4135 HDSPM_TCO1_set_drop_frame_flag;
4136 break;
4137 default:
4138 break;
4139 }
4140
4141 switch (hdspm->tco->wordclock) {
4142 case 1:
4143 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_LSB;
4144 break;
4145 case 2:
4146 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_MSB;
4147 break;
4148 default:
4149 break;
4150 }
4151
4152 switch (hdspm->tco->samplerate) {
4153 case 1:
4154 tc[2] |= HDSPM_TCO2_set_freq;
4155 break;
4156 case 2:
4157 tc[2] |= HDSPM_TCO2_set_freq_from_app;
4158 break;
4159 default:
4160 break;
4161 }
4162
4163 switch (hdspm->tco->pull) {
4164 case 1:
4165 tc[2] |= HDSPM_TCO2_set_pull_up;
4166 break;
4167 case 2:
4168 tc[2] |= HDSPM_TCO2_set_pull_down;
4169 break;
4170 case 3:
4171 tc[2] |= HDSPM_TCO2_set_pull_up + HDSPM_TCO2_set_01_4;
4172 break;
4173 case 4:
4174 tc[2] |= HDSPM_TCO2_set_pull_down + HDSPM_TCO2_set_01_4;
4175 break;
4176 default:
4177 break;
4178 }
4179
4180 if (1 == hdspm->tco->term) {
4181 tc[2] |= HDSPM_TCO2_set_term_75R;
4182 }
4183
4184 hdspm_write(hdspm, HDSPM_WR_TCO, tc[0]);
4185 hdspm_write(hdspm, HDSPM_WR_TCO+4, tc[1]);
4186 hdspm_write(hdspm, HDSPM_WR_TCO+8, tc[2]);
4187 hdspm_write(hdspm, HDSPM_WR_TCO+12, tc[3]);
4188}
4189
4190
4191#define HDSPM_TCO_SAMPLE_RATE(xname, xindex) \
4192{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4193 .name = xname, \
4194 .index = xindex, \
4195 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4196 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4197 .info = snd_hdspm_info_tco_sample_rate, \
4198 .get = snd_hdspm_get_tco_sample_rate, \
4199 .put = snd_hdspm_put_tco_sample_rate \
4200}
4201
4202static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol,
4203 struct snd_ctl_elem_info *uinfo)
4204{
Martin Dausel69358fc2013-07-05 11:28:23 +02004205 /* TODO freq from app could be supported here, see tco->samplerate */
Adrian Knoth38816542013-07-05 11:28:20 +02004206 static const char *const texts[] = { "44.1 kHz", "48 kHz" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004207 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004208 return 0;
4209}
4210
4211static int snd_hdspm_get_tco_sample_rate(struct snd_kcontrol *kcontrol,
4212 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02004213{
Takashi Iwai98274f02005-11-17 14:52:34 +01004214 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02004215
Adrian Knoth0dca1792011-01-26 19:32:14 +01004216 ucontrol->value.enumerated.item[0] = hdspm->tco->samplerate;
4217
Takashi Iwai763f3562005-06-03 11:25:34 +02004218 return 0;
4219}
4220
Adrian Knoth0dca1792011-01-26 19:32:14 +01004221static int snd_hdspm_put_tco_sample_rate(struct snd_kcontrol *kcontrol,
4222 struct snd_ctl_elem_value *ucontrol)
Remy Bruno3cee5a62006-10-16 12:46:32 +02004223{
Adrian Knoth0dca1792011-01-26 19:32:14 +01004224 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4225
4226 if (hdspm->tco->samplerate != ucontrol->value.enumerated.item[0]) {
4227 hdspm->tco->samplerate = ucontrol->value.enumerated.item[0];
4228
4229 hdspm_tco_write(hdspm);
4230
4231 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004232 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01004233
Remy Bruno3cee5a62006-10-16 12:46:32 +02004234 return 0;
4235}
4236
Adrian Knoth0dca1792011-01-26 19:32:14 +01004237
4238#define HDSPM_TCO_PULL(xname, xindex) \
4239{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4240 .name = xname, \
4241 .index = xindex, \
4242 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4243 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4244 .info = snd_hdspm_info_tco_pull, \
4245 .get = snd_hdspm_get_tco_pull, \
4246 .put = snd_hdspm_put_tco_pull \
4247}
4248
4249static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol,
4250 struct snd_ctl_elem_info *uinfo)
4251{
Adrian Knoth38816542013-07-05 11:28:20 +02004252 static const char *const texts[] = { "0", "+ 0.1 %", "- 0.1 %",
4253 "+ 4 %", "- 4 %" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004254 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004255 return 0;
4256}
4257
4258static int snd_hdspm_get_tco_pull(struct snd_kcontrol *kcontrol,
4259 struct snd_ctl_elem_value *ucontrol)
4260{
4261 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4262
4263 ucontrol->value.enumerated.item[0] = hdspm->tco->pull;
4264
4265 return 0;
4266}
4267
4268static int snd_hdspm_put_tco_pull(struct snd_kcontrol *kcontrol,
4269 struct snd_ctl_elem_value *ucontrol)
4270{
4271 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4272
4273 if (hdspm->tco->pull != ucontrol->value.enumerated.item[0]) {
4274 hdspm->tco->pull = ucontrol->value.enumerated.item[0];
4275
4276 hdspm_tco_write(hdspm);
4277
4278 return 1;
4279 }
4280
4281 return 0;
4282}
4283
4284#define HDSPM_TCO_WCK_CONVERSION(xname, xindex) \
4285{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4286 .name = xname, \
4287 .index = xindex, \
4288 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4289 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4290 .info = snd_hdspm_info_tco_wck_conversion, \
4291 .get = snd_hdspm_get_tco_wck_conversion, \
4292 .put = snd_hdspm_put_tco_wck_conversion \
4293}
4294
4295static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4296 struct snd_ctl_elem_info *uinfo)
4297{
Adrian Knoth38816542013-07-05 11:28:20 +02004298 static const char *const texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004299 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004300 return 0;
4301}
4302
4303static int snd_hdspm_get_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4304 struct snd_ctl_elem_value *ucontrol)
4305{
4306 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4307
4308 ucontrol->value.enumerated.item[0] = hdspm->tco->wordclock;
4309
4310 return 0;
4311}
4312
4313static int snd_hdspm_put_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 if (hdspm->tco->wordclock != ucontrol->value.enumerated.item[0]) {
4319 hdspm->tco->wordclock = ucontrol->value.enumerated.item[0];
4320
4321 hdspm_tco_write(hdspm);
4322
4323 return 1;
4324 }
4325
4326 return 0;
4327}
4328
4329
4330#define HDSPM_TCO_FRAME_RATE(xname, xindex) \
4331{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4332 .name = xname, \
4333 .index = xindex, \
4334 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4335 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4336 .info = snd_hdspm_info_tco_frame_rate, \
4337 .get = snd_hdspm_get_tco_frame_rate, \
4338 .put = snd_hdspm_put_tco_frame_rate \
4339}
4340
4341static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol,
4342 struct snd_ctl_elem_info *uinfo)
4343{
Adrian Knoth38816542013-07-05 11:28:20 +02004344 static const char *const texts[] = { "24 fps", "25 fps", "29.97fps",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004345 "29.97 dfps", "30 fps", "30 dfps" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004346 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004347 return 0;
4348}
4349
4350static int snd_hdspm_get_tco_frame_rate(struct snd_kcontrol *kcontrol,
Remy Bruno3cee5a62006-10-16 12:46:32 +02004351 struct snd_ctl_elem_value *ucontrol)
4352{
Remy Bruno3cee5a62006-10-16 12:46:32 +02004353 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4354
Adrian Knoth0dca1792011-01-26 19:32:14 +01004355 ucontrol->value.enumerated.item[0] = hdspm->tco->framerate;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004356
Remy Bruno3cee5a62006-10-16 12:46:32 +02004357 return 0;
4358}
Takashi Iwai763f3562005-06-03 11:25:34 +02004359
Adrian Knoth0dca1792011-01-26 19:32:14 +01004360static int snd_hdspm_put_tco_frame_rate(struct snd_kcontrol *kcontrol,
4361 struct snd_ctl_elem_value *ucontrol)
4362{
4363 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4364
4365 if (hdspm->tco->framerate != ucontrol->value.enumerated.item[0]) {
4366 hdspm->tco->framerate = ucontrol->value.enumerated.item[0];
4367
4368 hdspm_tco_write(hdspm);
4369
4370 return 1;
4371 }
4372
4373 return 0;
4374}
4375
4376
4377#define HDSPM_TCO_SYNC_SOURCE(xname, xindex) \
4378{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4379 .name = xname, \
4380 .index = xindex, \
4381 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4382 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4383 .info = snd_hdspm_info_tco_sync_source, \
4384 .get = snd_hdspm_get_tco_sync_source, \
4385 .put = snd_hdspm_put_tco_sync_source \
4386}
4387
4388static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol,
4389 struct snd_ctl_elem_info *uinfo)
4390{
Adrian Knoth38816542013-07-05 11:28:20 +02004391 static const char *const texts[] = { "LTC", "Video", "WCK" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004392 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004393 return 0;
4394}
4395
4396static int snd_hdspm_get_tco_sync_source(struct snd_kcontrol *kcontrol,
4397 struct snd_ctl_elem_value *ucontrol)
4398{
4399 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4400
4401 ucontrol->value.enumerated.item[0] = hdspm->tco->input;
4402
4403 return 0;
4404}
4405
4406static int snd_hdspm_put_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 if (hdspm->tco->input != ucontrol->value.enumerated.item[0]) {
4412 hdspm->tco->input = ucontrol->value.enumerated.item[0];
4413
4414 hdspm_tco_write(hdspm);
4415
4416 return 1;
4417 }
4418
4419 return 0;
4420}
4421
4422
4423#define HDSPM_TCO_WORD_TERM(xname, xindex) \
4424{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4425 .name = xname, \
4426 .index = xindex, \
4427 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4428 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4429 .info = snd_hdspm_info_tco_word_term, \
4430 .get = snd_hdspm_get_tco_word_term, \
4431 .put = snd_hdspm_put_tco_word_term \
4432}
4433
4434static int snd_hdspm_info_tco_word_term(struct snd_kcontrol *kcontrol,
4435 struct snd_ctl_elem_info *uinfo)
4436{
4437 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
4438 uinfo->count = 1;
4439 uinfo->value.integer.min = 0;
4440 uinfo->value.integer.max = 1;
4441
4442 return 0;
4443}
4444
4445
4446static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol,
4447 struct snd_ctl_elem_value *ucontrol)
4448{
4449 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4450
Takashi Iwai537e4812016-02-29 14:25:16 +01004451 ucontrol->value.integer.value[0] = hdspm->tco->term;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004452
4453 return 0;
4454}
4455
4456
4457static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol,
4458 struct snd_ctl_elem_value *ucontrol)
4459{
4460 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4461
Takashi Iwai537e4812016-02-29 14:25:16 +01004462 if (hdspm->tco->term != ucontrol->value.integer.value[0]) {
4463 hdspm->tco->term = ucontrol->value.integer.value[0];
Adrian Knoth0dca1792011-01-26 19:32:14 +01004464
4465 hdspm_tco_write(hdspm);
4466
4467 return 1;
4468 }
4469
4470 return 0;
4471}
4472
4473
4474
Takashi Iwai763f3562005-06-03 11:25:34 +02004475
Takashi Iwaib4e5e702020-01-03 09:16:53 +01004476static const struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004477 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004478 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Takashi Iwai763f3562005-06-03 11:25:34 +02004479 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4480 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4481 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4482 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Adrian Knothb8812c52012-10-19 17:42:26 +02004483 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004484 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4485 HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
Adrian Knoth930f4ff2012-10-19 17:42:29 +02004486 HDSPM_SYNC_CHECK("TCO SyncCheck", 2),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004487 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
Adrian Knothc9e16682012-12-03 14:55:50 +01004488 HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
4489 HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
Adrian Knoth696be0f2013-03-10 00:37:23 +01004490 HDSPM_TOGGLE_SETTING("Disable 96K frames", HDSPM_SMUX),
Adrian Knothc9e16682012-12-03 14:55:50 +01004491 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
4492 HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
Adrian Knoth700d1ef2011-07-29 03:11:02 +02004493 HDSPM_INPUT_SELECT("Input Select", 0),
4494 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004495};
4496
4497
Takashi Iwaib4e5e702020-01-03 09:16:53 +01004498static const struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004499 HDSPM_MIXER("Mixer", 0),
4500 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4501 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4502 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4503 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4504 HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
Adrian Knothc9e16682012-12-03 14:55:50 +01004505 HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
4506 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
4507 HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
Adrian Knoth700d1ef2011-07-29 03:11:02 +02004508 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004509};
4510
Takashi Iwaib4e5e702020-01-03 09:16:53 +01004511static const struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004512 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004513 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004514 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4515 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004516 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004517 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004518 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4519 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4520 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4521 HDSPM_SYNC_CHECK("ADAT SyncCheck", 3),
4522 HDSPM_SYNC_CHECK("TCO SyncCheck", 4),
4523 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 5),
4524 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4525 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4526 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4527 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT Frequency", 3),
4528 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 4),
Adrian Knothfb0f1212013-07-05 11:27:58 +02004529 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5),
Adrian Knoth42f4c122013-07-05 11:28:01 +02004530 HDSPM_CONTROL_TRISTATE("S/PDIF Input", HDSPM_c0_Input0),
Adrian Knothfb0f1212013-07-05 11:27:58 +02004531 HDSPM_TOGGLE_SETTING("S/PDIF Out Optical", HDSPM_c0_Spdif_Opt),
4532 HDSPM_TOGGLE_SETTING("S/PDIF Out Professional", HDSPM_c0_Pro),
4533 HDSPM_TOGGLE_SETTING("ADAT internal (AEB/TEB)", HDSPM_c0_AEB1),
4534 HDSPM_TOGGLE_SETTING("XLR Breakout Cable", HDSPM_c0_Sym6db),
Adrian Knoth42f4c122013-07-05 11:28:01 +02004535 HDSPM_TOGGLE_SETTING("Single Speed WordClock Out", HDSPM_c0_Wck48),
4536 HDSPM_CONTROL_TRISTATE("Input Level", HDSPM_c0_AD_GAIN0),
4537 HDSPM_CONTROL_TRISTATE("Output Level", HDSPM_c0_DA_GAIN0),
4538 HDSPM_CONTROL_TRISTATE("Phones Level", HDSPM_c0_PH_GAIN0)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004539
4540 /*
4541 HDSPM_INPUT_SELECT("Input Select", 0),
4542 HDSPM_SPDIF_OPTICAL("SPDIF Out Optical", 0),
4543 HDSPM_PROFESSIONAL("SPDIF Out Professional", 0);
4544 HDSPM_SPDIF_IN("SPDIF In", 0);
4545 HDSPM_BREAKOUT_CABLE("Breakout Cable", 0);
4546 HDSPM_INPUT_LEVEL("Input Level", 0);
4547 HDSPM_OUTPUT_LEVEL("Output Level", 0);
4548 HDSPM_PHONES("Phones", 0);
4549 */
4550};
4551
Takashi Iwaib4e5e702020-01-03 09:16:53 +01004552static const struct snd_kcontrol_new snd_hdspm_controls_raydat[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004553 HDSPM_MIXER("Mixer", 0),
4554 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4555 HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0),
4556 HDSPM_PREF_SYNC_REF("Pref Sync Ref", 0),
4557 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4558 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4559 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4560 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4561 HDSPM_SYNC_CHECK("ADAT1 SyncCheck", 3),
4562 HDSPM_SYNC_CHECK("ADAT2 SyncCheck", 4),
4563 HDSPM_SYNC_CHECK("ADAT3 SyncCheck", 5),
4564 HDSPM_SYNC_CHECK("ADAT4 SyncCheck", 6),
4565 HDSPM_SYNC_CHECK("TCO SyncCheck", 7),
4566 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 8),
4567 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4568 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4569 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4570 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT1 Frequency", 3),
4571 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT2 Frequency", 4),
4572 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT3 Frequency", 5),
4573 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT4 Frequency", 6),
4574 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 7),
Adrian Knoth11a5cd32013-07-05 11:27:57 +02004575 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8),
4576 HDSPM_TOGGLE_SETTING("S/PDIF Out Professional", HDSPM_c0_Pro),
4577 HDSPM_TOGGLE_SETTING("Single Speed WordClock Out", HDSPM_c0_Wck48)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004578};
4579
Takashi Iwaib4e5e702020-01-03 09:16:53 +01004580static const struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004581 HDSPM_MIXER("Mixer", 0),
4582 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4583 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4584 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4585 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4586 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Adrian Knoth2d63ec32013-07-05 11:28:18 +02004587 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 11),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004588 HDSPM_SYNC_CHECK("WC Sync Check", 0),
4589 HDSPM_SYNC_CHECK("AES1 Sync Check", 1),
4590 HDSPM_SYNC_CHECK("AES2 Sync Check", 2),
4591 HDSPM_SYNC_CHECK("AES3 Sync Check", 3),
4592 HDSPM_SYNC_CHECK("AES4 Sync Check", 4),
4593 HDSPM_SYNC_CHECK("AES5 Sync Check", 5),
4594 HDSPM_SYNC_CHECK("AES6 Sync Check", 6),
4595 HDSPM_SYNC_CHECK("AES7 Sync Check", 7),
4596 HDSPM_SYNC_CHECK("AES8 Sync Check", 8),
4597 HDSPM_SYNC_CHECK("TCO Sync Check", 9),
4598 HDSPM_SYNC_CHECK("SYNC IN Sync Check", 10),
4599 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4600 HDSPM_AUTOSYNC_SAMPLE_RATE("AES1 Frequency", 1),
4601 HDSPM_AUTOSYNC_SAMPLE_RATE("AES2 Frequency", 2),
4602 HDSPM_AUTOSYNC_SAMPLE_RATE("AES3 Frequency", 3),
4603 HDSPM_AUTOSYNC_SAMPLE_RATE("AES4 Frequency", 4),
4604 HDSPM_AUTOSYNC_SAMPLE_RATE("AES5 Frequency", 5),
4605 HDSPM_AUTOSYNC_SAMPLE_RATE("AES6 Frequency", 6),
4606 HDSPM_AUTOSYNC_SAMPLE_RATE("AES7 Frequency", 7),
4607 HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8),
4608 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9),
4609 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10),
Adrian Knothc9e16682012-12-03 14:55:50 +01004610 HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
4611 HDSPM_TOGGLE_SETTING("Emphasis", HDSPM_Emphasis),
4612 HDSPM_TOGGLE_SETTING("Non Audio", HDSPM_Dolby),
4613 HDSPM_TOGGLE_SETTING("Professional", HDSPM_Professional),
4614 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004615 HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
4616 HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
4617};
4618
Adrian Knoth0dca1792011-01-26 19:32:14 +01004619
4620
4621/* Control elements for the optional TCO module */
Takashi Iwaib4e5e702020-01-03 09:16:53 +01004622static const struct snd_kcontrol_new snd_hdspm_controls_tco[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004623 HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0),
4624 HDSPM_TCO_PULL("TCO Pull", 0),
4625 HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0),
4626 HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0),
4627 HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0),
Adrian Knotha8176502013-03-10 00:37:27 +01004628 HDSPM_TCO_WORD_TERM("TCO Word Term", 0),
4629 HDSPM_TCO_LOCK_CHECK("TCO Input Check", 11),
4630 HDSPM_TCO_LOCK_CHECK("TCO LTC Valid", 12),
4631 HDSPM_TCO_LTC_FRAMES("TCO Detected Frame Rate", 0),
4632 HDSPM_TCO_VIDEO_INPUT_FORMAT("Video Input Format", 0)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004633};
4634
4635
Takashi Iwai98274f02005-11-17 14:52:34 +01004636static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
Takashi Iwai763f3562005-06-03 11:25:34 +02004637
4638
Takashi Iwai98274f02005-11-17 14:52:34 +01004639static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004640{
4641 int i;
4642
Adrian Knoth0dca1792011-01-26 19:32:14 +01004643 for (i = hdspm->ds_out_channels; i < hdspm->ss_out_channels; ++i) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004644 if (hdspm->system_sample_rate > 48000) {
4645 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004646 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
4647 SNDRV_CTL_ELEM_ACCESS_READ |
4648 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004649 } else {
4650 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004651 SNDRV_CTL_ELEM_ACCESS_READWRITE |
4652 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004653 }
4654 snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
Adrian Knoth0dca1792011-01-26 19:32:14 +01004655 SNDRV_CTL_EVENT_MASK_INFO,
4656 &hdspm->playback_mixer_ctls[i]->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02004657 }
4658
4659 return 0;
4660}
4661
4662
Adrian Knoth0dca1792011-01-26 19:32:14 +01004663static int snd_hdspm_create_controls(struct snd_card *card,
4664 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004665{
4666 unsigned int idx, limit;
4667 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01004668 struct snd_kcontrol *kctl;
Takashi Iwaib4e5e702020-01-03 09:16:53 +01004669 const struct snd_kcontrol_new *list = NULL;
Takashi Iwai763f3562005-06-03 11:25:34 +02004670
Adrian Knoth0dca1792011-01-26 19:32:14 +01004671 switch (hdspm->io_type) {
4672 case MADI:
4673 list = snd_hdspm_controls_madi;
4674 limit = ARRAY_SIZE(snd_hdspm_controls_madi);
4675 break;
4676 case MADIface:
4677 list = snd_hdspm_controls_madiface;
4678 limit = ARRAY_SIZE(snd_hdspm_controls_madiface);
4679 break;
4680 case AIO:
4681 list = snd_hdspm_controls_aio;
4682 limit = ARRAY_SIZE(snd_hdspm_controls_aio);
4683 break;
4684 case RayDAT:
4685 list = snd_hdspm_controls_raydat;
4686 limit = ARRAY_SIZE(snd_hdspm_controls_raydat);
4687 break;
4688 case AES32:
4689 list = snd_hdspm_controls_aes32;
4690 limit = ARRAY_SIZE(snd_hdspm_controls_aes32);
4691 break;
4692 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004693
Markus Elfringda2ea372017-08-12 17:07:09 +02004694 if (list) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004695 for (idx = 0; idx < limit; idx++) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004696 err = snd_ctl_add(card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004697 snd_ctl_new1(&list[idx], hdspm));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004698 if (err < 0)
4699 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004700 }
4701 }
4702
Takashi Iwai763f3562005-06-03 11:25:34 +02004703
Adrian Knoth0dca1792011-01-26 19:32:14 +01004704 /* create simple 1:1 playback mixer controls */
Takashi Iwai763f3562005-06-03 11:25:34 +02004705 snd_hdspm_playback_mixer.name = "Chn";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004706 if (hdspm->system_sample_rate >= 128000) {
4707 limit = hdspm->qs_out_channels;
4708 } else if (hdspm->system_sample_rate >= 64000) {
4709 limit = hdspm->ds_out_channels;
4710 } else {
4711 limit = hdspm->ss_out_channels;
4712 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004713 for (idx = 0; idx < limit; ++idx) {
4714 snd_hdspm_playback_mixer.index = idx + 1;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004715 kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm);
4716 err = snd_ctl_add(card, kctl);
4717 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004718 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004719 hdspm->playback_mixer_ctls[idx] = kctl;
4720 }
4721
Adrian Knoth0dca1792011-01-26 19:32:14 +01004722
4723 if (hdspm->tco) {
4724 /* add tco control elements */
4725 list = snd_hdspm_controls_tco;
4726 limit = ARRAY_SIZE(snd_hdspm_controls_tco);
4727 for (idx = 0; idx < limit; idx++) {
4728 err = snd_ctl_add(card,
4729 snd_ctl_new1(&list[idx], hdspm));
4730 if (err < 0)
4731 return err;
4732 }
4733 }
4734
Takashi Iwai763f3562005-06-03 11:25:34 +02004735 return 0;
4736}
4737
4738/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01004739 /proc interface
Takashi Iwai763f3562005-06-03 11:25:34 +02004740 ------------------------------------------------------------*/
4741
4742static void
Adrian Knoth57601072013-07-05 11:28:04 +02004743snd_hdspm_proc_read_tco(struct snd_info_entry *entry,
4744 struct snd_info_buffer *buffer)
Takashi Iwai763f3562005-06-03 11:25:34 +02004745{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004746 struct hdspm *hdspm = entry->private_data;
Adrian Knoth57601072013-07-05 11:28:04 +02004747 unsigned int status, control;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004748 int a, ltc, frames, seconds, minutes, hours;
4749 unsigned int period;
4750 u64 freq_const = 0;
4751 u32 rate;
4752
Adrian Knoth57601072013-07-05 11:28:04 +02004753 snd_iprintf(buffer, "--- TCO ---\n");
4754
Takashi Iwai763f3562005-06-03 11:25:34 +02004755 status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004756 control = hdspm->control_register;
Takashi Iwai763f3562005-06-03 11:25:34 +02004757
Adrian Knoth0dca1792011-01-26 19:32:14 +01004758
Adrian Knoth0dca1792011-01-26 19:32:14 +01004759 if (status & HDSPM_tco_detect) {
4760 snd_iprintf(buffer, "TCO module detected.\n");
4761 a = hdspm_read(hdspm, HDSPM_RD_TCO+4);
4762 if (a & HDSPM_TCO1_LTC_Input_valid) {
4763 snd_iprintf(buffer, " LTC valid, ");
4764 switch (a & (HDSPM_TCO1_LTC_Format_LSB |
4765 HDSPM_TCO1_LTC_Format_MSB)) {
4766 case 0:
4767 snd_iprintf(buffer, "24 fps, ");
4768 break;
4769 case HDSPM_TCO1_LTC_Format_LSB:
4770 snd_iprintf(buffer, "25 fps, ");
4771 break;
4772 case HDSPM_TCO1_LTC_Format_MSB:
4773 snd_iprintf(buffer, "29.97 fps, ");
4774 break;
4775 default:
4776 snd_iprintf(buffer, "30 fps, ");
4777 break;
4778 }
4779 if (a & HDSPM_TCO1_set_drop_frame_flag) {
4780 snd_iprintf(buffer, "drop frame\n");
4781 } else {
4782 snd_iprintf(buffer, "full frame\n");
4783 }
4784 } else {
4785 snd_iprintf(buffer, " no LTC\n");
4786 }
4787 if (a & HDSPM_TCO1_Video_Input_Format_NTSC) {
4788 snd_iprintf(buffer, " Video: NTSC\n");
4789 } else if (a & HDSPM_TCO1_Video_Input_Format_PAL) {
4790 snd_iprintf(buffer, " Video: PAL\n");
4791 } else {
4792 snd_iprintf(buffer, " No video\n");
4793 }
4794 if (a & HDSPM_TCO1_TCO_lock) {
4795 snd_iprintf(buffer, " Sync: lock\n");
4796 } else {
4797 snd_iprintf(buffer, " Sync: no lock\n");
4798 }
4799
4800 switch (hdspm->io_type) {
4801 case MADI:
4802 case AES32:
4803 freq_const = 110069313433624ULL;
4804 break;
4805 case RayDAT:
4806 case AIO:
4807 freq_const = 104857600000000ULL;
4808 break;
4809 case MADIface:
4810 break; /* no TCO possible */
4811 }
4812
4813 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
4814 snd_iprintf(buffer, " period: %u\n", period);
4815
4816
4817 /* rate = freq_const/period; */
4818 rate = div_u64(freq_const, period);
4819
4820 if (control & HDSPM_QuadSpeed) {
4821 rate *= 4;
4822 } else if (control & HDSPM_DoubleSpeed) {
4823 rate *= 2;
4824 }
4825
4826 snd_iprintf(buffer, " Frequency: %u Hz\n",
4827 (unsigned int) rate);
4828
4829 ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
4830 frames = ltc & 0xF;
4831 ltc >>= 4;
4832 frames += (ltc & 0x3) * 10;
4833 ltc >>= 4;
4834 seconds = ltc & 0xF;
4835 ltc >>= 4;
4836 seconds += (ltc & 0x7) * 10;
4837 ltc >>= 4;
4838 minutes = ltc & 0xF;
4839 ltc >>= 4;
4840 minutes += (ltc & 0x7) * 10;
4841 ltc >>= 4;
4842 hours = ltc & 0xF;
4843 ltc >>= 4;
4844 hours += (ltc & 0x3) * 10;
4845 snd_iprintf(buffer,
4846 " LTC In: %02d:%02d:%02d:%02d\n",
4847 hours, minutes, seconds, frames);
4848
4849 } else {
4850 snd_iprintf(buffer, "No TCO module detected.\n");
4851 }
Adrian Knoth57601072013-07-05 11:28:04 +02004852}
4853
4854static void
4855snd_hdspm_proc_read_madi(struct snd_info_entry *entry,
4856 struct snd_info_buffer *buffer)
4857{
4858 struct hdspm *hdspm = entry->private_data;
Sudip Mukherjeedf57de12014-10-29 20:09:45 +05304859 unsigned int status, status2;
Adrian Knoth57601072013-07-05 11:28:04 +02004860
4861 char *pref_sync_ref;
4862 char *autosync_ref;
4863 char *system_clock_mode;
Adrian Knoth57601072013-07-05 11:28:04 +02004864 int x, x2;
4865
4866 status = hdspm_read(hdspm, HDSPM_statusRegister);
4867 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth57601072013-07-05 11:28:04 +02004868
4869 snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
4870 hdspm->card_name, hdspm->card->number + 1,
4871 hdspm->firmware_rev,
4872 (status2 & HDSPM_version0) |
4873 (status2 & HDSPM_version1) | (status2 &
4874 HDSPM_version2));
4875
4876 snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n",
4877 (hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF,
4878 hdspm->serial);
4879
4880 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
4881 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
4882
4883 snd_iprintf(buffer, "--- System ---\n");
4884
4885 snd_iprintf(buffer,
4886 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4887 status & HDSPM_audioIRQPending,
4888 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4889 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4890 hdspm->irq_count);
4891 snd_iprintf(buffer,
4892 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4893 "estimated= %ld (bytes)\n",
4894 ((status & HDSPM_BufferID) ? 1 : 0),
4895 (status & HDSPM_BufferPositionMask),
4896 (status & HDSPM_BufferPositionMask) %
4897 (2 * (int)hdspm->period_bytes),
4898 ((status & HDSPM_BufferPositionMask) - 64) %
4899 (2 * (int)hdspm->period_bytes),
4900 (long) hdspm_hw_pointer(hdspm) * 4);
4901
4902 snd_iprintf(buffer,
4903 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4904 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4905 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4906 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4907 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
4908 snd_iprintf(buffer,
4909 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4910 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4911 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4912 snd_iprintf(buffer,
4913 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4914 "status2=0x%x\n",
4915 hdspm->control_register, hdspm->control2_register,
4916 status, status2);
4917
Takashi Iwai763f3562005-06-03 11:25:34 +02004918
4919 snd_iprintf(buffer, "--- Settings ---\n");
4920
Adrian Knoth7cb155f2011-08-15 00:22:53 +02004921 x = hdspm_get_latency(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02004922
4923 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004924 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4925 x, (unsigned long) hdspm->period_bytes);
Takashi Iwai763f3562005-06-03 11:25:34 +02004926
Adrian Knoth0dca1792011-01-26 19:32:14 +01004927 snd_iprintf(buffer, "Line out: %s\n",
4928 (hdspm->control_register & HDSPM_LineOut) ? "on " : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004929
Takashi Iwai763f3562005-06-03 11:25:34 +02004930 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004931 "ClearTrackMarker = %s, Transmit in %s Channel Mode, "
4932 "Auto Input %s\n",
4933 (hdspm->control_register & HDSPM_clr_tms) ? "on" : "off",
4934 (hdspm->control_register & HDSPM_TX_64ch) ? "64" : "56",
4935 (hdspm->control_register & HDSPM_AutoInp) ? "on" : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004936
Adrian Knoth0dca1792011-01-26 19:32:14 +01004937
Remy Bruno3cee5a62006-10-16 12:46:32 +02004938 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
Adrian Knoth0dca1792011-01-26 19:32:14 +01004939 system_clock_mode = "AutoSync";
Remy Bruno3cee5a62006-10-16 12:46:32 +02004940 else
Takashi Iwai763f3562005-06-03 11:25:34 +02004941 system_clock_mode = "Master";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004942 snd_iprintf(buffer, "AutoSync Reference: %s\n", system_clock_mode);
Takashi Iwai763f3562005-06-03 11:25:34 +02004943
4944 switch (hdspm_pref_sync_ref(hdspm)) {
4945 case HDSPM_SYNC_FROM_WORD:
4946 pref_sync_ref = "Word Clock";
4947 break;
4948 case HDSPM_SYNC_FROM_MADI:
4949 pref_sync_ref = "MADI Sync";
4950 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004951 case HDSPM_SYNC_FROM_TCO:
4952 pref_sync_ref = "TCO";
4953 break;
4954 case HDSPM_SYNC_FROM_SYNC_IN:
4955 pref_sync_ref = "Sync In";
4956 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004957 default:
4958 pref_sync_ref = "XXXX Clock";
4959 break;
4960 }
4961 snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004962 pref_sync_ref);
Takashi Iwai763f3562005-06-03 11:25:34 +02004963
4964 snd_iprintf(buffer, "System Clock Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004965 hdspm->system_sample_rate);
Takashi Iwai763f3562005-06-03 11:25:34 +02004966
4967
4968 snd_iprintf(buffer, "--- Status:\n");
4969
4970 x = status & HDSPM_madiSync;
4971 x2 = status2 & HDSPM_wcSync;
4972
4973 snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004974 (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
4975 "NoLock",
4976 (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
4977 "NoLock");
Takashi Iwai763f3562005-06-03 11:25:34 +02004978
4979 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004980 case HDSPM_AUTOSYNC_FROM_SYNC_IN:
4981 autosync_ref = "Sync In";
4982 break;
4983 case HDSPM_AUTOSYNC_FROM_TCO:
4984 autosync_ref = "TCO";
4985 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004986 case HDSPM_AUTOSYNC_FROM_WORD:
4987 autosync_ref = "Word Clock";
4988 break;
4989 case HDSPM_AUTOSYNC_FROM_MADI:
4990 autosync_ref = "MADI Sync";
4991 break;
4992 case HDSPM_AUTOSYNC_FROM_NONE:
4993 autosync_ref = "Input not valid";
4994 break;
4995 default:
4996 autosync_ref = "---";
4997 break;
4998 }
4999 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005000 "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
5001 autosync_ref, hdspm_external_sample_rate(hdspm),
5002 (status & HDSPM_madiFreqMask) >> 22,
5003 (status2 & HDSPM_wcFreqMask) >> 5);
Takashi Iwai763f3562005-06-03 11:25:34 +02005004
5005 snd_iprintf(buffer, "Input: %s, Mode=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01005006 (status & HDSPM_AB_int) ? "Coax" : "Optical",
5007 (status & HDSPM_RX_64ch) ? "64 channels" :
5008 "56 channels");
Takashi Iwai763f3562005-06-03 11:25:34 +02005009
Adrian Knoth57601072013-07-05 11:28:04 +02005010 /* call readout function for TCO specific status */
5011 snd_hdspm_proc_read_tco(entry, buffer);
5012
Takashi Iwai763f3562005-06-03 11:25:34 +02005013 snd_iprintf(buffer, "\n");
5014}
5015
Remy Bruno3cee5a62006-10-16 12:46:32 +02005016static void
5017snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
5018 struct snd_info_buffer *buffer)
5019{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005020 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005021 unsigned int status;
5022 unsigned int status2;
5023 unsigned int timecode;
Andre Schramm56bde0f2013-01-09 14:40:18 +01005024 unsigned int wcLock, wcSync;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005025 int pref_syncref;
5026 char *autosync_ref;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005027 int x;
5028
5029 status = hdspm_read(hdspm, HDSPM_statusRegister);
5030 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
5031 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
5032
5033 snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
5034 hdspm->card_name, hdspm->card->number + 1,
5035 hdspm->firmware_rev);
5036
5037 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
5038 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
5039
5040 snd_iprintf(buffer, "--- System ---\n");
5041
5042 snd_iprintf(buffer,
5043 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
5044 status & HDSPM_audioIRQPending,
5045 (status & HDSPM_midi0IRQPending) ? 1 : 0,
5046 (status & HDSPM_midi1IRQPending) ? 1 : 0,
5047 hdspm->irq_count);
5048 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005049 "HW pointer: id = %d, rawptr = %d (%d->%d) "
5050 "estimated= %ld (bytes)\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005051 ((status & HDSPM_BufferID) ? 1 : 0),
5052 (status & HDSPM_BufferPositionMask),
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005053 (status & HDSPM_BufferPositionMask) %
5054 (2 * (int)hdspm->period_bytes),
5055 ((status & HDSPM_BufferPositionMask) - 64) %
5056 (2 * (int)hdspm->period_bytes),
Remy Bruno3cee5a62006-10-16 12:46:32 +02005057 (long) hdspm_hw_pointer(hdspm) * 4);
5058
5059 snd_iprintf(buffer,
5060 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
5061 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
5062 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
5063 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
5064 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
5065 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005066 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
5067 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
5068 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
5069 snd_iprintf(buffer,
5070 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
5071 "status2=0x%x\n",
5072 hdspm->control_register, hdspm->control2_register,
5073 status, status2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02005074
5075 snd_iprintf(buffer, "--- Settings ---\n");
5076
Adrian Knoth7cb155f2011-08-15 00:22:53 +02005077 x = hdspm_get_latency(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02005078
5079 snd_iprintf(buffer,
5080 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
5081 x, (unsigned long) hdspm->period_bytes);
5082
Adrian Knoth0dca1792011-01-26 19:32:14 +01005083 snd_iprintf(buffer, "Line out: %s\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005084 (hdspm->
Adrian Knoth0dca1792011-01-26 19:32:14 +01005085 control_register & HDSPM_LineOut) ? "on " : "off");
Remy Bruno3cee5a62006-10-16 12:46:32 +02005086
5087 snd_iprintf(buffer,
5088 "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
5089 (hdspm->
5090 control_register & HDSPM_clr_tms) ? "on" : "off",
5091 (hdspm->
5092 control_register & HDSPM_Emphasis) ? "on" : "off",
5093 (hdspm->
5094 control_register & HDSPM_Dolby) ? "on" : "off");
5095
Remy Bruno3cee5a62006-10-16 12:46:32 +02005096
5097 pref_syncref = hdspm_pref_sync_ref(hdspm);
5098 if (pref_syncref == 0)
5099 snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
5100 else
5101 snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
5102 pref_syncref);
5103
5104 snd_iprintf(buffer, "System Clock Frequency: %d\n",
5105 hdspm->system_sample_rate);
5106
5107 snd_iprintf(buffer, "Double speed: %s\n",
5108 hdspm->control_register & HDSPM_DS_DoubleWire?
5109 "Double wire" : "Single wire");
5110 snd_iprintf(buffer, "Quad speed: %s\n",
5111 hdspm->control_register & HDSPM_QS_DoubleWire?
5112 "Double wire" :
5113 hdspm->control_register & HDSPM_QS_QuadWire?
5114 "Quad wire" : "Single wire");
5115
5116 snd_iprintf(buffer, "--- Status:\n");
5117
Andre Schramm56bde0f2013-01-09 14:40:18 +01005118 wcLock = status & HDSPM_AES32_wcLock;
5119 wcSync = wcLock && (status & HDSPM_AES32_wcSync);
5120
Remy Bruno3cee5a62006-10-16 12:46:32 +02005121 snd_iprintf(buffer, "Word: %s Frequency: %d\n",
Andre Schramm56bde0f2013-01-09 14:40:18 +01005122 (wcLock) ? (wcSync ? "Sync " : "Lock ") : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005123 HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02005124
5125 for (x = 0; x < 8; x++) {
5126 snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005127 x+1,
5128 (status2 & (HDSPM_LockAES >> x)) ?
Adrian Knoth0dca1792011-01-26 19:32:14 +01005129 "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005130 HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02005131 }
5132
5133 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005134 case HDSPM_AES32_AUTOSYNC_FROM_NONE:
5135 autosync_ref = "None"; break;
5136 case HDSPM_AES32_AUTOSYNC_FROM_WORD:
5137 autosync_ref = "Word Clock"; break;
5138 case HDSPM_AES32_AUTOSYNC_FROM_AES1:
5139 autosync_ref = "AES1"; break;
5140 case HDSPM_AES32_AUTOSYNC_FROM_AES2:
5141 autosync_ref = "AES2"; break;
5142 case HDSPM_AES32_AUTOSYNC_FROM_AES3:
5143 autosync_ref = "AES3"; break;
5144 case HDSPM_AES32_AUTOSYNC_FROM_AES4:
5145 autosync_ref = "AES4"; break;
5146 case HDSPM_AES32_AUTOSYNC_FROM_AES5:
5147 autosync_ref = "AES5"; break;
5148 case HDSPM_AES32_AUTOSYNC_FROM_AES6:
5149 autosync_ref = "AES6"; break;
5150 case HDSPM_AES32_AUTOSYNC_FROM_AES7:
5151 autosync_ref = "AES7"; break;
5152 case HDSPM_AES32_AUTOSYNC_FROM_AES8:
5153 autosync_ref = "AES8"; break;
Adrian Knoth194062d2013-07-05 11:28:16 +02005154 case HDSPM_AES32_AUTOSYNC_FROM_TCO:
5155 autosync_ref = "TCO"; break;
5156 case HDSPM_AES32_AUTOSYNC_FROM_SYNC_IN:
5157 autosync_ref = "Sync In"; break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005158 default:
5159 autosync_ref = "---"; break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005160 }
5161 snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
5162
Adrian Knoth194062d2013-07-05 11:28:16 +02005163 /* call readout function for TCO specific status */
5164 snd_hdspm_proc_read_tco(entry, buffer);
5165
Remy Bruno3cee5a62006-10-16 12:46:32 +02005166 snd_iprintf(buffer, "\n");
5167}
5168
Adrian Knoth0dca1792011-01-26 19:32:14 +01005169static void
5170snd_hdspm_proc_read_raydat(struct snd_info_entry *entry,
5171 struct snd_info_buffer *buffer)
5172{
5173 struct hdspm *hdspm = entry->private_data;
Sudip Mukherjeedf57de12014-10-29 20:09:45 +05305174 unsigned int status1, status2, status3, i;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005175 unsigned int lock, sync;
5176
5177 status1 = hdspm_read(hdspm, HDSPM_RD_STATUS_1); /* s1 */
5178 status2 = hdspm_read(hdspm, HDSPM_RD_STATUS_2); /* freq */
5179 status3 = hdspm_read(hdspm, HDSPM_RD_STATUS_3); /* s2 */
5180
Adrian Knoth0dca1792011-01-26 19:32:14 +01005181 snd_iprintf(buffer, "STATUS1: 0x%08x\n", status1);
5182 snd_iprintf(buffer, "STATUS2: 0x%08x\n", status2);
5183 snd_iprintf(buffer, "STATUS3: 0x%08x\n", status3);
5184
5185
5186 snd_iprintf(buffer, "\n*** CLOCK MODE\n\n");
5187
5188 snd_iprintf(buffer, "Clock mode : %s\n",
5189 (hdspm_system_clock_mode(hdspm) == 0) ? "master" : "slave");
5190 snd_iprintf(buffer, "System frequency: %d Hz\n",
5191 hdspm_get_system_sample_rate(hdspm));
5192
5193 snd_iprintf(buffer, "\n*** INPUT STATUS\n\n");
5194
5195 lock = 0x1;
5196 sync = 0x100;
5197
5198 for (i = 0; i < 8; i++) {
5199 snd_iprintf(buffer, "s1_input %d: Lock %d, Sync %d, Freq %s\n",
5200 i,
5201 (status1 & lock) ? 1 : 0,
5202 (status1 & sync) ? 1 : 0,
5203 texts_freq[(status2 >> (i * 4)) & 0xF]);
5204
5205 lock = lock<<1;
5206 sync = sync<<1;
5207 }
5208
5209 snd_iprintf(buffer, "WC input: Lock %d, Sync %d, Freq %s\n",
5210 (status1 & 0x1000000) ? 1 : 0,
5211 (status1 & 0x2000000) ? 1 : 0,
5212 texts_freq[(status1 >> 16) & 0xF]);
5213
5214 snd_iprintf(buffer, "TCO input: Lock %d, Sync %d, Freq %s\n",
5215 (status1 & 0x4000000) ? 1 : 0,
5216 (status1 & 0x8000000) ? 1 : 0,
5217 texts_freq[(status1 >> 20) & 0xF]);
5218
5219 snd_iprintf(buffer, "SYNC IN: Lock %d, Sync %d, Freq %s\n",
5220 (status3 & 0x400) ? 1 : 0,
5221 (status3 & 0x800) ? 1 : 0,
5222 texts_freq[(status2 >> 12) & 0xF]);
5223
5224}
5225
Remy Bruno3cee5a62006-10-16 12:46:32 +02005226#ifdef CONFIG_SND_DEBUG
5227static void
Adrian Knoth0dca1792011-01-26 19:32:14 +01005228snd_hdspm_proc_read_debug(struct snd_info_entry *entry,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005229 struct snd_info_buffer *buffer)
5230{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005231 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005232
5233 int j,i;
5234
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005235 for (i = 0; i < 256 /* 1024*64 */; i += j) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02005236 snd_iprintf(buffer, "0x%08X: ", i);
5237 for (j = 0; j < 16; j += 4)
5238 snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
5239 snd_iprintf(buffer, "\n");
5240 }
5241}
5242#endif
5243
5244
Adrian Knoth0dca1792011-01-26 19:32:14 +01005245static void snd_hdspm_proc_ports_in(struct snd_info_entry *entry,
5246 struct snd_info_buffer *buffer)
5247{
5248 struct hdspm *hdspm = entry->private_data;
5249 int i;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005250
Adrian Knoth0dca1792011-01-26 19:32:14 +01005251 snd_iprintf(buffer, "# generated by hdspm\n");
5252
5253 for (i = 0; i < hdspm->max_channels_in; i++) {
5254 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_in[i]);
5255 }
5256}
5257
5258static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry,
5259 struct snd_info_buffer *buffer)
5260{
5261 struct hdspm *hdspm = entry->private_data;
5262 int i;
5263
5264 snd_iprintf(buffer, "# generated by hdspm\n");
5265
5266 for (i = 0; i < hdspm->max_channels_out; i++) {
5267 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_out[i]);
5268 }
5269}
5270
5271
Bill Pembertone23e7a12012-12-06 12:35:10 -05005272static void snd_hdspm_proc_init(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005273{
Takashi Iwai47f27692019-02-04 16:01:39 +01005274 void (*read)(struct snd_info_entry *, struct snd_info_buffer *) = NULL;
Takashi Iwai763f3562005-06-03 11:25:34 +02005275
Takashi Iwai47f27692019-02-04 16:01:39 +01005276 switch (hdspm->io_type) {
5277 case AES32:
5278 read = snd_hdspm_proc_read_aes32;
5279 break;
5280 case MADI:
5281 read = snd_hdspm_proc_read_madi;
5282 break;
5283 case MADIface:
5284 /* read = snd_hdspm_proc_read_madiface; */
5285 break;
5286 case RayDAT:
5287 read = snd_hdspm_proc_read_raydat;
5288 break;
5289 case AIO:
5290 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005291 }
5292
Takashi Iwai47f27692019-02-04 16:01:39 +01005293 snd_card_ro_proc_new(hdspm->card, "hdspm", hdspm, read);
5294 snd_card_ro_proc_new(hdspm->card, "ports.in", hdspm,
5295 snd_hdspm_proc_ports_in);
5296 snd_card_ro_proc_new(hdspm->card, "ports.out", hdspm,
5297 snd_hdspm_proc_ports_out);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005298
Remy Bruno3cee5a62006-10-16 12:46:32 +02005299#ifdef CONFIG_SND_DEBUG
5300 /* debug file to read all hdspm registers */
Takashi Iwai47f27692019-02-04 16:01:39 +01005301 snd_card_ro_proc_new(hdspm->card, "debug", hdspm,
5302 snd_hdspm_proc_read_debug);
Remy Bruno3cee5a62006-10-16 12:46:32 +02005303#endif
Takashi Iwai763f3562005-06-03 11:25:34 +02005304}
5305
5306/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005307 hdspm intitialize
Takashi Iwai763f3562005-06-03 11:25:34 +02005308 ------------------------------------------------------------*/
5309
Takashi Iwai98274f02005-11-17 14:52:34 +01005310static int snd_hdspm_set_defaults(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005311{
Takashi Iwai763f3562005-06-03 11:25:34 +02005312 /* ASSUMPTION: hdspm->lock is either held, or there is no need to
Joe Perches561de312007-12-18 13:13:47 +01005313 hold it (e.g. during module initialization).
Adrian Knoth0dca1792011-01-26 19:32:14 +01005314 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005315
5316 /* set defaults: */
5317
Adrian Knoth0dca1792011-01-26 19:32:14 +01005318 hdspm->settings_register = 0;
5319
5320 switch (hdspm->io_type) {
5321 case MADI:
5322 case MADIface:
5323 hdspm->control_register =
5324 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5325 break;
5326
5327 case RayDAT:
5328 case AIO:
5329 hdspm->settings_register = 0x1 + 0x1000;
5330 /* Magic values are: LAT_0, LAT_2, Master, freq1, tx64ch, inp_0,
5331 * line_out */
5332 hdspm->control_register =
5333 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5334 break;
5335
5336 case AES32:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005337 hdspm->control_register =
Adrian Knothe71b95a2013-07-05 11:28:06 +02005338 HDSPM_ClockModeMaster | /* Master Clock Mode on */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005339 hdspm_encode_latency(7) | /* latency max=8192samples */
Remy Bruno3cee5a62006-10-16 12:46:32 +02005340 HDSPM_SyncRef0 | /* AES1 is syncclock */
5341 HDSPM_LineOut | /* Analog output in */
5342 HDSPM_Professional; /* Professional mode */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005343 break;
5344 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005345
5346 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5347
Adrian Knoth0dca1792011-01-26 19:32:14 +01005348 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005349 /* No control2 register for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005350#ifdef SNDRV_BIG_ENDIAN
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005351 hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
Takashi Iwai763f3562005-06-03 11:25:34 +02005352#else
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005353 hdspm->control2_register = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005354#endif
5355
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005356 hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
5357 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005358 hdspm_compute_period_size(hdspm);
5359
5360 /* silence everything */
5361
5362 all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
5363
Adrian Knothb2ed6322013-07-05 11:27:54 +02005364 if (hdspm_is_raydat_or_aio(hdspm))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005365 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
Takashi Iwai763f3562005-06-03 11:25:34 +02005366
5367 /* set a default rate so that the channel map is set up. */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005368 hdspm_set_rate(hdspm, 48000, 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02005369
5370 return 0;
5371}
5372
5373
5374/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005375 interrupt
Takashi Iwai763f3562005-06-03 11:25:34 +02005376 ------------------------------------------------------------*/
5377
David Howells7d12e782006-10-05 14:55:46 +01005378static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02005379{
Takashi Iwai98274f02005-11-17 14:52:34 +01005380 struct hdspm *hdspm = (struct hdspm *) dev_id;
Takashi Iwai763f3562005-06-03 11:25:34 +02005381 unsigned int status;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005382 int i, audio, midi, schedule = 0;
5383 /* cycles_t now; */
Takashi Iwai763f3562005-06-03 11:25:34 +02005384
5385 status = hdspm_read(hdspm, HDSPM_statusRegister);
5386
5387 audio = status & HDSPM_audioIRQPending;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005388 midi = status & (HDSPM_midi0IRQPending | HDSPM_midi1IRQPending |
5389 HDSPM_midi2IRQPending | HDSPM_midi3IRQPending);
Takashi Iwai763f3562005-06-03 11:25:34 +02005390
Adrian Knoth0dca1792011-01-26 19:32:14 +01005391 /* now = get_cycles(); */
Takashi Iwaiddcecf62014-11-10 17:24:26 +01005392 /*
Adrian Knoth0dca1792011-01-26 19:32:14 +01005393 * LAT_2..LAT_0 period counter (win) counter (mac)
5394 * 6 4096 ~256053425 ~514672358
5395 * 5 2048 ~128024983 ~257373821
5396 * 4 1024 ~64023706 ~128718089
5397 * 3 512 ~32005945 ~64385999
5398 * 2 256 ~16003039 ~32260176
5399 * 1 128 ~7998738 ~16194507
5400 * 0 64 ~3998231 ~8191558
Takashi Iwaiddcecf62014-11-10 17:24:26 +01005401 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005402 /*
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005403 dev_info(hdspm->card->dev, "snd_hdspm_interrupt %llu @ %llx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01005404 now-hdspm->last_interrupt, status & 0xFFC0);
5405 hdspm->last_interrupt = now;
5406 */
5407
5408 if (!audio && !midi)
Takashi Iwai763f3562005-06-03 11:25:34 +02005409 return IRQ_NONE;
5410
5411 hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
5412 hdspm->irq_count++;
5413
Takashi Iwai763f3562005-06-03 11:25:34 +02005414
5415 if (audio) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005416 if (hdspm->capture_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005417 snd_pcm_period_elapsed(hdspm->capture_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005418
5419 if (hdspm->playback_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005420 snd_pcm_period_elapsed(hdspm->playback_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005421 }
5422
Adrian Knoth0dca1792011-01-26 19:32:14 +01005423 if (midi) {
5424 i = 0;
5425 while (i < hdspm->midiPorts) {
5426 if ((hdspm_read(hdspm,
5427 hdspm->midi[i].statusIn) & 0xff) &&
5428 (status & hdspm->midi[i].irq)) {
5429 /* we disable interrupts for this input until
5430 * processing is done
5431 */
5432 hdspm->control_register &= ~hdspm->midi[i].ie;
5433 hdspm_write(hdspm, HDSPM_controlRegister,
5434 hdspm->control_register);
5435 hdspm->midi[i].pending = 1;
5436 schedule = 1;
5437 }
5438
5439 i++;
5440 }
5441
5442 if (schedule)
Takashi Iwaia2e527c2020-09-03 12:41:27 +02005443 queue_work(system_highpri_wq, &hdspm->midi_work);
Takashi Iwai763f3562005-06-03 11:25:34 +02005444 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005445
Takashi Iwai763f3562005-06-03 11:25:34 +02005446 return IRQ_HANDLED;
5447}
5448
5449/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005450 pcm interface
Takashi Iwai763f3562005-06-03 11:25:34 +02005451 ------------------------------------------------------------*/
5452
5453
Adrian Knoth0dca1792011-01-26 19:32:14 +01005454static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream
5455 *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005456{
Takashi Iwai98274f02005-11-17 14:52:34 +01005457 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005458 return hdspm_hw_pointer(hdspm);
5459}
5460
Takashi Iwai763f3562005-06-03 11:25:34 +02005461
Takashi Iwai98274f02005-11-17 14:52:34 +01005462static int snd_hdspm_reset(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005463{
Takashi Iwai98274f02005-11-17 14:52:34 +01005464 struct snd_pcm_runtime *runtime = substream->runtime;
5465 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5466 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005467
5468 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5469 other = hdspm->capture_substream;
5470 else
5471 other = hdspm->playback_substream;
5472
5473 if (hdspm->running)
5474 runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
5475 else
5476 runtime->status->hw_ptr = 0;
5477 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005478 struct snd_pcm_substream *s;
5479 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01005480 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005481 if (s == other) {
5482 oruntime->status->hw_ptr =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005483 runtime->status->hw_ptr;
Takashi Iwai763f3562005-06-03 11:25:34 +02005484 break;
5485 }
5486 }
5487 }
5488 return 0;
5489}
5490
Takashi Iwai98274f02005-11-17 14:52:34 +01005491static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
5492 struct snd_pcm_hw_params *params)
Takashi Iwai763f3562005-06-03 11:25:34 +02005493{
Takashi Iwai98274f02005-11-17 14:52:34 +01005494 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005495 int err;
5496 int i;
5497 pid_t this_pid;
5498 pid_t other_pid;
Takashi Iwai763f3562005-06-03 11:25:34 +02005499
5500 spin_lock_irq(&hdspm->lock);
5501
5502 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5503 this_pid = hdspm->playback_pid;
5504 other_pid = hdspm->capture_pid;
5505 } else {
5506 this_pid = hdspm->capture_pid;
5507 other_pid = hdspm->playback_pid;
5508 }
5509
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005510 if (other_pid > 0 && this_pid != other_pid) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005511
5512 /* The other stream is open, and not by the same
5513 task as this one. Make sure that the parameters
5514 that matter are the same.
Adrian Knoth0dca1792011-01-26 19:32:14 +01005515 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005516
5517 if (params_rate(params) != hdspm->system_sample_rate) {
5518 spin_unlock_irq(&hdspm->lock);
5519 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005520 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005521 return -EBUSY;
5522 }
5523
5524 if (params_period_size(params) != hdspm->period_bytes / 4) {
5525 spin_unlock_irq(&hdspm->lock);
5526 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005527 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005528 return -EBUSY;
5529 }
5530
5531 }
5532 /* We're fine. */
5533 spin_unlock_irq(&hdspm->lock);
5534
5535 /* how to make sure that the rate matches an externally-set one ? */
5536
5537 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005538 err = hdspm_set_rate(hdspm, params_rate(params), 0);
5539 if (err < 0) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005540 dev_info(hdspm->card->dev, "err on hdspm_set_rate: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005541 spin_unlock_irq(&hdspm->lock);
5542 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005543 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005544 return err;
5545 }
5546 spin_unlock_irq(&hdspm->lock);
5547
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005548 err = hdspm_set_interrupt_interval(hdspm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005549 params_period_size(params));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005550 if (err < 0) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005551 dev_info(hdspm->card->dev,
5552 "err on hdspm_set_interrupt_interval: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005553 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005554 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005555 return err;
5556 }
5557
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005558 /* Memory allocation, takashi's method, dont know if we should
5559 * spinlock
5560 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005561 /* malloc all buffer even if not enabled to get sure */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005562 /* Update for MADI rev 204: we need to allocate for all channels,
5563 * otherwise it doesn't work at 96kHz */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005564
Takashi Iwai763f3562005-06-03 11:25:34 +02005565 err =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005566 snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
5567 if (err < 0) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005568 dev_info(hdspm->card->dev,
5569 "err on snd_pcm_lib_malloc_pages: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005570 return err;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005571 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005572
Takashi Iwai763f3562005-06-03 11:25:34 +02005573 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5574
Philippe Bekaerte4e07c62019-05-23 23:56:49 +02005575 for (i = 0; i < params_channels(params); ++i) {
5576 int c = hdspm->channel_map_out[i];
Takashi Iwai763f3562005-06-03 11:25:34 +02005577
Philippe Bekaerte4e07c62019-05-23 23:56:49 +02005578 if (c < 0)
5579 continue; /* just make sure */
5580 hdspm_set_channel_dma_addr(hdspm, substream,
5581 HDSPM_pageAddressBufferOut,
5582 c);
5583 snd_hdspm_enable_out(hdspm, c, 1);
5584 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005585
5586 hdspm->playback_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005587 (unsigned char *) substream->runtime->dma_area;
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005588 dev_dbg(hdspm->card->dev,
5589 "Allocated sample buffer for playback at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005590 hdspm->playback_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005591 } else {
Philippe Bekaerte4e07c62019-05-23 23:56:49 +02005592 for (i = 0; i < params_channels(params); ++i) {
5593 int c = hdspm->channel_map_in[i];
Takashi Iwai763f3562005-06-03 11:25:34 +02005594
Philippe Bekaerte4e07c62019-05-23 23:56:49 +02005595 if (c < 0)
5596 continue;
5597 hdspm_set_channel_dma_addr(hdspm, substream,
5598 HDSPM_pageAddressBufferIn,
5599 c);
5600 snd_hdspm_enable_in(hdspm, c, 1);
5601 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005602
5603 hdspm->capture_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005604 (unsigned char *) substream->runtime->dma_area;
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005605 dev_dbg(hdspm->card->dev,
5606 "Allocated sample buffer for capture at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005607 hdspm->capture_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005608 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005609
Remy Bruno3cee5a62006-10-16 12:46:32 +02005610 /*
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005611 dev_dbg(hdspm->card->dev,
5612 "Allocated sample buffer for %s at 0x%08X\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005613 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5614 "playback" : "capture",
Takashi Iwai77a23f22008-08-21 13:00:13 +02005615 snd_pcm_sgbuf_get_addr(substream, 0));
Adrian Knoth0dca1792011-01-26 19:32:14 +01005616 */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005617 /*
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005618 dev_dbg(hdspm->card->dev,
5619 "set_hwparams: %s %d Hz, %d channels, bs = %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01005620 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5621 "playback" : "capture",
5622 params_rate(params), params_channels(params),
5623 params_buffer_size(params));
5624 */
5625
5626
Adrian Knoth3ac9b0a2013-07-05 11:28:13 +02005627 /* For AES cards, the float format bit is the same as the
5628 * preferred sync reference. Since we don't want to break
5629 * sync settings, we have to skip the remaining part of this
5630 * function.
5631 */
5632 if (hdspm->io_type == AES32) {
5633 return 0;
5634 }
5635
5636
Adrian Knoth0dca1792011-01-26 19:32:14 +01005637 /* Switch to native float format if requested */
5638 if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) {
5639 if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT))
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005640 dev_info(hdspm->card->dev,
5641 "Switching to native 32bit LE float format.\n");
Adrian Knoth0dca1792011-01-26 19:32:14 +01005642
5643 hdspm->control_register |= HDSPe_FLOAT_FORMAT;
5644 } else if (SNDRV_PCM_FORMAT_S32_LE == params_format(params)) {
5645 if (hdspm->control_register & HDSPe_FLOAT_FORMAT)
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005646 dev_info(hdspm->card->dev,
5647 "Switching to native 32bit LE integer format.\n");
Adrian Knoth0dca1792011-01-26 19:32:14 +01005648
5649 hdspm->control_register &= ~HDSPe_FLOAT_FORMAT;
5650 }
5651 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5652
Takashi Iwai763f3562005-06-03 11:25:34 +02005653 return 0;
5654}
5655
Takashi Iwai98274f02005-11-17 14:52:34 +01005656static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005657{
5658 int i;
Takashi Iwai98274f02005-11-17 14:52:34 +01005659 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005660
5661 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
Philippe Bekaerte4e07c62019-05-23 23:56:49 +02005662 /* Just disable all channels. The saving when disabling a */
5663 /* smaller set is not worth the trouble. */
5664 for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005665 snd_hdspm_enable_out(hdspm, i, 0);
5666
5667 hdspm->playback_buffer = NULL;
5668 } else {
Philippe Bekaerte4e07c62019-05-23 23:56:49 +02005669 for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005670 snd_hdspm_enable_in(hdspm, i, 0);
5671
5672 hdspm->capture_buffer = NULL;
Takashi Iwai763f3562005-06-03 11:25:34 +02005673 }
5674
5675 snd_pcm_lib_free_pages(substream);
5676
5677 return 0;
5678}
5679
Adrian Knoth0dca1792011-01-26 19:32:14 +01005680
Takashi Iwai98274f02005-11-17 14:52:34 +01005681static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005682 struct snd_pcm_channel_info *info)
Takashi Iwai763f3562005-06-03 11:25:34 +02005683{
Takashi Iwai98274f02005-11-17 14:52:34 +01005684 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai10513142018-04-24 08:03:14 +02005685 unsigned int channel = info->channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02005686
Adrian Knoth0dca1792011-01-26 19:32:14 +01005687 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
Takashi Iwai10513142018-04-24 08:03:14 +02005688 if (snd_BUG_ON(channel >= hdspm->max_channels_out)) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005689 dev_info(hdspm->card->dev,
5690 "snd_hdspm_channel_info: output channel out of range (%d)\n",
Takashi Iwai10513142018-04-24 08:03:14 +02005691 channel);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005692 return -EINVAL;
5693 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005694
Takashi Iwai10513142018-04-24 08:03:14 +02005695 channel = array_index_nospec(channel, hdspm->max_channels_out);
5696 if (hdspm->channel_map_out[channel] < 0) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005697 dev_info(hdspm->card->dev,
5698 "snd_hdspm_channel_info: output channel %d mapped out\n",
Takashi Iwai10513142018-04-24 08:03:14 +02005699 channel);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005700 return -EINVAL;
5701 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005702
Takashi Iwai10513142018-04-24 08:03:14 +02005703 info->offset = hdspm->channel_map_out[channel] *
Adrian Knoth0dca1792011-01-26 19:32:14 +01005704 HDSPM_CHANNEL_BUFFER_BYTES;
5705 } else {
Takashi Iwai10513142018-04-24 08:03:14 +02005706 if (snd_BUG_ON(channel >= hdspm->max_channels_in)) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005707 dev_info(hdspm->card->dev,
5708 "snd_hdspm_channel_info: input channel out of range (%d)\n",
Takashi Iwai10513142018-04-24 08:03:14 +02005709 channel);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005710 return -EINVAL;
5711 }
5712
Takashi Iwai10513142018-04-24 08:03:14 +02005713 channel = array_index_nospec(channel, hdspm->max_channels_in);
5714 if (hdspm->channel_map_in[channel] < 0) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005715 dev_info(hdspm->card->dev,
5716 "snd_hdspm_channel_info: input channel %d mapped out\n",
Takashi Iwai10513142018-04-24 08:03:14 +02005717 channel);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005718 return -EINVAL;
5719 }
5720
Takashi Iwai10513142018-04-24 08:03:14 +02005721 info->offset = hdspm->channel_map_in[channel] *
Adrian Knoth0dca1792011-01-26 19:32:14 +01005722 HDSPM_CHANNEL_BUFFER_BYTES;
5723 }
5724
Takashi Iwai763f3562005-06-03 11:25:34 +02005725 info->first = 0;
5726 info->step = 32;
5727 return 0;
5728}
5729
Adrian Knoth0dca1792011-01-26 19:32:14 +01005730
Takashi Iwai98274f02005-11-17 14:52:34 +01005731static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005732 unsigned int cmd, void *arg)
Takashi Iwai763f3562005-06-03 11:25:34 +02005733{
5734 switch (cmd) {
5735 case SNDRV_PCM_IOCTL1_RESET:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005736 return snd_hdspm_reset(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005737
5738 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Adrian Knoth0dca1792011-01-26 19:32:14 +01005739 {
5740 struct snd_pcm_channel_info *info = arg;
5741 return snd_hdspm_channel_info(substream, info);
5742 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005743 default:
5744 break;
5745 }
5746
5747 return snd_pcm_lib_ioctl(substream, cmd, arg);
5748}
5749
Takashi Iwai98274f02005-11-17 14:52:34 +01005750static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
Takashi Iwai763f3562005-06-03 11:25:34 +02005751{
Takashi Iwai98274f02005-11-17 14:52:34 +01005752 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5753 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005754 int running;
5755
5756 spin_lock(&hdspm->lock);
5757 running = hdspm->running;
5758 switch (cmd) {
5759 case SNDRV_PCM_TRIGGER_START:
5760 running |= 1 << substream->stream;
5761 break;
5762 case SNDRV_PCM_TRIGGER_STOP:
5763 running &= ~(1 << substream->stream);
5764 break;
5765 default:
5766 snd_BUG();
5767 spin_unlock(&hdspm->lock);
5768 return -EINVAL;
5769 }
5770 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5771 other = hdspm->capture_substream;
5772 else
5773 other = hdspm->playback_substream;
5774
5775 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005776 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01005777 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005778 if (s == other) {
5779 snd_pcm_trigger_done(s, substream);
5780 if (cmd == SNDRV_PCM_TRIGGER_START)
5781 running |= 1 << s->stream;
5782 else
5783 running &= ~(1 << s->stream);
5784 goto _ok;
5785 }
5786 }
5787 if (cmd == SNDRV_PCM_TRIGGER_START) {
5788 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005789 && substream->stream ==
5790 SNDRV_PCM_STREAM_CAPTURE)
Takashi Iwai763f3562005-06-03 11:25:34 +02005791 hdspm_silence_playback(hdspm);
5792 } else {
5793 if (running &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01005794 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Takashi Iwai763f3562005-06-03 11:25:34 +02005795 hdspm_silence_playback(hdspm);
5796 }
5797 } else {
5798 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
5799 hdspm_silence_playback(hdspm);
5800 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005801_ok:
Takashi Iwai763f3562005-06-03 11:25:34 +02005802 snd_pcm_trigger_done(substream, substream);
5803 if (!hdspm->running && running)
5804 hdspm_start_audio(hdspm);
5805 else if (hdspm->running && !running)
5806 hdspm_stop_audio(hdspm);
5807 hdspm->running = running;
5808 spin_unlock(&hdspm->lock);
5809
5810 return 0;
5811}
5812
Takashi Iwai98274f02005-11-17 14:52:34 +01005813static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005814{
5815 return 0;
5816}
5817
Takashi Iwaic1c39812020-01-03 09:16:17 +01005818static const struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005819 .info = (SNDRV_PCM_INFO_MMAP |
5820 SNDRV_PCM_INFO_MMAP_VALID |
5821 SNDRV_PCM_INFO_NONINTERLEAVED |
5822 SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
5823 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5824 .rates = (SNDRV_PCM_RATE_32000 |
5825 SNDRV_PCM_RATE_44100 |
5826 SNDRV_PCM_RATE_48000 |
5827 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005828 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5829 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ),
Takashi Iwai763f3562005-06-03 11:25:34 +02005830 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005831 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005832 .channels_min = 1,
5833 .channels_max = HDSPM_MAX_CHANNELS,
5834 .buffer_bytes_max =
5835 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
Adrian Knoth1b6fa102011-08-15 00:22:51 +02005836 .period_bytes_min = (32 * 4),
Takashi Iwai52e6fb42011-08-15 10:40:59 +02005837 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005838 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005839 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005840 .fifo_size = 0
5841};
5842
Takashi Iwaic1c39812020-01-03 09:16:17 +01005843static const struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005844 .info = (SNDRV_PCM_INFO_MMAP |
5845 SNDRV_PCM_INFO_MMAP_VALID |
5846 SNDRV_PCM_INFO_NONINTERLEAVED |
5847 SNDRV_PCM_INFO_SYNC_START),
5848 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5849 .rates = (SNDRV_PCM_RATE_32000 |
5850 SNDRV_PCM_RATE_44100 |
5851 SNDRV_PCM_RATE_48000 |
5852 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005853 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5854 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
Takashi Iwai763f3562005-06-03 11:25:34 +02005855 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005856 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005857 .channels_min = 1,
5858 .channels_max = HDSPM_MAX_CHANNELS,
5859 .buffer_bytes_max =
5860 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
Adrian Knoth1b6fa102011-08-15 00:22:51 +02005861 .period_bytes_min = (32 * 4),
Takashi Iwai52e6fb42011-08-15 10:40:59 +02005862 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005863 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005864 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005865 .fifo_size = 0
5866};
5867
Adrian Knoth0dca1792011-01-26 19:32:14 +01005868static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
5869 struct snd_pcm_hw_rule *rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005870{
Takashi Iwai98274f02005-11-17 14:52:34 +01005871 struct hdspm *hdspm = rule->private;
5872 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005873 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005874 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005875 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5876
Adrian Knoth0dca1792011-01-26 19:32:14 +01005877 if (r->min > 96000 && r->max <= 192000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005878 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005879 .min = hdspm->qs_in_channels,
5880 .max = hdspm->qs_in_channels,
5881 .integer = 1,
5882 };
5883 return snd_interval_refine(c, &t);
5884 } else if (r->min > 48000 && r->max <= 96000) {
5885 struct snd_interval t = {
5886 .min = hdspm->ds_in_channels,
5887 .max = hdspm->ds_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005888 .integer = 1,
5889 };
5890 return snd_interval_refine(c, &t);
5891 } else if (r->max < 64000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005892 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005893 .min = hdspm->ss_in_channels,
5894 .max = hdspm->ss_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005895 .integer = 1,
5896 };
5897 return snd_interval_refine(c, &t);
5898 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005899
Takashi Iwai763f3562005-06-03 11:25:34 +02005900 return 0;
5901}
5902
Adrian Knoth0dca1792011-01-26 19:32:14 +01005903static int snd_hdspm_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
Takashi Iwai98274f02005-11-17 14:52:34 +01005904 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005905{
Takashi Iwai98274f02005-11-17 14:52:34 +01005906 struct hdspm *hdspm = rule->private;
5907 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005908 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005909 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005910 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5911
Adrian Knoth0dca1792011-01-26 19:32:14 +01005912 if (r->min > 96000 && r->max <= 192000) {
5913 struct snd_interval t = {
5914 .min = hdspm->qs_out_channels,
5915 .max = hdspm->qs_out_channels,
5916 .integer = 1,
5917 };
5918 return snd_interval_refine(c, &t);
5919 } else if (r->min > 48000 && r->max <= 96000) {
5920 struct snd_interval t = {
5921 .min = hdspm->ds_out_channels,
5922 .max = hdspm->ds_out_channels,
5923 .integer = 1,
5924 };
5925 return snd_interval_refine(c, &t);
5926 } else if (r->max < 64000) {
5927 struct snd_interval t = {
5928 .min = hdspm->ss_out_channels,
5929 .max = hdspm->ss_out_channels,
5930 .integer = 1,
5931 };
5932 return snd_interval_refine(c, &t);
5933 } else {
5934 }
5935 return 0;
5936}
5937
5938static int snd_hdspm_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
5939 struct snd_pcm_hw_rule * rule)
5940{
5941 struct hdspm *hdspm = rule->private;
5942 struct snd_interval *c =
5943 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5944 struct snd_interval *r =
5945 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5946
5947 if (c->min >= hdspm->ss_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005948 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005949 .min = 32000,
5950 .max = 48000,
5951 .integer = 1,
5952 };
5953 return snd_interval_refine(r, &t);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005954 } else if (c->max <= hdspm->qs_in_channels) {
5955 struct snd_interval t = {
5956 .min = 128000,
5957 .max = 192000,
5958 .integer = 1,
5959 };
5960 return snd_interval_refine(r, &t);
5961 } else if (c->max <= hdspm->ds_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005962 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005963 .min = 64000,
5964 .max = 96000,
5965 .integer = 1,
5966 };
Takashi Iwai763f3562005-06-03 11:25:34 +02005967 return snd_interval_refine(r, &t);
5968 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005969
5970 return 0;
5971}
5972static int snd_hdspm_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
5973 struct snd_pcm_hw_rule *rule)
5974{
5975 struct hdspm *hdspm = rule->private;
5976 struct snd_interval *c =
5977 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5978 struct snd_interval *r =
5979 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5980
5981 if (c->min >= hdspm->ss_out_channels) {
5982 struct snd_interval t = {
5983 .min = 32000,
5984 .max = 48000,
5985 .integer = 1,
5986 };
5987 return snd_interval_refine(r, &t);
5988 } else if (c->max <= hdspm->qs_out_channels) {
5989 struct snd_interval t = {
5990 .min = 128000,
5991 .max = 192000,
5992 .integer = 1,
5993 };
5994 return snd_interval_refine(r, &t);
5995 } else if (c->max <= hdspm->ds_out_channels) {
5996 struct snd_interval t = {
5997 .min = 64000,
5998 .max = 96000,
5999 .integer = 1,
6000 };
6001 return snd_interval_refine(r, &t);
6002 }
6003
Takashi Iwai763f3562005-06-03 11:25:34 +02006004 return 0;
6005}
6006
Adrian Knoth0dca1792011-01-26 19:32:14 +01006007static int snd_hdspm_hw_rule_in_channels(struct snd_pcm_hw_params *params,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006008 struct snd_pcm_hw_rule *rule)
6009{
6010 unsigned int list[3];
6011 struct hdspm *hdspm = rule->private;
6012 struct snd_interval *c = hw_param_interval(params,
6013 SNDRV_PCM_HW_PARAM_CHANNELS);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006014
6015 list[0] = hdspm->qs_in_channels;
6016 list[1] = hdspm->ds_in_channels;
6017 list[2] = hdspm->ss_in_channels;
6018 return snd_interval_list(c, 3, list, 0);
6019}
6020
6021static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params,
6022 struct snd_pcm_hw_rule *rule)
6023{
6024 unsigned int list[3];
6025 struct hdspm *hdspm = rule->private;
6026 struct snd_interval *c = hw_param_interval(params,
6027 SNDRV_PCM_HW_PARAM_CHANNELS);
6028
6029 list[0] = hdspm->qs_out_channels;
6030 list[1] = hdspm->ds_out_channels;
6031 list[2] = hdspm->ss_out_channels;
6032 return snd_interval_list(c, 3, list, 0);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006033}
6034
6035
Takashi Iwaibdf84db2017-06-07 14:22:35 +02006036static const unsigned int hdspm_aes32_sample_rates[] = {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006037 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000
6038};
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006039
Takashi Iwaibdf84db2017-06-07 14:22:35 +02006040static const struct snd_pcm_hw_constraint_list
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006041hdspm_hw_constraints_aes32_sample_rates = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006042 .count = ARRAY_SIZE(hdspm_aes32_sample_rates),
6043 .list = hdspm_aes32_sample_rates,
6044 .mask = 0
6045};
6046
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006047static int snd_hdspm_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02006048{
Takashi Iwai98274f02005-11-17 14:52:34 +01006049 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
6050 struct snd_pcm_runtime *runtime = substream->runtime;
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006051 bool playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
Takashi Iwai763f3562005-06-03 11:25:34 +02006052
Takashi Iwai763f3562005-06-03 11:25:34 +02006053 spin_lock_irq(&hdspm->lock);
Takashi Iwai763f3562005-06-03 11:25:34 +02006054 snd_pcm_set_sync(substream);
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006055 runtime->hw = (playback) ? snd_hdspm_playback_subinfo :
6056 snd_hdspm_capture_subinfo;
Takashi Iwai763f3562005-06-03 11:25:34 +02006057
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006058 if (playback) {
Markus Elfringda2ea372017-08-12 17:07:09 +02006059 if (!hdspm->capture_substream)
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006060 hdspm_stop_audio(hdspm);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006061
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006062 hdspm->playback_pid = current->pid;
6063 hdspm->playback_substream = substream;
6064 } else {
Markus Elfringda2ea372017-08-12 17:07:09 +02006065 if (!hdspm->playback_substream)
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006066 hdspm_stop_audio(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006067
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006068 hdspm->capture_pid = current->pid;
6069 hdspm->capture_substream = substream;
6070 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006071
6072 spin_unlock_irq(&hdspm->lock);
6073
6074 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Takashi Iwaid8776812011-08-15 10:45:42 +02006075 snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02006076
Adrian Knoth0dca1792011-01-26 19:32:14 +01006077 switch (hdspm->io_type) {
6078 case AIO:
6079 case RayDAT:
Takashi Iwaid8776812011-08-15 10:45:42 +02006080 snd_pcm_hw_constraint_minmax(runtime,
6081 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
6082 32, 4096);
6083 /* RayDAT & AIO have a fixed buffer of 16384 samples per channel */
Lars-Peter Clausenb4ffc1b2015-10-18 15:39:21 +02006084 snd_pcm_hw_constraint_single(runtime,
Takashi Iwaid8776812011-08-15 10:45:42 +02006085 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
Lars-Peter Clausenb4ffc1b2015-10-18 15:39:21 +02006086 16384);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006087 break;
6088
6089 default:
Takashi Iwaid8776812011-08-15 10:45:42 +02006090 snd_pcm_hw_constraint_minmax(runtime,
6091 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
6092 64, 8192);
Lars-Peter Clausenb4ffc1b2015-10-18 15:39:21 +02006093 snd_pcm_hw_constraint_single(runtime,
6094 SNDRV_PCM_HW_PARAM_PERIODS, 2);
Takashi Iwaid8776812011-08-15 10:45:42 +02006095 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006096 }
6097
6098 if (AES32 == hdspm->io_type) {
Takashi Iwai3fa9e3d2011-08-15 10:42:23 +02006099 runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006100 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
6101 &hdspm_hw_constraints_aes32_sample_rates);
6102 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006103 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006104 (playback ?
6105 snd_hdspm_hw_rule_rate_out_channels :
6106 snd_hdspm_hw_rule_rate_in_channels), hdspm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006107 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006108 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01006109
6110 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006111 (playback ? snd_hdspm_hw_rule_out_channels :
6112 snd_hdspm_hw_rule_in_channels), hdspm,
Adrian Knoth88fabbf2011-02-23 11:43:10 +01006113 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
6114
6115 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006116 (playback ? snd_hdspm_hw_rule_out_channels_rate :
6117 snd_hdspm_hw_rule_in_channels_rate), hdspm,
Adrian Knoth88fabbf2011-02-23 11:43:10 +01006118 SNDRV_PCM_HW_PARAM_RATE, -1);
6119
Takashi Iwai763f3562005-06-03 11:25:34 +02006120 return 0;
6121}
6122
Adrian Knoth8b73b862015-02-17 00:05:05 +01006123static int snd_hdspm_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02006124{
Takashi Iwai98274f02005-11-17 14:52:34 +01006125 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Adrian Knoth8b73b862015-02-17 00:05:05 +01006126 bool playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
Takashi Iwai763f3562005-06-03 11:25:34 +02006127
6128 spin_lock_irq(&hdspm->lock);
6129
Adrian Knoth8b73b862015-02-17 00:05:05 +01006130 if (playback) {
6131 hdspm->playback_pid = -1;
6132 hdspm->playback_substream = NULL;
6133 } else {
6134 hdspm->capture_pid = -1;
6135 hdspm->capture_substream = NULL;
6136 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006137
6138 spin_unlock_irq(&hdspm->lock);
6139
6140 return 0;
6141}
6142
Adrian Knoth0dca1792011-01-26 19:32:14 +01006143static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
Takashi Iwai763f3562005-06-03 11:25:34 +02006144{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006145 /* we have nothing to initialize but the call is required */
6146 return 0;
6147}
6148
6149static inline int copy_u32_le(void __user *dest, void __iomem *src)
6150{
6151 u32 val = readl(src);
6152 return copy_to_user(dest, &val, 4);
6153}
6154
6155static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006156 unsigned int cmd, unsigned long arg)
Adrian Knoth0dca1792011-01-26 19:32:14 +01006157{
6158 void __user *argp = (void __user *)arg;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006159 struct hdspm *hdspm = hw->private_data;
Takashi Iwai98274f02005-11-17 14:52:34 +01006160 struct hdspm_mixer_ioctl mixer;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006161 struct hdspm_config info;
6162 struct hdspm_status status;
Takashi Iwai98274f02005-11-17 14:52:34 +01006163 struct hdspm_version hdspm_version;
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006164 struct hdspm_peak_rms *levels;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006165 struct hdspm_ltc ltc;
6166 unsigned int statusregister;
6167 long unsigned int s;
6168 int i = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02006169
6170 switch (cmd) {
6171
Takashi Iwai763f3562005-06-03 11:25:34 +02006172 case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006173 levels = &hdspm->peak_rms;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006174 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006175 levels->input_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006176 readl(hdspm->iobase +
6177 HDSPM_MADI_INPUT_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006178 levels->playback_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006179 readl(hdspm->iobase +
6180 HDSPM_MADI_PLAYBACK_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006181 levels->output_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006182 readl(hdspm->iobase +
6183 HDSPM_MADI_OUTPUT_PEAK + i*4);
6184
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006185 levels->input_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006186 ((uint64_t) readl(hdspm->iobase +
6187 HDSPM_MADI_INPUT_RMS_H + i*4) << 32) |
6188 (uint64_t) readl(hdspm->iobase +
6189 HDSPM_MADI_INPUT_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006190 levels->playback_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006191 ((uint64_t)readl(hdspm->iobase +
6192 HDSPM_MADI_PLAYBACK_RMS_H+i*4) << 32) |
6193 (uint64_t)readl(hdspm->iobase +
6194 HDSPM_MADI_PLAYBACK_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006195 levels->output_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006196 ((uint64_t)readl(hdspm->iobase +
6197 HDSPM_MADI_OUTPUT_RMS_H + i*4) << 32) |
6198 (uint64_t)readl(hdspm->iobase +
6199 HDSPM_MADI_OUTPUT_RMS_L + i*4);
6200 }
6201
6202 if (hdspm->system_sample_rate > 96000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006203 levels->speed = qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006204 } else if (hdspm->system_sample_rate > 48000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006205 levels->speed = ds;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006206 } else {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006207 levels->speed = ss;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006208 }
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006209 levels->status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006210
Markus Elfring7dfec502017-08-12 16:50:06 +02006211 s = copy_to_user(argp, levels, sizeof(*levels));
Adrian Knoth0dca1792011-01-26 19:32:14 +01006212 if (0 != s) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006213 /* dev_err(hdspm->card->dev, "copy_to_user(.., .., %lu): %lu
Adrian Knoth0dca1792011-01-26 19:32:14 +01006214 [Levels]\n", sizeof(struct hdspm_peak_rms), s);
6215 */
Takashi Iwai763f3562005-06-03 11:25:34 +02006216 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006217 }
6218 break;
6219
6220 case SNDRV_HDSPM_IOCTL_GET_LTC:
6221 ltc.ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
6222 i = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
6223 if (i & HDSPM_TCO1_LTC_Input_valid) {
6224 switch (i & (HDSPM_TCO1_LTC_Format_LSB |
6225 HDSPM_TCO1_LTC_Format_MSB)) {
6226 case 0:
6227 ltc.format = fps_24;
6228 break;
6229 case HDSPM_TCO1_LTC_Format_LSB:
6230 ltc.format = fps_25;
6231 break;
6232 case HDSPM_TCO1_LTC_Format_MSB:
6233 ltc.format = fps_2997;
6234 break;
6235 default:
Adrian Knoth17d2f002013-08-19 17:20:30 +02006236 ltc.format = fps_30;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006237 break;
6238 }
6239 if (i & HDSPM_TCO1_set_drop_frame_flag) {
6240 ltc.frame = drop_frame;
6241 } else {
6242 ltc.frame = full_frame;
6243 }
6244 } else {
6245 ltc.format = format_invalid;
6246 ltc.frame = frame_invalid;
6247 }
6248 if (i & HDSPM_TCO1_Video_Input_Format_NTSC) {
6249 ltc.input_format = ntsc;
6250 } else if (i & HDSPM_TCO1_Video_Input_Format_PAL) {
6251 ltc.input_format = pal;
6252 } else {
6253 ltc.input_format = no_video;
6254 }
6255
Markus Elfring7dfec502017-08-12 16:50:06 +02006256 s = copy_to_user(argp, &ltc, sizeof(ltc));
Adrian Knoth0dca1792011-01-26 19:32:14 +01006257 if (0 != s) {
6258 /*
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006259 dev_err(hdspm->card->dev, "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */
Takashi Iwai763f3562005-06-03 11:25:34 +02006260 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006261 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006262
6263 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02006264
Adrian Knoth0dca1792011-01-26 19:32:14 +01006265 case SNDRV_HDSPM_IOCTL_GET_CONFIG:
Takashi Iwai763f3562005-06-03 11:25:34 +02006266
Adrian Knoth4ab69a22011-02-23 11:43:14 +01006267 memset(&info, 0, sizeof(info));
Takashi Iwai763f3562005-06-03 11:25:34 +02006268 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006269 info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
6270 info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006271
6272 info.system_sample_rate = hdspm->system_sample_rate;
6273 info.autosync_sample_rate =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006274 hdspm_external_sample_rate(hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006275 info.system_clock_mode = hdspm_system_clock_mode(hdspm);
6276 info.clock_source = hdspm_clock_source(hdspm);
6277 info.autosync_ref = hdspm_autosync_ref(hdspm);
Adrian Knothc9e16682012-12-03 14:55:50 +01006278 info.line_out = hdspm_toggle_setting(hdspm, HDSPM_LineOut);
Takashi Iwai763f3562005-06-03 11:25:34 +02006279 info.passthru = 0;
6280 spin_unlock_irq(&hdspm->lock);
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006281 if (copy_to_user(argp, &info, sizeof(info)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006282 return -EFAULT;
6283 break;
6284
Adrian Knoth0dca1792011-01-26 19:32:14 +01006285 case SNDRV_HDSPM_IOCTL_GET_STATUS:
Dan Carpenter643d6bb2011-09-23 09:24:21 +03006286 memset(&status, 0, sizeof(status));
6287
Adrian Knoth0dca1792011-01-26 19:32:14 +01006288 status.card_type = hdspm->io_type;
6289
6290 status.autosync_source = hdspm_autosync_ref(hdspm);
6291
6292 status.card_clock = 110069313433624ULL;
6293 status.master_period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
6294
6295 switch (hdspm->io_type) {
6296 case MADI:
6297 case MADIface:
6298 status.card_specific.madi.sync_wc =
6299 hdspm_wc_sync_check(hdspm);
6300 status.card_specific.madi.sync_madi =
6301 hdspm_madi_sync_check(hdspm);
6302 status.card_specific.madi.sync_tco =
6303 hdspm_tco_sync_check(hdspm);
6304 status.card_specific.madi.sync_in =
6305 hdspm_sync_in_sync_check(hdspm);
6306
6307 statusregister =
6308 hdspm_read(hdspm, HDSPM_statusRegister);
6309 status.card_specific.madi.madi_input =
6310 (statusregister & HDSPM_AB_int) ? 1 : 0;
6311 status.card_specific.madi.channel_format =
Adrian Knoth9e6ff522011-10-27 21:57:52 +02006312 (statusregister & HDSPM_RX_64ch) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006313 /* TODO: Mac driver sets it when f_s>48kHz */
6314 status.card_specific.madi.frame_format = 0;
Gustavo A. R. Silva704cbc42020-11-20 12:33:52 -06006315 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006316
6317 default:
6318 break;
6319 }
6320
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006321 if (copy_to_user(argp, &status, sizeof(status)))
Adrian Knoth0dca1792011-01-26 19:32:14 +01006322 return -EFAULT;
6323
6324
6325 break;
6326
Takashi Iwai763f3562005-06-03 11:25:34 +02006327 case SNDRV_HDSPM_IOCTL_GET_VERSION:
Dan Carpenter643d6bb2011-09-23 09:24:21 +03006328 memset(&hdspm_version, 0, sizeof(hdspm_version));
6329
Adrian Knoth0dca1792011-01-26 19:32:14 +01006330 hdspm_version.card_type = hdspm->io_type;
Joe Perches75b1a8f2021-01-04 09:17:34 -08006331 strscpy(hdspm_version.cardname, hdspm->card_name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006332 sizeof(hdspm_version.cardname));
Adrian Knoth7d53a632012-01-04 14:31:16 +01006333 hdspm_version.serial = hdspm->serial;
Takashi Iwai763f3562005-06-03 11:25:34 +02006334 hdspm_version.firmware_rev = hdspm->firmware_rev;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006335 hdspm_version.addons = 0;
6336 if (hdspm->tco)
6337 hdspm_version.addons |= HDSPM_ADDON_TCO;
6338
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006339 if (copy_to_user(argp, &hdspm_version,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006340 sizeof(hdspm_version)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006341 return -EFAULT;
6342 break;
6343
6344 case SNDRV_HDSPM_IOCTL_GET_MIXER:
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006345 if (copy_from_user(&mixer, argp, sizeof(mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006346 return -EFAULT;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006347 if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
Markus Elfring7dfec502017-08-12 16:50:06 +02006348 sizeof(*mixer.mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006349 return -EFAULT;
6350 break;
6351
6352 default:
6353 return -EINVAL;
6354 }
6355 return 0;
6356}
6357
Julia Lawall6769e9882016-09-02 00:13:10 +02006358static const struct snd_pcm_ops snd_hdspm_ops = {
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006359 .open = snd_hdspm_open,
Adrian Knoth8b73b862015-02-17 00:05:05 +01006360 .close = snd_hdspm_release,
Takashi Iwai763f3562005-06-03 11:25:34 +02006361 .ioctl = snd_hdspm_ioctl,
6362 .hw_params = snd_hdspm_hw_params,
6363 .hw_free = snd_hdspm_hw_free,
6364 .prepare = snd_hdspm_prepare,
6365 .trigger = snd_hdspm_trigger,
6366 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006367};
6368
Bill Pembertone23e7a12012-12-06 12:35:10 -05006369static int snd_hdspm_create_hwdep(struct snd_card *card,
6370 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006371{
Takashi Iwai98274f02005-11-17 14:52:34 +01006372 struct snd_hwdep *hw;
Takashi Iwai763f3562005-06-03 11:25:34 +02006373 int err;
6374
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006375 err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw);
6376 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006377 return err;
6378
6379 hdspm->hwdep = hw;
6380 hw->private_data = hdspm;
6381 strcpy(hw->name, "HDSPM hwdep interface");
6382
Adrian Knoth0dca1792011-01-26 19:32:14 +01006383 hw->ops.open = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006384 hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
Adrian Knoth8de5d6f2012-03-08 15:38:04 +01006385 hw->ops.ioctl_compat = snd_hdspm_hwdep_ioctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006386 hw->ops.release = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006387
6388 return 0;
6389}
6390
6391
6392/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01006393 memory interface
Takashi Iwai763f3562005-06-03 11:25:34 +02006394 ------------------------------------------------------------*/
Bill Pembertone23e7a12012-12-06 12:35:10 -05006395static int snd_hdspm_preallocate_memory(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006396{
Takashi Iwai98274f02005-11-17 14:52:34 +01006397 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006398 size_t wanted;
6399
6400 pcm = hdspm->pcm;
6401
Remy Bruno3cee5a62006-10-16 12:46:32 +02006402 wanted = HDSPM_DMA_AREA_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02006403
Takashi Iwai5116b942019-02-04 16:32:09 +01006404 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
Takashi Iwai1a810432019-11-05 16:18:54 +01006405 &hdspm->pci->dev,
Takashi Iwai5116b942019-02-04 16:32:09 +01006406 wanted, wanted);
6407 dev_dbg(hdspm->card->dev, " Preallocated %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006408 return 0;
6409}
6410
Philippe Bekaerte4e07c62019-05-23 23:56:49 +02006411/* Inform the card what DMA addresses to use for the indicated channel. */
6412/* Each channel got 16 4K pages allocated for DMA transfers. */
6413static void hdspm_set_channel_dma_addr(struct hdspm *hdspm,
6414 struct snd_pcm_substream *substream,
6415 unsigned int reg, int channel)
Takashi Iwai763f3562005-06-03 11:25:34 +02006416{
6417 int i;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006418
Philippe Bekaerte4e07c62019-05-23 23:56:49 +02006419 for (i = channel * 16; i < channel * 16 + 16; i++)
Takashi Iwai763f3562005-06-03 11:25:34 +02006420 hdspm_write(hdspm, reg + 4 * i,
Philippe Bekaerte4e07c62019-05-23 23:56:49 +02006421 snd_pcm_sgbuf_get_addr(substream, 4096 * i));
Takashi Iwai763f3562005-06-03 11:25:34 +02006422}
6423
Adrian Knoth0dca1792011-01-26 19:32:14 +01006424
Takashi Iwai763f3562005-06-03 11:25:34 +02006425/* ------------- ALSA Devices ---------------------------- */
Bill Pembertone23e7a12012-12-06 12:35:10 -05006426static int snd_hdspm_create_pcm(struct snd_card *card,
6427 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006428{
Takashi Iwai98274f02005-11-17 14:52:34 +01006429 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006430 int err;
6431
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006432 err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm);
6433 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006434 return err;
6435
6436 hdspm->pcm = pcm;
6437 pcm->private_data = hdspm;
6438 strcpy(pcm->name, hdspm->card_name);
6439
6440 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
Adrian Knoth0c8d9482015-02-17 00:05:06 +01006441 &snd_hdspm_ops);
Takashi Iwai763f3562005-06-03 11:25:34 +02006442 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
Adrian Knoth0c8d9482015-02-17 00:05:06 +01006443 &snd_hdspm_ops);
Takashi Iwai763f3562005-06-03 11:25:34 +02006444
6445 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
6446
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006447 err = snd_hdspm_preallocate_memory(hdspm);
6448 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006449 return err;
6450
6451 return 0;
6452}
6453
Takashi Iwai98274f02005-11-17 14:52:34 +01006454static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006455{
Adrian Knoth7c7102b2011-02-28 15:14:50 +01006456 int i;
6457
6458 for (i = 0; i < hdspm->midiPorts; i++)
6459 snd_hdspm_flush_midi_input(hdspm, i);
Takashi Iwai763f3562005-06-03 11:25:34 +02006460}
6461
Bill Pembertone23e7a12012-12-06 12:35:10 -05006462static int snd_hdspm_create_alsa_devices(struct snd_card *card,
6463 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006464{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006465 int err, i;
Takashi Iwai763f3562005-06-03 11:25:34 +02006466
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006467 dev_dbg(card->dev, "Create card...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006468 err = snd_hdspm_create_pcm(card, hdspm);
6469 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006470 return err;
6471
Adrian Knoth0dca1792011-01-26 19:32:14 +01006472 i = 0;
6473 while (i < hdspm->midiPorts) {
6474 err = snd_hdspm_create_midi(card, hdspm, i);
6475 if (err < 0) {
6476 return err;
6477 }
6478 i++;
6479 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006480
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006481 err = snd_hdspm_create_controls(card, hdspm);
6482 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006483 return err;
6484
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006485 err = snd_hdspm_create_hwdep(card, hdspm);
6486 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006487 return err;
6488
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006489 dev_dbg(card->dev, "proc init...\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02006490 snd_hdspm_proc_init(hdspm);
6491
6492 hdspm->system_sample_rate = -1;
6493 hdspm->last_external_sample_rate = -1;
6494 hdspm->last_internal_sample_rate = -1;
6495 hdspm->playback_pid = -1;
6496 hdspm->capture_pid = -1;
6497 hdspm->capture_substream = NULL;
6498 hdspm->playback_substream = NULL;
6499
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006500 dev_dbg(card->dev, "Set defaults...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006501 err = snd_hdspm_set_defaults(hdspm);
6502 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006503 return err;
6504
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006505 dev_dbg(card->dev, "Update mixer controls...\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02006506 hdspm_update_simple_mixer_controls(hdspm);
6507
Colin Ian King1bb6d9e2018-08-26 23:09:52 +01006508 dev_dbg(card->dev, "Initializing complete?\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02006509
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006510 err = snd_card_register(card);
6511 if (err < 0) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006512 dev_err(card->dev, "error registering card\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02006513 return err;
6514 }
6515
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006516 dev_dbg(card->dev, "... yes now\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02006517
6518 return 0;
6519}
6520
Bill Pembertone23e7a12012-12-06 12:35:10 -05006521static int snd_hdspm_create(struct snd_card *card,
6522 struct hdspm *hdspm)
6523{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006524
Takashi Iwai763f3562005-06-03 11:25:34 +02006525 struct pci_dev *pci = hdspm->pci;
6526 int err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006527 unsigned long io_extent;
6528
6529 hdspm->irq = -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02006530 hdspm->card = card;
6531
6532 spin_lock_init(&hdspm->lock);
Takashi Iwaia2e527c2020-09-03 12:41:27 +02006533 INIT_WORK(&hdspm->midi_work, hdspm_midi_work);
Takashi Iwai763f3562005-06-03 11:25:34 +02006534
Takashi Iwai763f3562005-06-03 11:25:34 +02006535 pci_read_config_word(hdspm->pci,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006536 PCI_CLASS_REVISION, &hdspm->firmware_rev);
Remy Bruno3cee5a62006-10-16 12:46:32 +02006537
Takashi Iwai763f3562005-06-03 11:25:34 +02006538 strcpy(card->mixername, "Xilinx FPGA");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006539 strcpy(card->driver, "HDSPM");
6540
6541 switch (hdspm->firmware_rev) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01006542 case HDSPM_RAYDAT_REV:
6543 hdspm->io_type = RayDAT;
6544 hdspm->card_name = "RME RayDAT";
6545 hdspm->midiPorts = 2;
6546 break;
6547 case HDSPM_AIO_REV:
6548 hdspm->io_type = AIO;
6549 hdspm->card_name = "RME AIO";
6550 hdspm->midiPorts = 1;
6551 break;
6552 case HDSPM_MADIFACE_REV:
6553 hdspm->io_type = MADIface;
6554 hdspm->card_name = "RME MADIface";
6555 hdspm->midiPorts = 1;
6556 break;
Adrian Knoth5027f342011-02-28 15:14:49 +01006557 default:
Adrian Knothc09403d2011-10-27 21:57:54 +02006558 if ((hdspm->firmware_rev == 0xf0) ||
6559 ((hdspm->firmware_rev >= 0xe6) &&
6560 (hdspm->firmware_rev <= 0xea))) {
6561 hdspm->io_type = AES32;
6562 hdspm->card_name = "RME AES32";
6563 hdspm->midiPorts = 2;
Adrian Knoth05c7cc92011-11-21 16:15:36 +01006564 } else if ((hdspm->firmware_rev == 0xd2) ||
Adrian Knothc09403d2011-10-27 21:57:54 +02006565 ((hdspm->firmware_rev >= 0xc8) &&
6566 (hdspm->firmware_rev <= 0xcf))) {
6567 hdspm->io_type = MADI;
6568 hdspm->card_name = "RME MADI";
6569 hdspm->midiPorts = 3;
6570 } else {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006571 dev_err(card->dev,
6572 "unknown firmware revision %x\n",
Adrian Knoth5027f342011-02-28 15:14:49 +01006573 hdspm->firmware_rev);
Adrian Knothc09403d2011-10-27 21:57:54 +02006574 return -ENODEV;
6575 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02006576 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006577
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006578 err = pci_enable_device(pci);
6579 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006580 return err;
6581
6582 pci_set_master(hdspm->pci);
6583
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006584 err = pci_request_regions(pci, "hdspm");
6585 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006586 return err;
6587
6588 hdspm->port = pci_resource_start(pci, 0);
6589 io_extent = pci_resource_len(pci, 0);
6590
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006591 dev_dbg(card->dev, "grabbed memory region 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006592 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006593
Christoph Hellwig4bdc0d62020-01-06 09:43:50 +01006594 hdspm->iobase = ioremap(hdspm->port, io_extent);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006595 if (!hdspm->iobase) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006596 dev_err(card->dev, "unable to remap region 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006597 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006598 return -EBUSY;
6599 }
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006600 dev_dbg(card->dev, "remapped region (0x%lx) 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006601 (unsigned long)hdspm->iobase, hdspm->port,
6602 hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006603
6604 if (request_irq(pci->irq, snd_hdspm_interrupt,
Takashi Iwai934c2b62011-06-10 16:36:37 +02006605 IRQF_SHARED, KBUILD_MODNAME, hdspm)) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006606 dev_err(card->dev, "unable to use IRQ %d\n", pci->irq);
Takashi Iwai763f3562005-06-03 11:25:34 +02006607 return -EBUSY;
6608 }
6609
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006610 dev_dbg(card->dev, "use IRQ %d\n", pci->irq);
Takashi Iwai763f3562005-06-03 11:25:34 +02006611
6612 hdspm->irq = pci->irq;
Takashi Iwai39cccf42019-12-10 07:34:32 +01006613 card->sync_irq = hdspm->irq;
Takashi Iwai763f3562005-06-03 11:25:34 +02006614
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006615 dev_dbg(card->dev, "kmalloc Mixer memory of %zd Bytes\n",
Markus Elfring7dfec502017-08-12 16:50:06 +02006616 sizeof(*hdspm->mixer));
6617 hdspm->mixer = kzalloc(sizeof(*hdspm->mixer), GFP_KERNEL);
Markus Elfring9dba5422017-08-12 16:10:32 +02006618 if (!hdspm->mixer)
Julia Lawallb17cbdd2012-08-19 09:02:54 +02006619 return -ENOMEM;
Takashi Iwai763f3562005-06-03 11:25:34 +02006620
Adrian Knoth0dca1792011-01-26 19:32:14 +01006621 hdspm->port_names_in = NULL;
6622 hdspm->port_names_out = NULL;
6623
6624 switch (hdspm->io_type) {
6625 case AES32:
Adrian Knothd2d10a22011-02-28 15:14:47 +01006626 hdspm->ss_in_channels = hdspm->ss_out_channels = AES32_CHANNELS;
6627 hdspm->ds_in_channels = hdspm->ds_out_channels = AES32_CHANNELS;
6628 hdspm->qs_in_channels = hdspm->qs_out_channels = AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006629
6630 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6631 channel_map_aes32;
6632 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6633 channel_map_aes32;
6634 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6635 channel_map_aes32;
6636 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6637 texts_ports_aes32;
6638 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6639 texts_ports_aes32;
6640 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6641 texts_ports_aes32;
6642
Adrian Knothd2d10a22011-02-28 15:14:47 +01006643 hdspm->max_channels_out = hdspm->max_channels_in =
6644 AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006645 hdspm->port_names_in = hdspm->port_names_out =
6646 texts_ports_aes32;
6647 hdspm->channel_map_in = hdspm->channel_map_out =
6648 channel_map_aes32;
6649
Adrian Knoth0dca1792011-01-26 19:32:14 +01006650 break;
6651
6652 case MADI:
6653 case MADIface:
6654 hdspm->ss_in_channels = hdspm->ss_out_channels =
6655 MADI_SS_CHANNELS;
6656 hdspm->ds_in_channels = hdspm->ds_out_channels =
6657 MADI_DS_CHANNELS;
6658 hdspm->qs_in_channels = hdspm->qs_out_channels =
6659 MADI_QS_CHANNELS;
6660
6661 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6662 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006663 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006664 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006665 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006666 channel_map_unity_ss;
6667
6668 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6669 texts_ports_madi;
6670 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6671 texts_ports_madi;
6672 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6673 texts_ports_madi;
6674 break;
6675
6676 case AIO:
Adrian Knoth0dca1792011-01-26 19:32:14 +01006677 hdspm->ss_in_channels = AIO_IN_SS_CHANNELS;
6678 hdspm->ds_in_channels = AIO_IN_DS_CHANNELS;
6679 hdspm->qs_in_channels = AIO_IN_QS_CHANNELS;
6680 hdspm->ss_out_channels = AIO_OUT_SS_CHANNELS;
6681 hdspm->ds_out_channels = AIO_OUT_DS_CHANNELS;
6682 hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS;
6683
Adrian Knoth3de9db22013-07-05 11:28:02 +02006684 if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006685 dev_info(card->dev, "AEB input board found\n");
Adrian Knoth3de9db22013-07-05 11:28:02 +02006686 hdspm->ss_in_channels += 4;
6687 hdspm->ds_in_channels += 4;
6688 hdspm->qs_in_channels += 4;
6689 }
6690
6691 if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBO_D)) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006692 dev_info(card->dev, "AEB output board found\n");
Adrian Knoth3de9db22013-07-05 11:28:02 +02006693 hdspm->ss_out_channels += 4;
6694 hdspm->ds_out_channels += 4;
6695 hdspm->qs_out_channels += 4;
6696 }
6697
Adrian Knoth0dca1792011-01-26 19:32:14 +01006698 hdspm->channel_map_out_ss = channel_map_aio_out_ss;
6699 hdspm->channel_map_out_ds = channel_map_aio_out_ds;
6700 hdspm->channel_map_out_qs = channel_map_aio_out_qs;
6701
6702 hdspm->channel_map_in_ss = channel_map_aio_in_ss;
6703 hdspm->channel_map_in_ds = channel_map_aio_in_ds;
6704 hdspm->channel_map_in_qs = channel_map_aio_in_qs;
6705
6706 hdspm->port_names_in_ss = texts_ports_aio_in_ss;
6707 hdspm->port_names_out_ss = texts_ports_aio_out_ss;
6708 hdspm->port_names_in_ds = texts_ports_aio_in_ds;
6709 hdspm->port_names_out_ds = texts_ports_aio_out_ds;
6710 hdspm->port_names_in_qs = texts_ports_aio_in_qs;
6711 hdspm->port_names_out_qs = texts_ports_aio_out_qs;
6712
6713 break;
6714
6715 case RayDAT:
6716 hdspm->ss_in_channels = hdspm->ss_out_channels =
6717 RAYDAT_SS_CHANNELS;
6718 hdspm->ds_in_channels = hdspm->ds_out_channels =
6719 RAYDAT_DS_CHANNELS;
6720 hdspm->qs_in_channels = hdspm->qs_out_channels =
6721 RAYDAT_QS_CHANNELS;
6722
6723 hdspm->max_channels_in = RAYDAT_SS_CHANNELS;
6724 hdspm->max_channels_out = RAYDAT_SS_CHANNELS;
6725
6726 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6727 channel_map_raydat_ss;
6728 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6729 channel_map_raydat_ds;
6730 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6731 channel_map_raydat_qs;
6732 hdspm->channel_map_in = hdspm->channel_map_out =
6733 channel_map_raydat_ss;
6734
6735 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6736 texts_ports_raydat_ss;
6737 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6738 texts_ports_raydat_ds;
6739 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6740 texts_ports_raydat_qs;
6741
6742
6743 break;
6744
6745 }
6746
6747 /* TCO detection */
6748 switch (hdspm->io_type) {
6749 case AIO:
6750 case RayDAT:
6751 if (hdspm_read(hdspm, HDSPM_statusRegister2) &
6752 HDSPM_s2_tco_detect) {
6753 hdspm->midiPorts++;
Markus Elfring7dfec502017-08-12 16:50:06 +02006754 hdspm->tco = kzalloc(sizeof(*hdspm->tco), GFP_KERNEL);
Markus Elfringda2ea372017-08-12 17:07:09 +02006755 if (hdspm->tco)
Adrian Knoth0dca1792011-01-26 19:32:14 +01006756 hdspm_tco_write(hdspm);
Markus Elfringda2ea372017-08-12 17:07:09 +02006757
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006758 dev_info(card->dev, "AIO/RayDAT TCO module found\n");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006759 } else {
6760 hdspm->tco = NULL;
6761 }
6762 break;
6763
6764 case MADI:
Adrian Knoth0dc831b2013-07-05 11:28:19 +02006765 case AES32:
Adrian Knoth0dca1792011-01-26 19:32:14 +01006766 if (hdspm_read(hdspm, HDSPM_statusRegister) & HDSPM_tco_detect) {
6767 hdspm->midiPorts++;
Markus Elfring7dfec502017-08-12 16:50:06 +02006768 hdspm->tco = kzalloc(sizeof(*hdspm->tco), GFP_KERNEL);
Markus Elfringda2ea372017-08-12 17:07:09 +02006769 if (hdspm->tco)
Adrian Knoth0dca1792011-01-26 19:32:14 +01006770 hdspm_tco_write(hdspm);
Markus Elfringda2ea372017-08-12 17:07:09 +02006771
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006772 dev_info(card->dev, "MADI/AES TCO module found\n");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006773 } else {
6774 hdspm->tco = NULL;
6775 }
6776 break;
6777
6778 default:
6779 hdspm->tco = NULL;
6780 }
6781
6782 /* texts */
6783 switch (hdspm->io_type) {
6784 case AES32:
6785 if (hdspm->tco) {
6786 hdspm->texts_autosync = texts_autosync_aes_tco;
Adrian Knothe71b95a2013-07-05 11:28:06 +02006787 hdspm->texts_autosync_items =
6788 ARRAY_SIZE(texts_autosync_aes_tco);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006789 } else {
6790 hdspm->texts_autosync = texts_autosync_aes;
Adrian Knothe71b95a2013-07-05 11:28:06 +02006791 hdspm->texts_autosync_items =
6792 ARRAY_SIZE(texts_autosync_aes);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006793 }
6794 break;
6795
6796 case MADI:
6797 if (hdspm->tco) {
6798 hdspm->texts_autosync = texts_autosync_madi_tco;
6799 hdspm->texts_autosync_items = 4;
6800 } else {
6801 hdspm->texts_autosync = texts_autosync_madi;
6802 hdspm->texts_autosync_items = 3;
6803 }
6804 break;
6805
6806 case MADIface:
6807
6808 break;
6809
6810 case RayDAT:
6811 if (hdspm->tco) {
6812 hdspm->texts_autosync = texts_autosync_raydat_tco;
6813 hdspm->texts_autosync_items = 9;
6814 } else {
6815 hdspm->texts_autosync = texts_autosync_raydat;
6816 hdspm->texts_autosync_items = 8;
6817 }
6818 break;
6819
6820 case AIO:
6821 if (hdspm->tco) {
6822 hdspm->texts_autosync = texts_autosync_aio_tco;
6823 hdspm->texts_autosync_items = 6;
6824 } else {
6825 hdspm->texts_autosync = texts_autosync_aio;
6826 hdspm->texts_autosync_items = 5;
6827 }
6828 break;
6829
6830 }
6831
Adrian Knothf7de8ba2012-01-10 20:58:40 +01006832 if (hdspm->io_type != MADIface) {
6833 hdspm->serial = (hdspm_read(hdspm,
6834 HDSPM_midiStatusIn0)>>8) & 0xFFFFFF;
6835 /* id contains either a user-provided value or the default
6836 * NULL. If it's the default, we're safe to
6837 * fill card->id with the serial number.
6838 *
6839 * If the serial number is 0xFFFFFF, then we're dealing with
6840 * an old PCI revision that comes without a sane number. In
6841 * this case, we don't set card->id to avoid collisions
6842 * when running with multiple cards.
6843 */
Markus Elfringda2ea372017-08-12 17:07:09 +02006844 if (!id[hdspm->dev] && hdspm->serial != 0xFFFFFF) {
Arnd Bergmann7ad210a2017-07-18 13:48:09 +02006845 snprintf(card->id, sizeof(card->id),
6846 "HDSPMx%06x", hdspm->serial);
Adrian Knothf7de8ba2012-01-10 20:58:40 +01006847 snd_card_set_id(card, card->id);
6848 }
6849 }
6850
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006851 dev_dbg(card->dev, "create alsa devices.\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006852 err = snd_hdspm_create_alsa_devices(card, hdspm);
6853 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006854 return err;
6855
6856 snd_hdspm_initialize_midi_flush(hdspm);
6857
6858 return 0;
6859}
6860
Adrian Knoth0dca1792011-01-26 19:32:14 +01006861
Takashi Iwai98274f02005-11-17 14:52:34 +01006862static int snd_hdspm_free(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006863{
6864
6865 if (hdspm->port) {
Takashi Iwaia2e527c2020-09-03 12:41:27 +02006866 cancel_work_sync(&hdspm->midi_work);
Takashi Iwai763f3562005-06-03 11:25:34 +02006867
6868 /* stop th audio, and cancel all interrupts */
6869 hdspm->control_register &=
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006870 ~(HDSPM_Start | HDSPM_AudioInterruptEnable |
Adrian Knoth0dca1792011-01-26 19:32:14 +01006871 HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable |
6872 HDSPM_Midi2InterruptEnable | HDSPM_Midi3InterruptEnable);
Takashi Iwai763f3562005-06-03 11:25:34 +02006873 hdspm_write(hdspm, HDSPM_controlRegister,
6874 hdspm->control_register);
6875 }
6876
6877 if (hdspm->irq >= 0)
6878 free_irq(hdspm->irq, (void *) hdspm);
6879
Jesper Juhlfc584222005-10-24 15:11:28 +02006880 kfree(hdspm->mixer);
Markus Elfringff6defa2015-01-03 22:55:54 +01006881 iounmap(hdspm->iobase);
Takashi Iwai763f3562005-06-03 11:25:34 +02006882
Takashi Iwai763f3562005-06-03 11:25:34 +02006883 if (hdspm->port)
6884 pci_release_regions(hdspm->pci);
6885
6886 pci_disable_device(hdspm->pci);
6887 return 0;
6888}
6889
Adrian Knoth0dca1792011-01-26 19:32:14 +01006890
Takashi Iwai98274f02005-11-17 14:52:34 +01006891static void snd_hdspm_card_free(struct snd_card *card)
Takashi Iwai763f3562005-06-03 11:25:34 +02006892{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006893 struct hdspm *hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006894
6895 if (hdspm)
6896 snd_hdspm_free(hdspm);
6897}
6898
Adrian Knoth0dca1792011-01-26 19:32:14 +01006899
Bill Pembertone23e7a12012-12-06 12:35:10 -05006900static int snd_hdspm_probe(struct pci_dev *pci,
6901 const struct pci_device_id *pci_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02006902{
6903 static int dev;
Takashi Iwai98274f02005-11-17 14:52:34 +01006904 struct hdspm *hdspm;
6905 struct snd_card *card;
Takashi Iwai763f3562005-06-03 11:25:34 +02006906 int err;
6907
6908 if (dev >= SNDRV_CARDS)
6909 return -ENODEV;
6910 if (!enable[dev]) {
6911 dev++;
6912 return -ENOENT;
6913 }
6914
Takashi Iwai60c57722014-01-29 14:20:19 +01006915 err = snd_card_new(&pci->dev, index[dev], id[dev],
Markus Elfring7dfec502017-08-12 16:50:06 +02006916 THIS_MODULE, sizeof(*hdspm), &card);
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006917 if (err < 0)
6918 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006919
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006920 hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006921 card->private_free = snd_hdspm_card_free;
6922 hdspm->dev = dev;
6923 hdspm->pci = pci;
6924
Adrian Knoth0dca1792011-01-26 19:32:14 +01006925 err = snd_hdspm_create(card, hdspm);
Markus Elfringe35e9dd2017-09-05 22:22:21 +02006926 if (err < 0)
6927 goto free_card;
Takashi Iwai763f3562005-06-03 11:25:34 +02006928
Adrian Knoth0dca1792011-01-26 19:32:14 +01006929 if (hdspm->io_type != MADIface) {
Arnd Bergmann7ad210a2017-07-18 13:48:09 +02006930 snprintf(card->shortname, sizeof(card->shortname), "%s_%x",
6931 hdspm->card_name, hdspm->serial);
6932 snprintf(card->longname, sizeof(card->longname),
6933 "%s S/N 0x%x at 0x%lx, irq %d",
6934 hdspm->card_name, hdspm->serial,
6935 hdspm->port, hdspm->irq);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006936 } else {
Arnd Bergmann7ad210a2017-07-18 13:48:09 +02006937 snprintf(card->shortname, sizeof(card->shortname), "%s",
6938 hdspm->card_name);
6939 snprintf(card->longname, sizeof(card->longname),
6940 "%s at 0x%lx, irq %d",
6941 hdspm->card_name, hdspm->port, hdspm->irq);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006942 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006943
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006944 err = snd_card_register(card);
Markus Elfringe35e9dd2017-09-05 22:22:21 +02006945 if (err < 0)
6946 goto free_card;
Takashi Iwai763f3562005-06-03 11:25:34 +02006947
6948 pci_set_drvdata(pci, card);
6949
6950 dev++;
6951 return 0;
Markus Elfringe35e9dd2017-09-05 22:22:21 +02006952
6953free_card:
6954 snd_card_free(card);
6955 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006956}
6957
Bill Pembertone23e7a12012-12-06 12:35:10 -05006958static void snd_hdspm_remove(struct pci_dev *pci)
Takashi Iwai763f3562005-06-03 11:25:34 +02006959{
6960 snd_card_free(pci_get_drvdata(pci));
Takashi Iwai763f3562005-06-03 11:25:34 +02006961}
6962
Takashi Iwaie9f66d92012-04-24 12:25:00 +02006963static struct pci_driver hdspm_driver = {
Takashi Iwai3733e422011-06-10 16:20:20 +02006964 .name = KBUILD_MODNAME,
Takashi Iwai763f3562005-06-03 11:25:34 +02006965 .id_table = snd_hdspm_ids,
6966 .probe = snd_hdspm_probe,
Bill Pembertone23e7a12012-12-06 12:35:10 -05006967 .remove = snd_hdspm_remove,
Takashi Iwai763f3562005-06-03 11:25:34 +02006968};
6969
Takashi Iwaie9f66d92012-04-24 12:25:00 +02006970module_pci_driver(hdspm_driver);