blob: 4a1f576dd9cfab827dbd52ba755de1dc03a3757b [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");
168MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
169
Adrian Knoth0dca1792011-01-26 19:32:14 +0100170/* --- Write registers. ---
Takashi Iwai763f3562005-06-03 11:25:34 +0200171 These are defined as byte-offsets from the iobase value. */
172
Adrian Knoth0dca1792011-01-26 19:32:14 +0100173#define HDSPM_WR_SETTINGS 0
174#define HDSPM_outputBufferAddress 32
175#define HDSPM_inputBufferAddress 36
Takashi Iwai763f3562005-06-03 11:25:34 +0200176#define HDSPM_controlRegister 64
177#define HDSPM_interruptConfirmation 96
178#define HDSPM_control2Reg 256 /* not in specs ???????? */
Martin Dausel69358fc2013-07-05 11:28:23 +0200179#define HDSPM_freqReg 256 /* for setting arbitrary clock values (DDS feature) */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100180#define HDSPM_midiDataOut0 352 /* just believe in old code */
181#define HDSPM_midiDataOut1 356
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100182#define HDSPM_eeprom_wr 384 /* for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200183
184/* DMA enable for 64 channels, only Bit 0 is relevant */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100185#define HDSPM_outputEnableBase 512 /* 512-767 input DMA */
Takashi Iwai763f3562005-06-03 11:25:34 +0200186#define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */
187
Adrian Knoth0dca1792011-01-26 19:32:14 +0100188/* 16 page addresses for each of the 64 channels DMA buffer in and out
Takashi Iwai763f3562005-06-03 11:25:34 +0200189 (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */
190#define HDSPM_pageAddressBufferOut 8192
191#define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4)
192
193#define HDSPM_MADI_mixerBase 32768 /* 32768-65535 for 2x64x64 Fader */
194
195#define HDSPM_MATRIX_MIXER_SIZE 8192 /* = 2*64*64 * 4 Byte => 32kB */
196
197/* --- Read registers. ---
198 These are defined as byte-offsets from the iobase value */
199#define HDSPM_statusRegister 0
Remy Bruno3cee5a62006-10-16 12:46:32 +0200200/*#define HDSPM_statusRegister2 96 */
201/* after RME Windows driver sources, status2 is 4-byte word # 48 = word at
202 * offset 192, for AES32 *and* MADI
203 * => need to check that offset 192 is working on MADI */
204#define HDSPM_statusRegister2 192
205#define HDSPM_timecodeRegister 128
Takashi Iwai763f3562005-06-03 11:25:34 +0200206
Adrian Knoth0dca1792011-01-26 19:32:14 +0100207/* AIO, RayDAT */
208#define HDSPM_RD_STATUS_0 0
209#define HDSPM_RD_STATUS_1 64
210#define HDSPM_RD_STATUS_2 128
211#define HDSPM_RD_STATUS_3 192
212
213#define HDSPM_RD_TCO 256
214#define HDSPM_RD_PLL_FREQ 512
215#define HDSPM_WR_TCO 128
216
217#define HDSPM_TCO1_TCO_lock 0x00000001
218#define HDSPM_TCO1_WCK_Input_Range_LSB 0x00000002
219#define HDSPM_TCO1_WCK_Input_Range_MSB 0x00000004
220#define HDSPM_TCO1_LTC_Input_valid 0x00000008
221#define HDSPM_TCO1_WCK_Input_valid 0x00000010
222#define HDSPM_TCO1_Video_Input_Format_NTSC 0x00000020
223#define HDSPM_TCO1_Video_Input_Format_PAL 0x00000040
224
225#define HDSPM_TCO1_set_TC 0x00000100
226#define HDSPM_TCO1_set_drop_frame_flag 0x00000200
227#define HDSPM_TCO1_LTC_Format_LSB 0x00000400
228#define HDSPM_TCO1_LTC_Format_MSB 0x00000800
229
230#define HDSPM_TCO2_TC_run 0x00010000
231#define HDSPM_TCO2_WCK_IO_ratio_LSB 0x00020000
232#define HDSPM_TCO2_WCK_IO_ratio_MSB 0x00040000
233#define HDSPM_TCO2_set_num_drop_frames_LSB 0x00080000
234#define HDSPM_TCO2_set_num_drop_frames_MSB 0x00100000
235#define HDSPM_TCO2_set_jam_sync 0x00200000
236#define HDSPM_TCO2_set_flywheel 0x00400000
237
238#define HDSPM_TCO2_set_01_4 0x01000000
239#define HDSPM_TCO2_set_pull_down 0x02000000
240#define HDSPM_TCO2_set_pull_up 0x04000000
241#define HDSPM_TCO2_set_freq 0x08000000
242#define HDSPM_TCO2_set_term_75R 0x10000000
243#define HDSPM_TCO2_set_input_LSB 0x20000000
244#define HDSPM_TCO2_set_input_MSB 0x40000000
245#define HDSPM_TCO2_set_freq_from_app 0x80000000
246
247
248#define HDSPM_midiDataOut0 352
249#define HDSPM_midiDataOut1 356
250#define HDSPM_midiDataOut2 368
251
Takashi Iwai763f3562005-06-03 11:25:34 +0200252#define HDSPM_midiDataIn0 360
253#define HDSPM_midiDataIn1 364
Adrian Knoth0dca1792011-01-26 19:32:14 +0100254#define HDSPM_midiDataIn2 372
255#define HDSPM_midiDataIn3 376
Takashi Iwai763f3562005-06-03 11:25:34 +0200256
257/* status is data bytes in MIDI-FIFO (0-128) */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100258#define HDSPM_midiStatusOut0 384
259#define HDSPM_midiStatusOut1 388
260#define HDSPM_midiStatusOut2 400
261
262#define HDSPM_midiStatusIn0 392
263#define HDSPM_midiStatusIn1 396
264#define HDSPM_midiStatusIn2 404
265#define HDSPM_midiStatusIn3 408
Takashi Iwai763f3562005-06-03 11:25:34 +0200266
267
268/* the meters are regular i/o-mapped registers, but offset
269 considerably from the rest. the peak registers are reset
Adrian Knoth0dca1792011-01-26 19:32:14 +0100270 when read; the least-significant 4 bits are full-scale counters;
Takashi Iwai763f3562005-06-03 11:25:34 +0200271 the actual peak value is in the most-significant 24 bits.
272*/
Adrian Knoth0dca1792011-01-26 19:32:14 +0100273
274#define HDSPM_MADI_INPUT_PEAK 4096
275#define HDSPM_MADI_PLAYBACK_PEAK 4352
276#define HDSPM_MADI_OUTPUT_PEAK 4608
277
278#define HDSPM_MADI_INPUT_RMS_L 6144
279#define HDSPM_MADI_PLAYBACK_RMS_L 6400
280#define HDSPM_MADI_OUTPUT_RMS_L 6656
281
282#define HDSPM_MADI_INPUT_RMS_H 7168
283#define HDSPM_MADI_PLAYBACK_RMS_H 7424
284#define HDSPM_MADI_OUTPUT_RMS_H 7680
Takashi Iwai763f3562005-06-03 11:25:34 +0200285
286/* --- Control Register bits --------- */
287#define HDSPM_Start (1<<0) /* start engine */
288
289#define HDSPM_Latency0 (1<<1) /* buffer size = 2^n */
290#define HDSPM_Latency1 (1<<2) /* where n is defined */
291#define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */
292
Adrian Knoth0dca1792011-01-26 19:32:14 +0100293#define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Autosync */
294#define HDSPM_c0Master 0x1 /* Master clock bit in settings
295 register [RayDAT, AIO] */
Takashi Iwai763f3562005-06-03 11:25:34 +0200296
297#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */
298
299#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */
300#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */
301#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200302#define HDSPM_QuadSpeed (1<<31) /* quad speed bit */
Takashi Iwai763f3562005-06-03 11:25:34 +0200303
Remy Bruno3cee5a62006-10-16 12:46:32 +0200304#define HDSPM_Professional (1<<9) /* Professional */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200305#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200306 56channelMODE=0 */ /* MADI ONLY*/
307#define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200308
Adrian Knoth0dca1792011-01-26 19:32:14 +0100309#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200310 0=off, 1=on */ /* MADI ONLY */
311#define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200312
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200313#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax
314 * -- MADI ONLY
315 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200316#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
317
Remy Bruno3cee5a62006-10-16 12:46:32 +0200318#define HDSPM_SyncRef2 (1<<13)
319#define HDSPM_SyncRef3 (1<<25)
Takashi Iwai763f3562005-06-03 11:25:34 +0200320
Remy Bruno3cee5a62006-10-16 12:46:32 +0200321#define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100322#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use
Takashi Iwai763f3562005-06-03 11:25:34 +0200323 AES additional bits in
324 lower 5 Audiodatabits ??? */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200325#define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */
326#define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200327
Adrian Knoth0dca1792011-01-26 19:32:14 +0100328#define HDSPM_Midi0InterruptEnable 0x0400000
329#define HDSPM_Midi1InterruptEnable 0x0800000
330#define HDSPM_Midi2InterruptEnable 0x0200000
331#define HDSPM_Midi3InterruptEnable 0x4000000
Takashi Iwai763f3562005-06-03 11:25:34 +0200332
333#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100334#define HDSPe_FLOAT_FORMAT 0x2000000
Takashi Iwai763f3562005-06-03 11:25:34 +0200335
Remy Bruno3cee5a62006-10-16 12:46:32 +0200336#define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */
337#define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */
338#define HDSPM_QS_QuadWire (1<<28) /* AES32 ONLY */
339
340#define HDSPM_wclk_sel (1<<30)
Takashi Iwai763f3562005-06-03 11:25:34 +0200341
Adrian Knoth384f7782013-07-05 11:27:53 +0200342/* additional control register bits for AIO*/
343#define HDSPM_c0_Wck48 0x20 /* also RayDAT */
344#define HDSPM_c0_Input0 0x1000
345#define HDSPM_c0_Input1 0x2000
346#define HDSPM_c0_Spdif_Opt 0x4000
347#define HDSPM_c0_Pro 0x8000
348#define HDSPM_c0_clr_tms 0x10000
349#define HDSPM_c0_AEB1 0x20000
350#define HDSPM_c0_AEB2 0x40000
351#define HDSPM_c0_LineOut 0x80000
352#define HDSPM_c0_AD_GAIN0 0x100000
353#define HDSPM_c0_AD_GAIN1 0x200000
354#define HDSPM_c0_DA_GAIN0 0x400000
355#define HDSPM_c0_DA_GAIN1 0x800000
356#define HDSPM_c0_PH_GAIN0 0x1000000
357#define HDSPM_c0_PH_GAIN1 0x2000000
358#define HDSPM_c0_Sym6db 0x4000000
359
360
Takashi Iwai763f3562005-06-03 11:25:34 +0200361/* --- bit helper defines */
362#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200363#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|\
364 HDSPM_DoubleSpeed|HDSPM_QuadSpeed)
Takashi Iwai763f3562005-06-03 11:25:34 +0200365#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1)
366#define HDSPM_InputOptical 0
367#define HDSPM_InputCoaxial (HDSPM_InputSelect0)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200368#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\
369 HDSPM_SyncRef2|HDSPM_SyncRef3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200370
Adrian Knoth0dca1792011-01-26 19:32:14 +0100371#define HDSPM_c0_SyncRef0 0x2
372#define HDSPM_c0_SyncRef1 0x4
373#define HDSPM_c0_SyncRef2 0x8
374#define HDSPM_c0_SyncRef3 0x10
375#define HDSPM_c0_SyncRefMask (HDSPM_c0_SyncRef0 | HDSPM_c0_SyncRef1 |\
376 HDSPM_c0_SyncRef2 | HDSPM_c0_SyncRef3)
377
378#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */
379#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */
380#define HDSPM_SYNC_FROM_TCO 2
381#define HDSPM_SYNC_FROM_SYNC_IN 3
Takashi Iwai763f3562005-06-03 11:25:34 +0200382
383#define HDSPM_Frequency32KHz HDSPM_Frequency0
384#define HDSPM_Frequency44_1KHz HDSPM_Frequency1
385#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0)
386#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0)
387#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200388#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|\
389 HDSPM_Frequency0)
Remy Bruno3cee5a62006-10-16 12:46:32 +0200390#define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0)
391#define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200392#define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\
393 HDSPM_Frequency0)
Takashi Iwai763f3562005-06-03 11:25:34 +0200394
Takashi Iwai763f3562005-06-03 11:25:34 +0200395
396/* Synccheck Status */
397#define HDSPM_SYNC_CHECK_NO_LOCK 0
398#define HDSPM_SYNC_CHECK_LOCK 1
399#define HDSPM_SYNC_CHECK_SYNC 2
400
401/* AutoSync References - used by "autosync_ref" control switch */
402#define HDSPM_AUTOSYNC_FROM_WORD 0
403#define HDSPM_AUTOSYNC_FROM_MADI 1
Adrian Knoth0dca1792011-01-26 19:32:14 +0100404#define HDSPM_AUTOSYNC_FROM_TCO 2
405#define HDSPM_AUTOSYNC_FROM_SYNC_IN 3
406#define HDSPM_AUTOSYNC_FROM_NONE 4
Takashi Iwai763f3562005-06-03 11:25:34 +0200407
408/* Possible sources of MADI input */
409#define HDSPM_OPTICAL 0 /* optical */
410#define HDSPM_COAXIAL 1 /* BNC */
411
412#define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask)
Adrian Knoth0dca1792011-01-26 19:32:14 +0100413#define hdspm_decode_latency(x) ((((x) & HDSPM_LatencyMask)>>1))
Takashi Iwai763f3562005-06-03 11:25:34 +0200414
415#define hdspm_encode_in(x) (((x)&0x3)<<14)
416#define hdspm_decode_in(x) (((x)>>14)&0x3)
417
418/* --- control2 register bits --- */
419#define HDSPM_TMS (1<<0)
420#define HDSPM_TCK (1<<1)
421#define HDSPM_TDI (1<<2)
422#define HDSPM_JTAG (1<<3)
423#define HDSPM_PWDN (1<<4)
424#define HDSPM_PROGRAM (1<<5)
425#define HDSPM_CONFIG_MODE_0 (1<<6)
426#define HDSPM_CONFIG_MODE_1 (1<<7)
427/*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/
428#define HDSPM_BIGENDIAN_MODE (1<<9)
429#define HDSPM_RD_MULTIPLE (1<<10)
430
Remy Bruno3cee5a62006-10-16 12:46:32 +0200431/* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200432 that do not conflict with specific bits for AES32 seem to be valid also
433 for the AES32
434 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200435#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200436#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn MODE=0 */
437#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1
438 * (like inp0)
439 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100440
Takashi Iwai763f3562005-06-03 11:25:34 +0200441#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100442#define HDSPM_madiSync (1<<18) /* MADI is in sync */
443
Adrian Knothb0bf5502013-07-05 11:28:05 +0200444#define HDSPM_tcoLockMadi 0x00000020 /* Optional TCO locked status for HDSPe MADI*/
445#define HDSPM_tcoSync 0x10000000 /* Optional TCO sync status for HDSPe MADI and AES32!*/
Adrian Knoth0dca1792011-01-26 19:32:14 +0100446
Adrian Knothb0bf5502013-07-05 11:28:05 +0200447#define HDSPM_syncInLock 0x00010000 /* Sync In lock status for HDSPe MADI! */
448#define HDSPM_syncInSync 0x00020000 /* Sync In sync status for HDSPe MADI! */
Takashi Iwai763f3562005-06-03 11:25:34 +0200449
450#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100451 /* since 64byte accurate, last 6 bits are not used */
Takashi Iwai763f3562005-06-03 11:25:34 +0200452
Adrian Knoth0dca1792011-01-26 19:32:14 +0100453
454
Takashi Iwai763f3562005-06-03 11:25:34 +0200455#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */
456
457#define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */
458#define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */
459#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */
460#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */
461
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200462#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with
463 * Interrupt
464 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100465#define HDSPM_tco_detect 0x08000000
Adrian Knothb0bf5502013-07-05 11:28:05 +0200466#define HDSPM_tcoLockAes 0x20000000 /* Optional TCO locked status for HDSPe AES */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100467
468#define HDSPM_s2_tco_detect 0x00000040
469#define HDSPM_s2_AEBO_D 0x00000080
470#define HDSPM_s2_AEBI_D 0x00000100
471
472
473#define HDSPM_midi0IRQPending 0x40000000
474#define HDSPM_midi1IRQPending 0x80000000
475#define HDSPM_midi2IRQPending 0x20000000
476#define HDSPM_midi2IRQPendingAES 0x00000020
477#define HDSPM_midi3IRQPending 0x00200000
Takashi Iwai763f3562005-06-03 11:25:34 +0200478
479/* --- status bit helpers */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200480#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\
481 HDSPM_madiFreq2|HDSPM_madiFreq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200482#define HDSPM_madiFreq32 (HDSPM_madiFreq0)
483#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1)
484#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1)
485#define HDSPM_madiFreq64 (HDSPM_madiFreq2)
486#define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2)
487#define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2)
488#define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2)
489#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
490#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0)
491
Remy Bruno3cee5a62006-10-16 12:46:32 +0200492/* Status2 Register bits */ /* MADI ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200493
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300494#define HDSPM_version0 (1<<0) /* not really defined but I guess */
Takashi Iwai763f3562005-06-03 11:25:34 +0200495#define HDSPM_version1 (1<<1) /* in former cards it was ??? */
496#define HDSPM_version2 (1<<2)
497
498#define HDSPM_wcLock (1<<3) /* Wordclock is detected and locked */
499#define HDSPM_wcSync (1<<4) /* Wordclock is in sync with systemclock */
500
501#define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */
502#define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */
Adrian Knotha8cd7142013-05-31 12:57:09 +0200503#define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, 111=128 */
504#define HDSPM_wc_freq3 0x800 /* 1000=176.4, 1001=192 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200505
Adrian Knoth0dca1792011-01-26 19:32:14 +0100506#define HDSPM_SyncRef0 0x10000 /* Sync Reference */
507#define HDSPM_SyncRef1 0x20000
508
509#define HDSPM_SelSyncRef0 (1<<8) /* AutoSync Source */
Takashi Iwai763f3562005-06-03 11:25:34 +0200510#define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */
511#define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */
512
513#define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync)
514
Adrian Knotha8cd7142013-05-31 12:57:09 +0200515#define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2|\
516 HDSPM_wc_freq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200517#define HDSPM_wcFreq32 (HDSPM_wc_freq0)
518#define HDSPM_wcFreq44_1 (HDSPM_wc_freq1)
519#define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1)
520#define HDSPM_wcFreq64 (HDSPM_wc_freq2)
521#define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2)
522#define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2)
Adrian Knotha8cd7142013-05-31 12:57:09 +0200523#define HDSPM_wcFreq128 (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2)
524#define HDSPM_wcFreq176_4 (HDSPM_wc_freq3)
525#define HDSPM_wcFreq192 (HDSPM_wc_freq0|HDSPM_wc_freq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200526
Adrian Knoth0dca1792011-01-26 19:32:14 +0100527#define HDSPM_status1_F_0 0x0400000
528#define HDSPM_status1_F_1 0x0800000
529#define HDSPM_status1_F_2 0x1000000
530#define HDSPM_status1_F_3 0x2000000
531#define HDSPM_status1_freqMask (HDSPM_status1_F_0|HDSPM_status1_F_1|HDSPM_status1_F_2|HDSPM_status1_F_3)
532
Takashi Iwai763f3562005-06-03 11:25:34 +0200533
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200534#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
535 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200536#define HDSPM_SelSyncRef_WORD 0
537#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0)
Adrian Knoth0dca1792011-01-26 19:32:14 +0100538#define HDSPM_SelSyncRef_TCO (HDSPM_SelSyncRef1)
539#define HDSPM_SelSyncRef_SyncIn (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200540#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
541 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200542
Remy Bruno3cee5a62006-10-16 12:46:32 +0200543/*
544 For AES32, bits for status, status2 and timecode are different
545*/
546/* status */
547#define HDSPM_AES32_wcLock 0x0200000
Andre Schramm56bde0f2013-01-09 14:40:18 +0100548#define HDSPM_AES32_wcSync 0x0100000
Remy Bruno3cee5a62006-10-16 12:46:32 +0200549#define HDSPM_AES32_wcFreq_bit 22
Adrian Knoth0dca1792011-01-26 19:32:14 +0100550/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function
Remy Bruno3cee5a62006-10-16 12:46:32 +0200551 HDSPM_bit2freq */
552#define HDSPM_AES32_syncref_bit 16
553/* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */
554
555#define HDSPM_AES32_AUTOSYNC_FROM_WORD 0
556#define HDSPM_AES32_AUTOSYNC_FROM_AES1 1
557#define HDSPM_AES32_AUTOSYNC_FROM_AES2 2
558#define HDSPM_AES32_AUTOSYNC_FROM_AES3 3
559#define HDSPM_AES32_AUTOSYNC_FROM_AES4 4
560#define HDSPM_AES32_AUTOSYNC_FROM_AES5 5
561#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6
562#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7
563#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8
Adrian Knothb0bf5502013-07-05 11:28:05 +0200564#define HDSPM_AES32_AUTOSYNC_FROM_TCO 9
565#define HDSPM_AES32_AUTOSYNC_FROM_SYNC_IN 10
566#define HDSPM_AES32_AUTOSYNC_FROM_NONE 11
Remy Bruno3cee5a62006-10-16 12:46:32 +0200567
568/* status2 */
569/* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */
570#define HDSPM_LockAES 0x80
571#define HDSPM_LockAES1 0x80
572#define HDSPM_LockAES2 0x40
573#define HDSPM_LockAES3 0x20
574#define HDSPM_LockAES4 0x10
575#define HDSPM_LockAES5 0x8
576#define HDSPM_LockAES6 0x4
577#define HDSPM_LockAES7 0x2
578#define HDSPM_LockAES8 0x1
579/*
580 Timecode
581 After windows driver sources, bits 4*i to 4*i+3 give the input frequency on
582 AES i+1
583 bits 3210
584 0001 32kHz
585 0010 44.1kHz
586 0011 48kHz
587 0100 64kHz
588 0101 88.2kHz
589 0110 96kHz
590 0111 128kHz
591 1000 176.4kHz
592 1001 192kHz
593 NB: Timecode register doesn't seem to work on AES32 card revision 230
594*/
595
Takashi Iwai763f3562005-06-03 11:25:34 +0200596/* Mixer Values */
597#define UNITY_GAIN 32768 /* = 65536/2 */
598#define MINUS_INFINITY_GAIN 0
599
Takashi Iwai763f3562005-06-03 11:25:34 +0200600/* Number of channels for different Speed Modes */
601#define MADI_SS_CHANNELS 64
602#define MADI_DS_CHANNELS 32
603#define MADI_QS_CHANNELS 16
604
Adrian Knoth0dca1792011-01-26 19:32:14 +0100605#define RAYDAT_SS_CHANNELS 36
606#define RAYDAT_DS_CHANNELS 20
607#define RAYDAT_QS_CHANNELS 12
608
609#define AIO_IN_SS_CHANNELS 14
610#define AIO_IN_DS_CHANNELS 10
611#define AIO_IN_QS_CHANNELS 8
612#define AIO_OUT_SS_CHANNELS 16
613#define AIO_OUT_DS_CHANNELS 12
614#define AIO_OUT_QS_CHANNELS 10
615
Adrian Knothd2d10a22011-02-28 15:14:47 +0100616#define AES32_CHANNELS 16
617
Takashi Iwai763f3562005-06-03 11:25:34 +0200618/* the size of a substream (1 mono data stream) */
619#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024)
620#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
621
622/* the size of the area we need to allocate for DMA transfers. the
623 size is the same regardless of the number of channels, and
Adrian Knoth0dca1792011-01-26 19:32:14 +0100624 also the latency to use.
Takashi Iwai763f3562005-06-03 11:25:34 +0200625 for one direction !!!
626*/
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100627#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
Takashi Iwai763f3562005-06-03 11:25:34 +0200628#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
629
Adrian Knoth0dca1792011-01-26 19:32:14 +0100630#define HDSPM_RAYDAT_REV 211
631#define HDSPM_AIO_REV 212
632#define HDSPM_MADIFACE_REV 213
Remy Bruno3cee5a62006-10-16 12:46:32 +0200633
Remy Bruno65345992007-08-31 12:21:08 +0200634/* speed factor modes */
635#define HDSPM_SPEED_SINGLE 0
636#define HDSPM_SPEED_DOUBLE 1
637#define HDSPM_SPEED_QUAD 2
Adrian Knoth0dca1792011-01-26 19:32:14 +0100638
Remy Bruno65345992007-08-31 12:21:08 +0200639/* names for speed modes */
Takashi Iwaie315cc32020-01-05 15:47:34 +0100640static const char * const hdspm_speed_names[] = { "single", "double", "quad" };
Remy Bruno65345992007-08-31 12:21:08 +0200641
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200642static const char *const texts_autosync_aes_tco[] = { "Word Clock",
Adrian Knoth0dca1792011-01-26 19:32:14 +0100643 "AES1", "AES2", "AES3", "AES4",
644 "AES5", "AES6", "AES7", "AES8",
Adrian Knothdb2d1a92013-07-05 11:28:08 +0200645 "TCO", "Sync In"
646};
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200647static const char *const texts_autosync_aes[] = { "Word Clock",
Adrian Knoth0dca1792011-01-26 19:32:14 +0100648 "AES1", "AES2", "AES3", "AES4",
Adrian Knothdb2d1a92013-07-05 11:28:08 +0200649 "AES5", "AES6", "AES7", "AES8",
650 "Sync In"
651};
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200652static const char *const texts_autosync_madi_tco[] = { "Word Clock",
Adrian Knoth0dca1792011-01-26 19:32:14 +0100653 "MADI", "TCO", "Sync In" };
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200654static const char *const texts_autosync_madi[] = { "Word Clock",
Adrian Knoth0dca1792011-01-26 19:32:14 +0100655 "MADI", "Sync In" };
656
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200657static const char *const texts_autosync_raydat_tco[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100658 "Word Clock",
659 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
660 "AES", "SPDIF", "TCO", "Sync In"
661};
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200662static const char *const texts_autosync_raydat[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100663 "Word Clock",
664 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
665 "AES", "SPDIF", "Sync In"
666};
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200667static const char *const texts_autosync_aio_tco[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100668 "Word Clock",
669 "ADAT", "AES", "SPDIF", "TCO", "Sync In"
670};
Adrian Knotheb0d4db2013-07-05 11:28:21 +0200671static const char *const texts_autosync_aio[] = { "Word Clock",
Adrian Knoth0dca1792011-01-26 19:32:14 +0100672 "ADAT", "AES", "SPDIF", "Sync In" };
673
Adrian Knoth38816542013-07-05 11:28:20 +0200674static const char *const texts_freq[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100675 "No Lock",
676 "32 kHz",
677 "44.1 kHz",
678 "48 kHz",
679 "64 kHz",
680 "88.2 kHz",
681 "96 kHz",
682 "128 kHz",
683 "176.4 kHz",
684 "192 kHz"
685};
686
Takashi Iwaie315cc32020-01-05 15:47:34 +0100687static const char * const texts_ports_madi[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100688 "MADI.1", "MADI.2", "MADI.3", "MADI.4", "MADI.5", "MADI.6",
689 "MADI.7", "MADI.8", "MADI.9", "MADI.10", "MADI.11", "MADI.12",
690 "MADI.13", "MADI.14", "MADI.15", "MADI.16", "MADI.17", "MADI.18",
691 "MADI.19", "MADI.20", "MADI.21", "MADI.22", "MADI.23", "MADI.24",
692 "MADI.25", "MADI.26", "MADI.27", "MADI.28", "MADI.29", "MADI.30",
693 "MADI.31", "MADI.32", "MADI.33", "MADI.34", "MADI.35", "MADI.36",
694 "MADI.37", "MADI.38", "MADI.39", "MADI.40", "MADI.41", "MADI.42",
695 "MADI.43", "MADI.44", "MADI.45", "MADI.46", "MADI.47", "MADI.48",
696 "MADI.49", "MADI.50", "MADI.51", "MADI.52", "MADI.53", "MADI.54",
697 "MADI.55", "MADI.56", "MADI.57", "MADI.58", "MADI.59", "MADI.60",
698 "MADI.61", "MADI.62", "MADI.63", "MADI.64",
699};
700
701
Takashi Iwaie315cc32020-01-05 15:47:34 +0100702static const char * const texts_ports_raydat_ss[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100703 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT1.5", "ADAT1.6",
704 "ADAT1.7", "ADAT1.8", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
705 "ADAT2.5", "ADAT2.6", "ADAT2.7", "ADAT2.8", "ADAT3.1", "ADAT3.2",
706 "ADAT3.3", "ADAT3.4", "ADAT3.5", "ADAT3.6", "ADAT3.7", "ADAT3.8",
707 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4", "ADAT4.5", "ADAT4.6",
708 "ADAT4.7", "ADAT4.8",
709 "AES.L", "AES.R",
710 "SPDIF.L", "SPDIF.R"
711};
712
Takashi Iwaie315cc32020-01-05 15:47:34 +0100713static const char * const texts_ports_raydat_ds[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100714 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4",
715 "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
716 "ADAT3.1", "ADAT3.2", "ADAT3.3", "ADAT3.4",
717 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4",
718 "AES.L", "AES.R",
719 "SPDIF.L", "SPDIF.R"
720};
721
Takashi Iwaie315cc32020-01-05 15:47:34 +0100722static const char * const texts_ports_raydat_qs[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100723 "ADAT1.1", "ADAT1.2",
724 "ADAT2.1", "ADAT2.2",
725 "ADAT3.1", "ADAT3.2",
726 "ADAT4.1", "ADAT4.2",
727 "AES.L", "AES.R",
728 "SPDIF.L", "SPDIF.R"
729};
730
731
Takashi Iwaie315cc32020-01-05 15:47:34 +0100732static const char * const texts_ports_aio_in_ss[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100733 "Analogue.L", "Analogue.R",
734 "AES.L", "AES.R",
735 "SPDIF.L", "SPDIF.R",
736 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200737 "ADAT.7", "ADAT.8",
738 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100739};
740
Takashi Iwaie315cc32020-01-05 15:47:34 +0100741static const char * const texts_ports_aio_out_ss[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100742 "Analogue.L", "Analogue.R",
743 "AES.L", "AES.R",
744 "SPDIF.L", "SPDIF.R",
745 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
746 "ADAT.7", "ADAT.8",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200747 "Phone.L", "Phone.R",
748 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100749};
750
Takashi Iwaie315cc32020-01-05 15:47:34 +0100751static const char * const texts_ports_aio_in_ds[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100752 "Analogue.L", "Analogue.R",
753 "AES.L", "AES.R",
754 "SPDIF.L", "SPDIF.R",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200755 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
756 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100757};
758
Takashi Iwaie315cc32020-01-05 15:47:34 +0100759static const char * const texts_ports_aio_out_ds[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100760 "Analogue.L", "Analogue.R",
761 "AES.L", "AES.R",
762 "SPDIF.L", "SPDIF.R",
763 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200764 "Phone.L", "Phone.R",
765 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100766};
767
Takashi Iwaie315cc32020-01-05 15:47:34 +0100768static const char * const texts_ports_aio_in_qs[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100769 "Analogue.L", "Analogue.R",
770 "AES.L", "AES.R",
771 "SPDIF.L", "SPDIF.R",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200772 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
773 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100774};
775
Takashi Iwaie315cc32020-01-05 15:47:34 +0100776static const char * const texts_ports_aio_out_qs[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +0100777 "Analogue.L", "Analogue.R",
778 "AES.L", "AES.R",
779 "SPDIF.L", "SPDIF.R",
780 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
Adrian Knoth3de9db22013-07-05 11:28:02 +0200781 "Phone.L", "Phone.R",
782 "AEB.1", "AEB.2", "AEB.3", "AEB.4"
Adrian Knoth0dca1792011-01-26 19:32:14 +0100783};
784
Takashi Iwaie315cc32020-01-05 15:47:34 +0100785static const char * const texts_ports_aes32[] = {
Adrian Knoth432d2502011-02-23 11:43:08 +0100786 "AES.1", "AES.2", "AES.3", "AES.4", "AES.5", "AES.6", "AES.7",
787 "AES.8", "AES.9.", "AES.10", "AES.11", "AES.12", "AES.13", "AES.14",
788 "AES.15", "AES.16"
789};
790
Adrian Knoth55a57602011-01-27 11:23:15 +0100791/* These tables map the ALSA channels 1..N to the channels that we
792 need to use in order to find the relevant channel buffer. RME
793 refers to this kind of mapping as between "the ADAT channel and
794 the DMA channel." We index it using the logical audio channel,
795 and the value is the DMA channel (i.e. channel buffer number)
796 where the data for that channel can be read/written from/to.
797*/
798
Takashi Iwaie315cc32020-01-05 15:47:34 +0100799static const char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = {
Adrian Knoth55a57602011-01-27 11:23:15 +0100800 0, 1, 2, 3, 4, 5, 6, 7,
801 8, 9, 10, 11, 12, 13, 14, 15,
802 16, 17, 18, 19, 20, 21, 22, 23,
803 24, 25, 26, 27, 28, 29, 30, 31,
804 32, 33, 34, 35, 36, 37, 38, 39,
805 40, 41, 42, 43, 44, 45, 46, 47,
806 48, 49, 50, 51, 52, 53, 54, 55,
807 56, 57, 58, 59, 60, 61, 62, 63
808};
809
Takashi Iwaie315cc32020-01-05 15:47:34 +0100810static const char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = {
Adrian Knoth55a57602011-01-27 11:23:15 +0100811 4, 5, 6, 7, 8, 9, 10, 11, /* ADAT 1 */
812 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT 2 */
813 20, 21, 22, 23, 24, 25, 26, 27, /* ADAT 3 */
814 28, 29, 30, 31, 32, 33, 34, 35, /* ADAT 4 */
815 0, 1, /* AES */
816 2, 3, /* SPDIF */
817 -1, -1, -1, -1,
818 -1, -1, -1, -1, -1, -1, -1, -1,
819 -1, -1, -1, -1, -1, -1, -1, -1,
820 -1, -1, -1, -1, -1, -1, -1, -1,
821};
822
Takashi Iwaie315cc32020-01-05 15:47:34 +0100823static const char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = {
Adrian Knoth55a57602011-01-27 11:23:15 +0100824 4, 5, 6, 7, /* ADAT 1 */
825 8, 9, 10, 11, /* ADAT 2 */
826 12, 13, 14, 15, /* ADAT 3 */
827 16, 17, 18, 19, /* ADAT 4 */
828 0, 1, /* AES */
829 2, 3, /* SPDIF */
830 -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 -1, -1, -1, -1, -1, -1, -1, -1,
836};
837
Takashi Iwaie315cc32020-01-05 15:47:34 +0100838static const char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = {
Adrian Knoth55a57602011-01-27 11:23:15 +0100839 4, 5, /* ADAT 1 */
840 6, 7, /* ADAT 2 */
841 8, 9, /* ADAT 3 */
842 10, 11, /* ADAT 4 */
843 0, 1, /* AES */
844 2, 3, /* SPDIF */
845 -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 -1, -1, -1, -1, -1, -1, -1, -1,
852};
853
Takashi Iwaie315cc32020-01-05 15:47:34 +0100854static const char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = {
Adrian Knoth55a57602011-01-27 11:23:15 +0100855 0, 1, /* line in */
856 8, 9, /* aes in, */
857 10, 11, /* spdif in */
858 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT in */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200859 2, 3, 4, 5, /* AEB */
860 -1, -1, -1, -1, -1, -1,
Adrian Knoth55a57602011-01-27 11:23:15 +0100861 -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 -1, -1, -1, -1, -1, -1, -1, -1,
866};
867
Takashi Iwaie315cc32020-01-05 15:47:34 +0100868static const char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = {
Adrian Knoth55a57602011-01-27 11:23:15 +0100869 0, 1, /* line out */
870 8, 9, /* aes out */
871 10, 11, /* spdif out */
872 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT out */
873 6, 7, /* phone out */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200874 2, 3, 4, 5, /* AEB */
875 -1, -1, -1, -1,
Adrian Knoth55a57602011-01-27 11:23:15 +0100876 -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 -1, -1, -1, -1, -1, -1, -1, -1,
881};
882
Takashi Iwaie315cc32020-01-05 15:47:34 +0100883static const char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = {
Adrian Knoth55a57602011-01-27 11:23:15 +0100884 0, 1, /* line in */
885 8, 9, /* aes in */
886 10, 11, /* spdif in */
887 12, 14, 16, 18, /* adat in */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200888 2, 3, 4, 5, /* AEB */
889 -1, -1,
Adrian Knoth55a57602011-01-27 11:23:15 +0100890 -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 -1, -1, -1, -1, -1, -1, -1, -1
896};
897
Takashi Iwaie315cc32020-01-05 15:47:34 +0100898static const char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = {
Adrian Knoth55a57602011-01-27 11:23:15 +0100899 0, 1, /* line out */
900 8, 9, /* aes out */
901 10, 11, /* spdif out */
902 12, 14, 16, 18, /* adat out */
903 6, 7, /* phone out */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200904 2, 3, 4, 5, /* AEB */
Adrian Knoth55a57602011-01-27 11:23:15 +0100905 -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 -1, -1, -1, -1, -1, -1, -1, -1
911};
912
Takashi Iwaie315cc32020-01-05 15:47:34 +0100913static const char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = {
Adrian Knoth55a57602011-01-27 11:23:15 +0100914 0, 1, /* line in */
915 8, 9, /* aes in */
916 10, 11, /* spdif in */
917 12, 16, /* adat in */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200918 2, 3, 4, 5, /* AEB */
919 -1, -1, -1, -1,
Adrian Knoth55a57602011-01-27 11:23:15 +0100920 -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 -1, -1, -1, -1, -1, -1, -1, -1
926};
927
Takashi Iwaie315cc32020-01-05 15:47:34 +0100928static const char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = {
Adrian Knoth55a57602011-01-27 11:23:15 +0100929 0, 1, /* line out */
930 8, 9, /* aes out */
931 10, 11, /* spdif out */
932 12, 16, /* adat out */
933 6, 7, /* phone out */
Adrian Knoth3de9db22013-07-05 11:28:02 +0200934 2, 3, 4, 5, /* AEB */
935 -1, -1,
Adrian Knoth55a57602011-01-27 11:23:15 +0100936 -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 -1, -1, -1, -1, -1, -1, -1, -1
942};
943
Takashi Iwaie315cc32020-01-05 15:47:34 +0100944static const char channel_map_aes32[HDSPM_MAX_CHANNELS] = {
Adrian Knoth432d2502011-02-23 11:43:08 +0100945 0, 1, 2, 3, 4, 5, 6, 7,
946 8, 9, 10, 11, 12, 13, 14, 15,
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 -1, -1, -1, -1, -1, -1, -1, -1
953};
954
Takashi Iwai98274f02005-11-17 14:52:34 +0100955struct hdspm_midi {
956 struct hdspm *hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +0200957 int id;
Takashi Iwai98274f02005-11-17 14:52:34 +0100958 struct snd_rawmidi *rmidi;
959 struct snd_rawmidi_substream *input;
960 struct snd_rawmidi_substream *output;
Takashi Iwai763f3562005-06-03 11:25:34 +0200961 char istimer; /* timer in use */
962 struct timer_list timer;
963 spinlock_t lock;
964 int pending;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100965 int dataIn;
966 int statusIn;
967 int dataOut;
968 int statusOut;
969 int ie;
970 int irq;
971};
972
973struct hdspm_tco {
Martin Dausel69358fc2013-07-05 11:28:23 +0200974 int input; /* 0: LTC, 1:Video, 2: WC*/
975 int framerate; /* 0=24, 1=25, 2=29.97, 3=29.97d, 4=30, 5=30d */
976 int wordclock; /* 0=1:1, 1=44.1->48, 2=48->44.1 */
977 int samplerate; /* 0=44.1, 1=48, 2= freq from app */
978 int pull; /* 0=0, 1=+0.1%, 2=-0.1%, 3=+4%, 4=-4%*/
Adrian Knoth0dca1792011-01-26 19:32:14 +0100979 int term; /* 0 = off, 1 = on */
Takashi Iwai763f3562005-06-03 11:25:34 +0200980};
981
Takashi Iwai98274f02005-11-17 14:52:34 +0100982struct hdspm {
Takashi Iwai763f3562005-06-03 11:25:34 +0200983 spinlock_t lock;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200984 /* only one playback and/or capture stream */
985 struct snd_pcm_substream *capture_substream;
986 struct snd_pcm_substream *playback_substream;
Takashi Iwai763f3562005-06-03 11:25:34 +0200987
988 char *card_name; /* for procinfo */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200989 unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
990
Adrian Knoth0dca1792011-01-26 19:32:14 +0100991 uint8_t io_type;
Takashi Iwai763f3562005-06-03 11:25:34 +0200992
Takashi Iwai763f3562005-06-03 11:25:34 +0200993 int monitor_outs; /* set up monitoring outs init flag */
994
995 u32 control_register; /* cached value */
996 u32 control2_register; /* cached value */
Martin Dausel69358fc2013-07-05 11:28:23 +0200997 u32 settings_register; /* cached value for AIO / RayDat (sync reference, master/slave) */
Takashi Iwai763f3562005-06-03 11:25:34 +0200998
Adrian Knoth0dca1792011-01-26 19:32:14 +0100999 struct hdspm_midi midi[4];
Takashi Iwaia2e527c2020-09-03 12:41:27 +02001000 struct work_struct midi_work;
Takashi Iwai763f3562005-06-03 11:25:34 +02001001
1002 size_t period_bytes;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001003 unsigned char ss_in_channels;
1004 unsigned char ds_in_channels;
1005 unsigned char qs_in_channels;
1006 unsigned char ss_out_channels;
1007 unsigned char ds_out_channels;
1008 unsigned char qs_out_channels;
1009
1010 unsigned char max_channels_in;
1011 unsigned char max_channels_out;
1012
Takashi Iwaie315cc32020-01-05 15:47:34 +01001013 const signed char *channel_map_in;
1014 const signed char *channel_map_out;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001015
Takashi Iwaie315cc32020-01-05 15:47:34 +01001016 const signed char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs;
1017 const signed char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001018
Takashi Iwaie315cc32020-01-05 15:47:34 +01001019 const char * const *port_names_in;
1020 const char * const *port_names_out;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001021
Takashi Iwaie315cc32020-01-05 15:47:34 +01001022 const char * const *port_names_in_ss;
1023 const char * const *port_names_in_ds;
1024 const char * const *port_names_in_qs;
1025 const char * const *port_names_out_ss;
1026 const char * const *port_names_out_ds;
1027 const char * const *port_names_out_qs;
Takashi Iwai763f3562005-06-03 11:25:34 +02001028
1029 unsigned char *playback_buffer; /* suitably aligned address */
1030 unsigned char *capture_buffer; /* suitably aligned address */
1031
1032 pid_t capture_pid; /* process id which uses capture */
1033 pid_t playback_pid; /* process id which uses capture */
1034 int running; /* running status */
1035
1036 int last_external_sample_rate; /* samplerate mystic ... */
1037 int last_internal_sample_rate;
1038 int system_sample_rate;
1039
Takashi Iwai763f3562005-06-03 11:25:34 +02001040 int dev; /* Hardware vars... */
1041 int irq;
1042 unsigned long port;
1043 void __iomem *iobase;
1044
1045 int irq_count; /* for debug */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001046 int midiPorts;
Takashi Iwai763f3562005-06-03 11:25:34 +02001047
Takashi Iwai98274f02005-11-17 14:52:34 +01001048 struct snd_card *card; /* one card */
1049 struct snd_pcm *pcm; /* has one pcm */
1050 struct snd_hwdep *hwdep; /* and a hwdep for additional ioctl */
Takashi Iwai763f3562005-06-03 11:25:34 +02001051 struct pci_dev *pci; /* and an pci info */
1052
1053 /* Mixer vars */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001054 /* fast alsa mixer */
1055 struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS];
1056 /* but input to much, so not used */
1057 struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS];
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001058 /* full mixer accessible over mixer ioctl or hwdep-device */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001059 struct hdspm_mixer *mixer;
Takashi Iwai763f3562005-06-03 11:25:34 +02001060
Adrian Knoth0dca1792011-01-26 19:32:14 +01001061 struct hdspm_tco *tco; /* NULL if no TCO detected */
Takashi Iwai763f3562005-06-03 11:25:34 +02001062
Adrian Knotheb0d4db2013-07-05 11:28:21 +02001063 const char *const *texts_autosync;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001064 int texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +02001065
Adrian Knoth0dca1792011-01-26 19:32:14 +01001066 cycles_t last_interrupt;
Jaroslav Kysela730a5862011-01-27 13:03:15 +01001067
Adrian Knoth7d53a632012-01-04 14:31:16 +01001068 unsigned int serial;
1069
Jaroslav Kysela730a5862011-01-27 13:03:15 +01001070 struct hdspm_peak_rms peak_rms;
Takashi Iwai763f3562005-06-03 11:25:34 +02001071};
1072
Takashi Iwai763f3562005-06-03 11:25:34 +02001073
Benoit Taine9baa3c32014-08-08 15:56:03 +02001074static const struct pci_device_id snd_hdspm_ids[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02001075 {
1076 .vendor = PCI_VENDOR_ID_XILINX,
1077 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
1078 .subvendor = PCI_ANY_ID,
1079 .subdevice = PCI_ANY_ID,
1080 .class = 0,
1081 .class_mask = 0,
1082 .driver_data = 0},
1083 {0,}
1084};
1085
1086MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
1087
1088/* prototypes */
Bill Pembertone23e7a12012-12-06 12:35:10 -05001089static int snd_hdspm_create_alsa_devices(struct snd_card *card,
1090 struct hdspm *hdspm);
1091static int snd_hdspm_create_pcm(struct snd_card *card,
1092 struct hdspm *hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001093
Adrian Knoth0dca1792011-01-26 19:32:14 +01001094static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
Adrian Knoth3f7bf912013-03-10 00:37:21 +01001095static inline int hdspm_get_pll_freq(struct hdspm *hdspm);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001096static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
1097static int hdspm_autosync_ref(struct hdspm *hdspm);
Adrian Knoth34be7ebb2013-07-05 11:27:56 +02001098static int hdspm_set_toggle_setting(struct hdspm *hdspm, u32 regmask, int out);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001099static int snd_hdspm_set_defaults(struct hdspm *hdspm);
Adrian Knoth21a164d2012-10-19 17:42:23 +02001100static int hdspm_system_clock_mode(struct hdspm *hdspm);
Philippe Bekaerte4e07c62019-05-23 23:56:49 +02001101static void hdspm_set_channel_dma_addr(struct hdspm *hdspm,
1102 struct snd_pcm_substream *substream,
1103 unsigned int reg, int channels);
Takashi Iwai763f3562005-06-03 11:25:34 +02001104
Adrian Knoth5b266352013-07-05 11:28:10 +02001105static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx);
1106static int hdspm_wc_sync_check(struct hdspm *hdspm);
1107static int hdspm_tco_sync_check(struct hdspm *hdspm);
1108static int hdspm_sync_in_sync_check(struct hdspm *hdspm);
1109
1110static int hdspm_get_aes_sample_rate(struct hdspm *hdspm, int index);
1111static int hdspm_get_tco_sample_rate(struct hdspm *hdspm);
1112static int hdspm_get_wc_sample_rate(struct hdspm *hdspm);
1113
1114
1115
Remy Bruno3cee5a62006-10-16 12:46:32 +02001116static inline int HDSPM_bit2freq(int n)
1117{
Denys Vlasenko62cef822008-04-14 13:04:18 +02001118 static const int bit2freq_tab[] = {
1119 0, 32000, 44100, 48000, 64000, 88200,
Remy Bruno3cee5a62006-10-16 12:46:32 +02001120 96000, 128000, 176400, 192000 };
1121 if (n < 1 || n > 9)
1122 return 0;
1123 return bit2freq_tab[n];
1124}
1125
Adrian Knothb2ed6322013-07-05 11:27:54 +02001126static bool hdspm_is_raydat_or_aio(struct hdspm *hdspm)
1127{
1128 return ((AIO == hdspm->io_type) || (RayDAT == hdspm->io_type));
1129}
1130
1131
Adrian Knoth0dca1792011-01-26 19:32:14 +01001132/* Write/read to/from HDSPM with Adresses in Bytes
Takashi Iwai763f3562005-06-03 11:25:34 +02001133 not words but only 32Bit writes are allowed */
1134
Takashi Iwai98274f02005-11-17 14:52:34 +01001135static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
Takashi Iwai763f3562005-06-03 11:25:34 +02001136 unsigned int val)
1137{
1138 writel(val, hdspm->iobase + reg);
1139}
1140
Takashi Iwai98274f02005-11-17 14:52:34 +01001141static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
Takashi Iwai763f3562005-06-03 11:25:34 +02001142{
1143 return readl(hdspm->iobase + reg);
1144}
1145
Adrian Knoth0dca1792011-01-26 19:32:14 +01001146/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
1147 mixer is write only on hardware so we have to cache him for read
Takashi Iwai763f3562005-06-03 11:25:34 +02001148 each fader is a u32, but uses only the first 16 bit */
1149
Takashi Iwai98274f02005-11-17 14:52:34 +01001150static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001151 unsigned int in)
1152{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001153 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001154 return 0;
1155
1156 return hdspm->mixer->ch[chan].in[in];
1157}
1158
Takashi Iwai98274f02005-11-17 14:52:34 +01001159static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001160 unsigned int pb)
1161{
Adrian Bunk5bab24822006-03-13 14:15:04 +01001162 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001163 return 0;
1164 return hdspm->mixer->ch[chan].pb[pb];
1165}
1166
Denys Vlasenko62cef822008-04-14 13:04:18 +02001167static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001168 unsigned int in, unsigned short data)
1169{
1170 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
1171 return -1;
1172
1173 hdspm_write(hdspm,
1174 HDSPM_MADI_mixerBase +
1175 ((in + 128 * chan) * sizeof(u32)),
1176 (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
1177 return 0;
1178}
1179
Denys Vlasenko62cef822008-04-14 13:04:18 +02001180static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001181 unsigned int pb, unsigned short data)
1182{
1183 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
1184 return -1;
1185
1186 hdspm_write(hdspm,
1187 HDSPM_MADI_mixerBase +
1188 ((64 + pb + 128 * chan) * sizeof(u32)),
1189 (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
1190 return 0;
1191}
1192
1193
1194/* enable DMA for specific channels, now available for DSP-MADI */
Takashi Iwai98274f02005-11-17 14:52:34 +01001195static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001196{
1197 hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
1198}
1199
Takashi Iwai98274f02005-11-17 14:52:34 +01001200static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001201{
1202 hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
1203}
1204
1205/* check if same process is writing and reading */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001206static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001207{
1208 unsigned long flags;
1209 int ret = 1;
1210
1211 spin_lock_irqsave(&hdspm->lock, flags);
1212 if ((hdspm->playback_pid != hdspm->capture_pid) &&
1213 (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
1214 ret = 0;
1215 }
1216 spin_unlock_irqrestore(&hdspm->lock, flags);
1217 return ret;
1218}
1219
Naoki Hayama7dcd5612020-10-08 17:47:44 +09001220/* round arbitrary sample rates to commonly known rates */
Adrian Knothfcdc4ba2013-03-10 00:37:22 +01001221static int hdspm_round_frequency(int rate)
1222{
1223 if (rate < 38050)
1224 return 32000;
1225 if (rate < 46008)
1226 return 44100;
1227 else
1228 return 48000;
1229}
1230
Adrian Knotha8a729f2013-05-31 12:57:10 +02001231/* QS and DS rates normally can not be detected
1232 * automatically by the card. Only exception is MADI
1233 * in 96k frame mode.
1234 *
1235 * So if we read SS values (32 .. 48k), check for
1236 * user-provided DS/QS bits in the control register
1237 * and multiply the base frequency accordingly.
1238 */
1239static int hdspm_rate_multiplier(struct hdspm *hdspm, int rate)
1240{
1241 if (rate <= 48000) {
1242 if (hdspm->control_register & HDSPM_QuadSpeed)
1243 return rate * 4;
1244 else if (hdspm->control_register &
1245 HDSPM_DoubleSpeed)
1246 return rate * 2;
Fengguang Wu68593c92013-07-15 21:41:32 +08001247 }
Adrian Knotha8a729f2013-05-31 12:57:10 +02001248 return rate;
1249}
1250
Adrian Knoth5b266352013-07-05 11:28:10 +02001251/* check for external sample rate, returns the sample rate in Hz*/
Denys Vlasenko62cef822008-04-14 13:04:18 +02001252static int hdspm_external_sample_rate(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001253{
Sudip Mukherjeedf57de12014-10-29 20:09:45 +05301254 unsigned int status, status2;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001255 int syncref, rate = 0, rate_bits;
Takashi Iwai763f3562005-06-03 11:25:34 +02001256
Adrian Knoth0dca1792011-01-26 19:32:14 +01001257 switch (hdspm->io_type) {
1258 case AES32:
1259 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1260 status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001261
1262 syncref = hdspm_autosync_ref(hdspm);
Adrian Knothdbae4a02013-07-05 11:28:14 +02001263 switch (syncref) {
1264 case HDSPM_AES32_AUTOSYNC_FROM_WORD:
1265 /* Check WC sync and get sample rate */
1266 if (hdspm_wc_sync_check(hdspm))
1267 return HDSPM_bit2freq(hdspm_get_wc_sample_rate(hdspm));
1268 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001269
Adrian Knothdbae4a02013-07-05 11:28:14 +02001270 case HDSPM_AES32_AUTOSYNC_FROM_AES1:
1271 case HDSPM_AES32_AUTOSYNC_FROM_AES2:
1272 case HDSPM_AES32_AUTOSYNC_FROM_AES3:
1273 case HDSPM_AES32_AUTOSYNC_FROM_AES4:
1274 case HDSPM_AES32_AUTOSYNC_FROM_AES5:
1275 case HDSPM_AES32_AUTOSYNC_FROM_AES6:
1276 case HDSPM_AES32_AUTOSYNC_FROM_AES7:
1277 case HDSPM_AES32_AUTOSYNC_FROM_AES8:
1278 /* Check AES sync and get sample rate */
1279 if (hdspm_aes_sync_check(hdspm, syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1))
1280 return HDSPM_bit2freq(hdspm_get_aes_sample_rate(hdspm,
1281 syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1));
1282 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001283
Adrian Knothdbae4a02013-07-05 11:28:14 +02001284
1285 case HDSPM_AES32_AUTOSYNC_FROM_TCO:
1286 /* Check TCO sync and get sample rate */
1287 if (hdspm_tco_sync_check(hdspm))
1288 return HDSPM_bit2freq(hdspm_get_tco_sample_rate(hdspm));
1289 break;
1290 default:
1291 return 0;
1292 } /* end switch(syncref) */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001293 break;
1294
1295 case MADIface:
1296 status = hdspm_read(hdspm, HDSPM_statusRegister);
1297
1298 if (!(status & HDSPM_madiLock)) {
1299 rate = 0; /* no lock */
1300 } else {
1301 switch (status & (HDSPM_status1_freqMask)) {
1302 case HDSPM_status1_F_0*1:
1303 rate = 32000; break;
1304 case HDSPM_status1_F_0*2:
1305 rate = 44100; break;
1306 case HDSPM_status1_F_0*3:
1307 rate = 48000; break;
1308 case HDSPM_status1_F_0*4:
1309 rate = 64000; break;
1310 case HDSPM_status1_F_0*5:
1311 rate = 88200; break;
1312 case HDSPM_status1_F_0*6:
1313 rate = 96000; break;
1314 case HDSPM_status1_F_0*7:
1315 rate = 128000; break;
1316 case HDSPM_status1_F_0*8:
1317 rate = 176400; break;
1318 case HDSPM_status1_F_0*9:
1319 rate = 192000; break;
1320 default:
1321 rate = 0; break;
1322 }
1323 }
1324
1325 break;
1326
1327 case MADI:
1328 case AIO:
1329 case RayDAT:
1330 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1331 status = hdspm_read(hdspm, HDSPM_statusRegister);
1332 rate = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02001333
Remy Bruno3cee5a62006-10-16 12:46:32 +02001334 /* if wordclock has synced freq and wordclock is valid */
1335 if ((status2 & HDSPM_wcLock) != 0 &&
Adrian Knothfedf1532011-06-12 17:26:18 +02001336 (status2 & HDSPM_SelSyncRef0) == 0) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02001337
1338 rate_bits = status2 & HDSPM_wcFreqMask;
1339
Adrian Knoth0dca1792011-01-26 19:32:14 +01001340
Remy Bruno3cee5a62006-10-16 12:46:32 +02001341 switch (rate_bits) {
1342 case HDSPM_wcFreq32:
1343 rate = 32000;
1344 break;
1345 case HDSPM_wcFreq44_1:
1346 rate = 44100;
1347 break;
1348 case HDSPM_wcFreq48:
1349 rate = 48000;
1350 break;
1351 case HDSPM_wcFreq64:
1352 rate = 64000;
1353 break;
1354 case HDSPM_wcFreq88_2:
1355 rate = 88200;
1356 break;
1357 case HDSPM_wcFreq96:
1358 rate = 96000;
1359 break;
Adrian Knotha8cd7142013-05-31 12:57:09 +02001360 case HDSPM_wcFreq128:
1361 rate = 128000;
1362 break;
1363 case HDSPM_wcFreq176_4:
1364 rate = 176400;
1365 break;
1366 case HDSPM_wcFreq192:
1367 rate = 192000;
1368 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001369 default:
1370 rate = 0;
1371 break;
1372 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001373 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001374
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001375 /* if rate detected and Syncref is Word than have it,
1376 * word has priority to MADI
1377 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001378 if (rate != 0 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001379 (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
Adrian Knoth7b559392013-05-31 12:57:11 +02001380 return hdspm_rate_multiplier(hdspm, rate);
Remy Bruno3cee5a62006-10-16 12:46:32 +02001381
Adrian Knoth0dca1792011-01-26 19:32:14 +01001382 /* maybe a madi input (which is taken if sel sync is madi) */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001383 if (status & HDSPM_madiLock) {
1384 rate_bits = status & HDSPM_madiFreqMask;
1385
1386 switch (rate_bits) {
1387 case HDSPM_madiFreq32:
1388 rate = 32000;
1389 break;
1390 case HDSPM_madiFreq44_1:
1391 rate = 44100;
1392 break;
1393 case HDSPM_madiFreq48:
1394 rate = 48000;
1395 break;
1396 case HDSPM_madiFreq64:
1397 rate = 64000;
1398 break;
1399 case HDSPM_madiFreq88_2:
1400 rate = 88200;
1401 break;
1402 case HDSPM_madiFreq96:
1403 rate = 96000;
1404 break;
1405 case HDSPM_madiFreq128:
1406 rate = 128000;
1407 break;
1408 case HDSPM_madiFreq176_4:
1409 rate = 176400;
1410 break;
1411 case HDSPM_madiFreq192:
1412 rate = 192000;
1413 break;
1414 default:
1415 rate = 0;
1416 break;
1417 }
Adrian Knothd12c51d2011-07-29 03:11:03 +02001418
Adrian Knothfcdc4ba2013-03-10 00:37:22 +01001419 } /* endif HDSPM_madiLock */
1420
1421 /* check sample rate from TCO or SYNC_IN */
1422 {
1423 bool is_valid_input = 0;
1424 bool has_sync = 0;
1425
1426 syncref = hdspm_autosync_ref(hdspm);
1427 if (HDSPM_AUTOSYNC_FROM_TCO == syncref) {
1428 is_valid_input = 1;
1429 has_sync = (HDSPM_SYNC_CHECK_SYNC ==
1430 hdspm_tco_sync_check(hdspm));
1431 } else if (HDSPM_AUTOSYNC_FROM_SYNC_IN == syncref) {
1432 is_valid_input = 1;
1433 has_sync = (HDSPM_SYNC_CHECK_SYNC ==
1434 hdspm_sync_in_sync_check(hdspm));
Adrian Knothd12c51d2011-07-29 03:11:03 +02001435 }
Adrian Knothfcdc4ba2013-03-10 00:37:22 +01001436
1437 if (is_valid_input && has_sync) {
1438 rate = hdspm_round_frequency(
1439 hdspm_get_pll_freq(hdspm));
1440 }
1441 }
1442
Adrian Knotha8a729f2013-05-31 12:57:10 +02001443 rate = hdspm_rate_multiplier(hdspm, rate);
1444
Adrian Knoth0dca1792011-01-26 19:32:14 +01001445 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001446 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001447
1448 return rate;
Takashi Iwai763f3562005-06-03 11:25:34 +02001449}
1450
Adrian Knoth7cb155f2011-08-15 00:22:53 +02001451/* return latency in samples per period */
1452static int hdspm_get_latency(struct hdspm *hdspm)
1453{
1454 int n;
1455
1456 n = hdspm_decode_latency(hdspm->control_register);
1457
1458 /* Special case for new RME cards with 32 samples period size.
1459 * The three latency bits in the control register
1460 * (HDSP_LatencyMask) encode latency values of 64 samples as
1461 * 0, 128 samples as 1 ... 4096 samples as 6. For old cards, 7
1462 * denotes 8192 samples, but on new cards like RayDAT or AIO,
1463 * it corresponds to 32 samples.
1464 */
1465 if ((7 == n) && (RayDAT == hdspm->io_type || AIO == hdspm->io_type))
1466 n = -1;
1467
1468 return 1 << (n + 6);
1469}
1470
Takashi Iwai763f3562005-06-03 11:25:34 +02001471/* Latency function */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001472static inline void hdspm_compute_period_size(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001473{
Adrian Knoth7cb155f2011-08-15 00:22:53 +02001474 hdspm->period_bytes = 4 * hdspm_get_latency(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001475}
1476
Adrian Knoth0dca1792011-01-26 19:32:14 +01001477
1478static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001479{
1480 int position;
1481
1482 position = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth483cee72011-02-23 11:43:09 +01001483
1484 switch (hdspm->io_type) {
1485 case RayDAT:
1486 case AIO:
1487 position &= HDSPM_BufferPositionMask;
1488 position /= 4; /* Bytes per sample */
1489 break;
1490 default:
1491 position = (position & HDSPM_BufferID) ?
1492 (hdspm->period_bytes / 4) : 0;
1493 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001494
1495 return position;
1496}
1497
1498
Takashi Iwai98274f02005-11-17 14:52:34 +01001499static inline void hdspm_start_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001500{
1501 s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
1502 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1503}
1504
Takashi Iwai98274f02005-11-17 14:52:34 +01001505static inline void hdspm_stop_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001506{
1507 s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
1508 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1509}
1510
1511/* should I silence all or only opened ones ? doit all for first even is 4MB*/
Denys Vlasenko62cef822008-04-14 13:04:18 +02001512static void hdspm_silence_playback(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001513{
1514 int i;
1515 int n = hdspm->period_bytes;
1516 void *buf = hdspm->playback_buffer;
1517
Markus Elfringda2ea372017-08-12 17:07:09 +02001518 if (!buf)
Remy Bruno3cee5a62006-10-16 12:46:32 +02001519 return;
Takashi Iwai763f3562005-06-03 11:25:34 +02001520
1521 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
1522 memset(buf, 0, n);
1523 buf += HDSPM_CHANNEL_BUFFER_BYTES;
1524 }
1525}
1526
Adrian Knoth0dca1792011-01-26 19:32:14 +01001527static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames)
Takashi Iwai763f3562005-06-03 11:25:34 +02001528{
1529 int n;
1530
1531 spin_lock_irq(&s->lock);
1532
Adrian Knoth2e610272011-08-15 00:22:54 +02001533 if (32 == frames) {
1534 /* Special case for new RME cards like RayDAT/AIO which
1535 * support period sizes of 32 samples. Since latency is
1536 * encoded in the three bits of HDSP_LatencyMask, we can only
1537 * have values from 0 .. 7. While 0 still means 64 samples and
1538 * 6 represents 4096 samples on all cards, 7 represents 8192
1539 * on older cards and 32 samples on new cards.
1540 *
1541 * In other words, period size in samples is calculated by
1542 * 2^(n+6) with n ranging from 0 .. 7.
1543 */
1544 n = 7;
1545 } else {
1546 frames >>= 7;
1547 n = 0;
1548 while (frames) {
1549 n++;
1550 frames >>= 1;
1551 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001552 }
Adrian Knoth2e610272011-08-15 00:22:54 +02001553
Takashi Iwai763f3562005-06-03 11:25:34 +02001554 s->control_register &= ~HDSPM_LatencyMask;
1555 s->control_register |= hdspm_encode_latency(n);
1556
1557 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1558
1559 hdspm_compute_period_size(s);
1560
1561 spin_unlock_irq(&s->lock);
1562
1563 return 0;
1564}
1565
Adrian Knoth0dca1792011-01-26 19:32:14 +01001566static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period)
1567{
1568 u64 freq_const;
1569
1570 if (period == 0)
1571 return 0;
1572
1573 switch (hdspm->io_type) {
1574 case MADI:
1575 case AES32:
1576 freq_const = 110069313433624ULL;
1577 break;
1578 case RayDAT:
1579 case AIO:
1580 freq_const = 104857600000000ULL;
1581 break;
1582 case MADIface:
1583 freq_const = 131072000000000ULL;
Takashi Iwai3d56c8e6b2011-08-05 12:30:12 +02001584 break;
1585 default:
1586 snd_BUG();
1587 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001588 }
1589
1590 return div_u64(freq_const, period);
1591}
1592
1593
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001594static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
1595{
1596 u64 n;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001597
Takashi Iwaic1099c32016-02-29 14:32:42 +01001598 if (snd_BUG_ON(rate <= 0))
1599 return;
1600
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001601 if (rate >= 112000)
1602 rate /= 4;
1603 else if (rate >= 56000)
1604 rate /= 2;
1605
Adrian Knoth0dca1792011-01-26 19:32:14 +01001606 switch (hdspm->io_type) {
1607 case MADIface:
Takashi Iwai3d56c8e6b2011-08-05 12:30:12 +02001608 n = 131072000000000ULL; /* 125 MHz */
1609 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001610 case MADI:
1611 case AES32:
Takashi Iwai3d56c8e6b2011-08-05 12:30:12 +02001612 n = 110069313433624ULL; /* 105 MHz */
1613 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001614 case RayDAT:
1615 case AIO:
Takashi Iwai3d56c8e6b2011-08-05 12:30:12 +02001616 n = 104857600000000ULL; /* 100 MHz */
1617 break;
1618 default:
1619 snd_BUG();
1620 return;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001621 }
1622
Takashi Iwai3f7440a2009-06-05 17:40:04 +02001623 n = div_u64(n, rate);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001624 /* n should be less than 2^32 for being written to FREQ register */
Takashi Iwaida3cec32008-08-08 17:12:14 +02001625 snd_BUG_ON(n >> 32);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001626 hdspm_write(hdspm, HDSPM_freqReg, (u32)n);
1627}
Takashi Iwai763f3562005-06-03 11:25:34 +02001628
1629/* dummy set rate lets see what happens */
Takashi Iwai98274f02005-11-17 14:52:34 +01001630static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
Takashi Iwai763f3562005-06-03 11:25:34 +02001631{
Takashi Iwai763f3562005-06-03 11:25:34 +02001632 int current_rate;
1633 int rate_bits;
1634 int not_set = 0;
Remy Bruno65345992007-08-31 12:21:08 +02001635 int current_speed, target_speed;
Takashi Iwai763f3562005-06-03 11:25:34 +02001636
1637 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
1638 it (e.g. during module initialization).
1639 */
1640
1641 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
1642
Adrian Knoth0dca1792011-01-26 19:32:14 +01001643 /* SLAVE --- */
Takashi Iwai763f3562005-06-03 11:25:34 +02001644 if (called_internally) {
1645
Adrian Knoth0dca1792011-01-26 19:32:14 +01001646 /* request from ctl or card initialization
1647 just make a warning an remember setting
1648 for future master mode switching */
1649
Takashi Iwaie3a471d62014-02-26 12:05:40 +01001650 dev_warn(hdspm->card->dev,
1651 "Warning: device is not running as a clock master.\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001652 not_set = 1;
1653 } else {
1654
1655 /* hw_param request while in AutoSync mode */
1656 int external_freq =
1657 hdspm_external_sample_rate(hdspm);
1658
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001659 if (hdspm_autosync_ref(hdspm) ==
1660 HDSPM_AUTOSYNC_FROM_NONE) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001661
Takashi Iwaie3a471d62014-02-26 12:05:40 +01001662 dev_warn(hdspm->card->dev,
Colin Ian King07cb3272016-08-22 12:50:02 +01001663 "Detected no External Sync\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001664 not_set = 1;
1665
1666 } else if (rate != external_freq) {
1667
Takashi Iwaie3a471d62014-02-26 12:05:40 +01001668 dev_warn(hdspm->card->dev,
1669 "Warning: No AutoSync source for requested rate\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001670 not_set = 1;
1671 }
1672 }
1673 }
1674
1675 current_rate = hdspm->system_sample_rate;
1676
1677 /* Changing between Singe, Double and Quad speed is not
1678 allowed if any substreams are open. This is because such a change
1679 causes a shift in the location of the DMA buffers and a reduction
1680 in the number of available buffers.
1681
1682 Note that a similar but essentially insoluble problem exists for
1683 externally-driven rate changes. All we can do is to flag rate
Adrian Knoth0dca1792011-01-26 19:32:14 +01001684 changes in the read/write routines.
Takashi Iwai763f3562005-06-03 11:25:34 +02001685 */
1686
Remy Bruno65345992007-08-31 12:21:08 +02001687 if (current_rate <= 48000)
1688 current_speed = HDSPM_SPEED_SINGLE;
1689 else if (current_rate <= 96000)
1690 current_speed = HDSPM_SPEED_DOUBLE;
1691 else
1692 current_speed = HDSPM_SPEED_QUAD;
1693
1694 if (rate <= 48000)
1695 target_speed = HDSPM_SPEED_SINGLE;
1696 else if (rate <= 96000)
1697 target_speed = HDSPM_SPEED_DOUBLE;
1698 else
1699 target_speed = HDSPM_SPEED_QUAD;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001700
Takashi Iwai763f3562005-06-03 11:25:34 +02001701 switch (rate) {
1702 case 32000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001703 rate_bits = HDSPM_Frequency32KHz;
1704 break;
1705 case 44100:
Takashi Iwai763f3562005-06-03 11:25:34 +02001706 rate_bits = HDSPM_Frequency44_1KHz;
1707 break;
1708 case 48000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001709 rate_bits = HDSPM_Frequency48KHz;
1710 break;
1711 case 64000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001712 rate_bits = HDSPM_Frequency64KHz;
1713 break;
1714 case 88200:
Takashi Iwai763f3562005-06-03 11:25:34 +02001715 rate_bits = HDSPM_Frequency88_2KHz;
1716 break;
1717 case 96000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001718 rate_bits = HDSPM_Frequency96KHz;
1719 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001720 case 128000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001721 rate_bits = HDSPM_Frequency128KHz;
1722 break;
1723 case 176400:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001724 rate_bits = HDSPM_Frequency176_4KHz;
1725 break;
1726 case 192000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001727 rate_bits = HDSPM_Frequency192KHz;
1728 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001729 default:
1730 return -EINVAL;
1731 }
1732
Remy Bruno65345992007-08-31 12:21:08 +02001733 if (current_speed != target_speed
Takashi Iwai763f3562005-06-03 11:25:34 +02001734 && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01001735 dev_err(hdspm->card->dev,
1736 "cannot change from %s speed to %s speed mode (capture PID = %d, playback PID = %d)\n",
1737 hdspm_speed_names[current_speed],
1738 hdspm_speed_names[target_speed],
1739 hdspm->capture_pid, hdspm->playback_pid);
Takashi Iwai763f3562005-06-03 11:25:34 +02001740 return -EBUSY;
1741 }
1742
1743 hdspm->control_register &= ~HDSPM_FrequencyMask;
1744 hdspm->control_register |= rate_bits;
1745 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1746
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001747 /* For AES32, need to set DDS value in FREQ register
1748 For MADI, also apparently */
1749 hdspm_set_dds_value(hdspm, rate);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001750
1751 if (AES32 == hdspm->io_type && rate != current_rate)
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001752 hdspm_write(hdspm, HDSPM_eeprom_wr, 0);
Takashi Iwai763f3562005-06-03 11:25:34 +02001753
1754 hdspm->system_sample_rate = rate;
1755
Adrian Knoth0dca1792011-01-26 19:32:14 +01001756 if (rate <= 48000) {
1757 hdspm->channel_map_in = hdspm->channel_map_in_ss;
1758 hdspm->channel_map_out = hdspm->channel_map_out_ss;
1759 hdspm->max_channels_in = hdspm->ss_in_channels;
1760 hdspm->max_channels_out = hdspm->ss_out_channels;
1761 hdspm->port_names_in = hdspm->port_names_in_ss;
1762 hdspm->port_names_out = hdspm->port_names_out_ss;
1763 } else if (rate <= 96000) {
1764 hdspm->channel_map_in = hdspm->channel_map_in_ds;
1765 hdspm->channel_map_out = hdspm->channel_map_out_ds;
1766 hdspm->max_channels_in = hdspm->ds_in_channels;
1767 hdspm->max_channels_out = hdspm->ds_out_channels;
1768 hdspm->port_names_in = hdspm->port_names_in_ds;
1769 hdspm->port_names_out = hdspm->port_names_out_ds;
1770 } else {
1771 hdspm->channel_map_in = hdspm->channel_map_in_qs;
1772 hdspm->channel_map_out = hdspm->channel_map_out_qs;
1773 hdspm->max_channels_in = hdspm->qs_in_channels;
1774 hdspm->max_channels_out = hdspm->qs_out_channels;
1775 hdspm->port_names_in = hdspm->port_names_in_qs;
1776 hdspm->port_names_out = hdspm->port_names_out_qs;
1777 }
1778
Takashi Iwai763f3562005-06-03 11:25:34 +02001779 if (not_set != 0)
1780 return -1;
1781
1782 return 0;
1783}
1784
1785/* mainly for init to 0 on load */
Takashi Iwai98274f02005-11-17 14:52:34 +01001786static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
Takashi Iwai763f3562005-06-03 11:25:34 +02001787{
1788 int i, j;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001789 unsigned int gain;
1790
1791 if (sgain > UNITY_GAIN)
1792 gain = UNITY_GAIN;
1793 else if (sgain < 0)
1794 gain = 0;
1795 else
1796 gain = sgain;
Takashi Iwai763f3562005-06-03 11:25:34 +02001797
1798 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
1799 for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
1800 hdspm_write_in_gain(hdspm, i, j, gain);
1801 hdspm_write_pb_gain(hdspm, i, j, gain);
1802 }
1803}
1804
1805/*----------------------------------------------------------------------------
1806 MIDI
1807 ----------------------------------------------------------------------------*/
1808
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001809static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm,
1810 int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001811{
1812 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001813 return hdspm_read(hdspm, hdspm->midi[id].dataIn);
Takashi Iwai763f3562005-06-03 11:25:34 +02001814}
1815
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001816static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
1817 int val)
Takashi Iwai763f3562005-06-03 11:25:34 +02001818{
1819 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001820 return hdspm_write(hdspm, hdspm->midi[id].dataOut, val);
Takashi Iwai763f3562005-06-03 11:25:34 +02001821}
1822
Takashi Iwai98274f02005-11-17 14:52:34 +01001823static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001824{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001825 return hdspm_read(hdspm, hdspm->midi[id].statusIn) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001826}
1827
Takashi Iwai98274f02005-11-17 14:52:34 +01001828static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001829{
1830 int fifo_bytes_used;
1831
Adrian Knoth0dca1792011-01-26 19:32:14 +01001832 fifo_bytes_used = hdspm_read(hdspm, hdspm->midi[id].statusOut) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001833
1834 if (fifo_bytes_used < 128)
1835 return 128 - fifo_bytes_used;
1836 else
1837 return 0;
1838}
1839
Denys Vlasenko62cef822008-04-14 13:04:18 +02001840static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001841{
1842 while (snd_hdspm_midi_input_available (hdspm, id))
1843 snd_hdspm_midi_read_byte (hdspm, id);
1844}
1845
Takashi Iwai98274f02005-11-17 14:52:34 +01001846static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001847{
1848 unsigned long flags;
1849 int n_pending;
1850 int to_write;
1851 int i;
1852 unsigned char buf[128];
1853
1854 /* Output is not interrupt driven */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001855
Takashi Iwai763f3562005-06-03 11:25:34 +02001856 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001857 if (hmidi->output &&
1858 !snd_rawmidi_transmit_empty (hmidi->output)) {
1859 n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm,
1860 hmidi->id);
1861 if (n_pending > 0) {
1862 if (n_pending > (int)sizeof (buf))
1863 n_pending = sizeof (buf);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001864
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001865 to_write = snd_rawmidi_transmit (hmidi->output, buf,
1866 n_pending);
1867 if (to_write > 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001868 for (i = 0; i < to_write; ++i)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001869 snd_hdspm_midi_write_byte (hmidi->hdspm,
1870 hmidi->id,
1871 buf[i]);
Takashi Iwai763f3562005-06-03 11:25:34 +02001872 }
1873 }
1874 }
1875 spin_unlock_irqrestore (&hmidi->lock, flags);
1876 return 0;
1877}
1878
Takashi Iwai98274f02005-11-17 14:52:34 +01001879static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001880{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001881 unsigned char buf[128]; /* this buffer is designed to match the MIDI
1882 * input FIFO size
1883 */
Takashi Iwai763f3562005-06-03 11:25:34 +02001884 unsigned long flags;
1885 int n_pending;
1886 int i;
1887
1888 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001889 n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id);
1890 if (n_pending > 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001891 if (hmidi->input) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001892 if (n_pending > (int)sizeof (buf))
Takashi Iwai763f3562005-06-03 11:25:34 +02001893 n_pending = sizeof (buf);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001894 for (i = 0; i < n_pending; ++i)
1895 buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm,
1896 hmidi->id);
1897 if (n_pending)
1898 snd_rawmidi_receive (hmidi->input, buf,
1899 n_pending);
Takashi Iwai763f3562005-06-03 11:25:34 +02001900 } else {
1901 /* flush the MIDI input FIFO */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001902 while (n_pending--)
1903 snd_hdspm_midi_read_byte (hmidi->hdspm,
1904 hmidi->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02001905 }
1906 }
1907 hmidi->pending = 0;
Adrian Knothc0da0012011-06-12 17:26:17 +02001908 spin_unlock_irqrestore(&hmidi->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001909
Adrian Knothc0da0012011-06-12 17:26:17 +02001910 spin_lock_irqsave(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001911 hmidi->hdspm->control_register |= hmidi->ie;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001912 hdspm_write(hmidi->hdspm, HDSPM_controlRegister,
1913 hmidi->hdspm->control_register);
Adrian Knothc0da0012011-06-12 17:26:17 +02001914 spin_unlock_irqrestore(&hmidi->hdspm->lock, flags);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001915
Takashi Iwai763f3562005-06-03 11:25:34 +02001916 return snd_hdspm_midi_output_write (hmidi);
1917}
1918
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001919static void
1920snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001921{
Takashi Iwai98274f02005-11-17 14:52:34 +01001922 struct hdspm *hdspm;
1923 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001924 unsigned long flags;
Takashi Iwai763f3562005-06-03 11:25:34 +02001925
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001926 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001927 hdspm = hmidi->hdspm;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001928
Takashi Iwai763f3562005-06-03 11:25:34 +02001929 spin_lock_irqsave (&hdspm->lock, flags);
1930 if (up) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001931 if (!(hdspm->control_register & hmidi->ie)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001932 snd_hdspm_flush_midi_input (hdspm, hmidi->id);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001933 hdspm->control_register |= hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001934 }
1935 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001936 hdspm->control_register &= ~hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001937 }
1938
1939 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1940 spin_unlock_irqrestore (&hdspm->lock, flags);
1941}
1942
Kees Cook7211ec62017-10-25 08:09:27 -07001943static void snd_hdspm_midi_output_timer(struct timer_list *t)
Takashi Iwai763f3562005-06-03 11:25:34 +02001944{
Kees Cook7211ec62017-10-25 08:09:27 -07001945 struct hdspm_midi *hmidi = from_timer(hmidi, t, timer);
Takashi Iwai763f3562005-06-03 11:25:34 +02001946 unsigned long flags;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001947
Takashi Iwai763f3562005-06-03 11:25:34 +02001948 snd_hdspm_midi_output_write(hmidi);
1949 spin_lock_irqsave (&hmidi->lock, flags);
1950
1951 /* this does not bump hmidi->istimer, because the
1952 kernel automatically removed the timer when it
1953 expired, and we are now adding it back, thus
Adrian Knoth0dca1792011-01-26 19:32:14 +01001954 leaving istimer wherever it was set before.
Takashi Iwai763f3562005-06-03 11:25:34 +02001955 */
1956
Takashi Iwai04018e12015-01-19 11:34:45 +01001957 if (hmidi->istimer)
1958 mod_timer(&hmidi->timer, 1 + jiffies);
Takashi Iwai763f3562005-06-03 11:25:34 +02001959
1960 spin_unlock_irqrestore (&hmidi->lock, flags);
1961}
1962
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001963static void
1964snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001965{
Takashi Iwai98274f02005-11-17 14:52:34 +01001966 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001967 unsigned long flags;
1968
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001969 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001970 spin_lock_irqsave (&hmidi->lock, flags);
1971 if (up) {
1972 if (!hmidi->istimer) {
Kees Cook7211ec62017-10-25 08:09:27 -07001973 timer_setup(&hmidi->timer,
1974 snd_hdspm_midi_output_timer, 0);
Takashi Iwai04018e12015-01-19 11:34:45 +01001975 mod_timer(&hmidi->timer, 1 + jiffies);
Takashi Iwai763f3562005-06-03 11:25:34 +02001976 hmidi->istimer++;
1977 }
1978 } else {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001979 if (hmidi->istimer && --hmidi->istimer <= 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02001980 del_timer (&hmidi->timer);
Takashi Iwai763f3562005-06-03 11:25:34 +02001981 }
1982 spin_unlock_irqrestore (&hmidi->lock, flags);
1983 if (up)
1984 snd_hdspm_midi_output_write(hmidi);
1985}
1986
Takashi Iwai98274f02005-11-17 14:52:34 +01001987static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001988{
Takashi Iwai98274f02005-11-17 14:52:34 +01001989 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001990
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001991 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001992 spin_lock_irq (&hmidi->lock);
1993 snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
1994 hmidi->input = substream;
1995 spin_unlock_irq (&hmidi->lock);
1996
1997 return 0;
1998}
1999
Takashi Iwai98274f02005-11-17 14:52:34 +01002000static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02002001{
Takashi Iwai98274f02005-11-17 14:52:34 +01002002 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02002003
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002004 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02002005 spin_lock_irq (&hmidi->lock);
2006 hmidi->output = substream;
2007 spin_unlock_irq (&hmidi->lock);
2008
2009 return 0;
2010}
2011
Takashi Iwai98274f02005-11-17 14:52:34 +01002012static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02002013{
Takashi Iwai98274f02005-11-17 14:52:34 +01002014 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02002015
2016 snd_hdspm_midi_input_trigger (substream, 0);
2017
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002018 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02002019 spin_lock_irq (&hmidi->lock);
2020 hmidi->input = NULL;
2021 spin_unlock_irq (&hmidi->lock);
2022
2023 return 0;
2024}
2025
Takashi Iwai98274f02005-11-17 14:52:34 +01002026static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02002027{
Takashi Iwai98274f02005-11-17 14:52:34 +01002028 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02002029
2030 snd_hdspm_midi_output_trigger (substream, 0);
2031
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002032 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02002033 spin_lock_irq (&hmidi->lock);
2034 hmidi->output = NULL;
2035 spin_unlock_irq (&hmidi->lock);
2036
2037 return 0;
2038}
2039
Takashi Iwai485885b2017-01-05 17:29:31 +01002040static const struct snd_rawmidi_ops snd_hdspm_midi_output =
Takashi Iwai763f3562005-06-03 11:25:34 +02002041{
2042 .open = snd_hdspm_midi_output_open,
2043 .close = snd_hdspm_midi_output_close,
2044 .trigger = snd_hdspm_midi_output_trigger,
2045};
2046
Takashi Iwai485885b2017-01-05 17:29:31 +01002047static const struct snd_rawmidi_ops snd_hdspm_midi_input =
Takashi Iwai763f3562005-06-03 11:25:34 +02002048{
2049 .open = snd_hdspm_midi_input_open,
2050 .close = snd_hdspm_midi_input_close,
2051 .trigger = snd_hdspm_midi_input_trigger,
2052};
2053
Bill Pembertone23e7a12012-12-06 12:35:10 -05002054static int snd_hdspm_create_midi(struct snd_card *card,
2055 struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02002056{
2057 int err;
Arnd Bergmann7ad210a2017-07-18 13:48:09 +02002058 char buf[64];
Takashi Iwai763f3562005-06-03 11:25:34 +02002059
2060 hdspm->midi[id].id = id;
Takashi Iwai763f3562005-06-03 11:25:34 +02002061 hdspm->midi[id].hdspm = hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +02002062 spin_lock_init (&hdspm->midi[id].lock);
2063
Adrian Knoth0dca1792011-01-26 19:32:14 +01002064 if (0 == id) {
2065 if (MADIface == hdspm->io_type) {
2066 /* MIDI-over-MADI on HDSPe MADIface */
2067 hdspm->midi[0].dataIn = HDSPM_midiDataIn2;
2068 hdspm->midi[0].statusIn = HDSPM_midiStatusIn2;
2069 hdspm->midi[0].dataOut = HDSPM_midiDataOut2;
2070 hdspm->midi[0].statusOut = HDSPM_midiStatusOut2;
2071 hdspm->midi[0].ie = HDSPM_Midi2InterruptEnable;
2072 hdspm->midi[0].irq = HDSPM_midi2IRQPending;
2073 } else {
2074 hdspm->midi[0].dataIn = HDSPM_midiDataIn0;
2075 hdspm->midi[0].statusIn = HDSPM_midiStatusIn0;
2076 hdspm->midi[0].dataOut = HDSPM_midiDataOut0;
2077 hdspm->midi[0].statusOut = HDSPM_midiStatusOut0;
2078 hdspm->midi[0].ie = HDSPM_Midi0InterruptEnable;
2079 hdspm->midi[0].irq = HDSPM_midi0IRQPending;
2080 }
2081 } else if (1 == id) {
2082 hdspm->midi[1].dataIn = HDSPM_midiDataIn1;
2083 hdspm->midi[1].statusIn = HDSPM_midiStatusIn1;
2084 hdspm->midi[1].dataOut = HDSPM_midiDataOut1;
2085 hdspm->midi[1].statusOut = HDSPM_midiStatusOut1;
2086 hdspm->midi[1].ie = HDSPM_Midi1InterruptEnable;
2087 hdspm->midi[1].irq = HDSPM_midi1IRQPending;
2088 } else if ((2 == id) && (MADI == hdspm->io_type)) {
2089 /* MIDI-over-MADI on HDSPe MADI */
2090 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
2091 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
2092 hdspm->midi[2].dataOut = HDSPM_midiDataOut2;
2093 hdspm->midi[2].statusOut = HDSPM_midiStatusOut2;
2094 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
2095 hdspm->midi[2].irq = HDSPM_midi2IRQPending;
2096 } else if (2 == id) {
2097 /* TCO MTC, read only */
2098 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
2099 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
2100 hdspm->midi[2].dataOut = -1;
2101 hdspm->midi[2].statusOut = -1;
2102 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
2103 hdspm->midi[2].irq = HDSPM_midi2IRQPendingAES;
2104 } else if (3 == id) {
2105 /* TCO MTC on HDSPe MADI */
2106 hdspm->midi[3].dataIn = HDSPM_midiDataIn3;
2107 hdspm->midi[3].statusIn = HDSPM_midiStatusIn3;
2108 hdspm->midi[3].dataOut = -1;
2109 hdspm->midi[3].statusOut = -1;
2110 hdspm->midi[3].ie = HDSPM_Midi3InterruptEnable;
2111 hdspm->midi[3].irq = HDSPM_midi3IRQPending;
2112 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002113
Adrian Knoth0dca1792011-01-26 19:32:14 +01002114 if ((id < 2) || ((2 == id) && ((MADI == hdspm->io_type) ||
2115 (MADIface == hdspm->io_type)))) {
2116 if ((id == 0) && (MADIface == hdspm->io_type)) {
Arnd Bergmann7ad210a2017-07-18 13:48:09 +02002117 snprintf(buf, sizeof(buf), "%s MIDIoverMADI",
2118 card->shortname);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002119 } else if ((id == 2) && (MADI == hdspm->io_type)) {
Arnd Bergmann7ad210a2017-07-18 13:48:09 +02002120 snprintf(buf, sizeof(buf), "%s MIDIoverMADI",
2121 card->shortname);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002122 } else {
Arnd Bergmann7ad210a2017-07-18 13:48:09 +02002123 snprintf(buf, sizeof(buf), "%s MIDI %d",
2124 card->shortname, id+1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002125 }
2126 err = snd_rawmidi_new(card, buf, id, 1, 1,
2127 &hdspm->midi[id].rmidi);
2128 if (err < 0)
2129 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02002130
Arnd Bergmann7ad210a2017-07-18 13:48:09 +02002131 snprintf(hdspm->midi[id].rmidi->name,
2132 sizeof(hdspm->midi[id].rmidi->name),
2133 "%s MIDI %d", card->id, id+1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002134 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
Takashi Iwai763f3562005-06-03 11:25:34 +02002135
Adrian Knoth0dca1792011-01-26 19:32:14 +01002136 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
2137 SNDRV_RAWMIDI_STREAM_OUTPUT,
2138 &snd_hdspm_midi_output);
2139 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
2140 SNDRV_RAWMIDI_STREAM_INPUT,
2141 &snd_hdspm_midi_input);
2142
2143 hdspm->midi[id].rmidi->info_flags |=
2144 SNDRV_RAWMIDI_INFO_OUTPUT |
2145 SNDRV_RAWMIDI_INFO_INPUT |
2146 SNDRV_RAWMIDI_INFO_DUPLEX;
2147 } else {
2148 /* TCO MTC, read only */
Arnd Bergmann7ad210a2017-07-18 13:48:09 +02002149 snprintf(buf, sizeof(buf), "%s MTC %d",
2150 card->shortname, id+1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002151 err = snd_rawmidi_new(card, buf, id, 1, 1,
2152 &hdspm->midi[id].rmidi);
2153 if (err < 0)
2154 return err;
2155
Arnd Bergmann7ad210a2017-07-18 13:48:09 +02002156 snprintf(hdspm->midi[id].rmidi->name,
2157 sizeof(hdspm->midi[id].rmidi->name),
2158 "%s MTC %d", card->id, id+1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002159 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
2160
2161 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
2162 SNDRV_RAWMIDI_STREAM_INPUT,
2163 &snd_hdspm_midi_input);
2164
2165 hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
2166 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002167
2168 return 0;
2169}
2170
2171
Takashi Iwaia2e527c2020-09-03 12:41:27 +02002172static void hdspm_midi_work(struct work_struct *work)
Takashi Iwai763f3562005-06-03 11:25:34 +02002173{
Takashi Iwaia2e527c2020-09-03 12:41:27 +02002174 struct hdspm *hdspm = container_of(work, struct hdspm, midi_work);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002175 int i = 0;
2176
2177 while (i < hdspm->midiPorts) {
2178 if (hdspm->midi[i].pending)
2179 snd_hdspm_midi_input_read(&hdspm->midi[i]);
2180
2181 i++;
2182 }
2183}
Takashi Iwai763f3562005-06-03 11:25:34 +02002184
2185
2186/*-----------------------------------------------------------------------------
2187 Status Interface
2188 ----------------------------------------------------------------------------*/
2189
2190/* get the system sample rate which is set */
2191
Adrian Knoth0dca1792011-01-26 19:32:14 +01002192
Adrian Knoth3f7bf912013-03-10 00:37:21 +01002193static inline int hdspm_get_pll_freq(struct hdspm *hdspm)
2194{
2195 unsigned int period, rate;
2196
2197 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
2198 rate = hdspm_calc_dds_value(hdspm, period);
2199
2200 return rate;
2201}
2202
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002203/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002204 * Calculate the real sample rate from the
2205 * current DDS value.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002206 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002207static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
2208{
Adrian Knoth3f7bf912013-03-10 00:37:21 +01002209 unsigned int rate;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002210
Adrian Knoth3f7bf912013-03-10 00:37:21 +01002211 rate = hdspm_get_pll_freq(hdspm);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002212
Adrian Knotha97bda72012-05-30 14:23:18 +02002213 if (rate > 207000) {
Adrian Knoth21a164d2012-10-19 17:42:23 +02002214 /* Unreasonable high sample rate as seen on PCI MADI cards. */
2215 if (0 == hdspm_system_clock_mode(hdspm)) {
2216 /* master mode, return internal sample rate */
2217 rate = hdspm->system_sample_rate;
2218 } else {
2219 /* slave mode, return external sample rate */
2220 rate = hdspm_external_sample_rate(hdspm);
Takashi Iwaic1099c32016-02-29 14:32:42 +01002221 if (!rate)
2222 rate = hdspm->system_sample_rate;
Adrian Knoth21a164d2012-10-19 17:42:23 +02002223 }
Adrian Knotha97bda72012-05-30 14:23:18 +02002224 }
2225
Adrian Knoth0dca1792011-01-26 19:32:14 +01002226 return rate;
2227}
2228
2229
Takashi Iwai763f3562005-06-03 11:25:34 +02002230#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02002231{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2232 .name = xname, \
2233 .index = xindex, \
2234 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2235 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2236 .info = snd_hdspm_info_system_sample_rate, \
2237 .put = snd_hdspm_put_system_sample_rate, \
2238 .get = snd_hdspm_get_system_sample_rate \
Takashi Iwai763f3562005-06-03 11:25:34 +02002239}
2240
Takashi Iwai98274f02005-11-17 14:52:34 +01002241static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
2242 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002243{
2244 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2245 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002246 uinfo->value.integer.min = 27000;
2247 uinfo->value.integer.max = 207000;
2248 uinfo->value.integer.step = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002249 return 0;
2250}
2251
Adrian Knoth0dca1792011-01-26 19:32:14 +01002252
Takashi Iwai98274f02005-11-17 14:52:34 +01002253static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
2254 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002255 ucontrol)
2256{
Takashi Iwai98274f02005-11-17 14:52:34 +01002257 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002258
Adrian Knoth0dca1792011-01-26 19:32:14 +01002259 ucontrol->value.integer.value[0] = hdspm_get_system_sample_rate(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002260 return 0;
2261}
2262
Adrian Knoth41285a92012-10-19 17:42:22 +02002263static int snd_hdspm_put_system_sample_rate(struct snd_kcontrol *kcontrol,
2264 struct snd_ctl_elem_value *
2265 ucontrol)
2266{
2267 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwaic1099c32016-02-29 14:32:42 +01002268 int rate = ucontrol->value.integer.value[0];
Adrian Knoth41285a92012-10-19 17:42:22 +02002269
Takashi Iwaic1099c32016-02-29 14:32:42 +01002270 if (rate < 27000 || rate > 207000)
2271 return -EINVAL;
Takashi Iwai537e4812016-02-29 14:25:16 +01002272 hdspm_set_dds_value(hdspm, ucontrol->value.integer.value[0]);
Adrian Knoth41285a92012-10-19 17:42:22 +02002273 return 0;
2274}
2275
Adrian Knoth0dca1792011-01-26 19:32:14 +01002276
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002277/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002278 * Returns the WordClock sample rate class for the given card.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002279 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002280static int hdspm_get_wc_sample_rate(struct hdspm *hdspm)
2281{
2282 int status;
2283
2284 switch (hdspm->io_type) {
2285 case RayDAT:
2286 case AIO:
2287 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2288 return (status >> 16) & 0xF;
2289 break;
Adrian Knotha57fea82013-07-05 11:28:11 +02002290 case AES32:
2291 status = hdspm_read(hdspm, HDSPM_statusRegister);
2292 return (status >> HDSPM_AES32_wcFreq_bit) & 0xF;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002293 default:
2294 break;
2295 }
2296
2297
2298 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002299}
2300
Adrian Knoth0dca1792011-01-26 19:32:14 +01002301
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002302/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002303 * Returns the TCO sample rate class for the given card.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002304 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002305static int hdspm_get_tco_sample_rate(struct hdspm *hdspm)
2306{
2307 int status;
2308
2309 if (hdspm->tco) {
2310 switch (hdspm->io_type) {
2311 case RayDAT:
2312 case AIO:
2313 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
2314 return (status >> 20) & 0xF;
2315 break;
Adrian Knoth051c44f2013-07-05 11:28:12 +02002316 case AES32:
2317 status = hdspm_read(hdspm, HDSPM_statusRegister);
2318 return (status >> 1) & 0xF;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002319 default:
2320 break;
2321 }
2322 }
2323
2324 return 0;
2325}
2326
2327
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002328/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002329 * Returns the SYNC_IN sample rate class for the given card.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002330 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002331static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm)
2332{
2333 int status;
2334
2335 if (hdspm->tco) {
2336 switch (hdspm->io_type) {
2337 case RayDAT:
2338 case AIO:
2339 status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2340 return (status >> 12) & 0xF;
2341 break;
2342 default:
2343 break;
2344 }
2345 }
2346
2347 return 0;
2348}
2349
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002350/*
Adrian Knothd3c36ed2013-07-05 11:28:09 +02002351 * Returns the AES sample rate class for the given card.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002352 */
Adrian Knothd3c36ed2013-07-05 11:28:09 +02002353static int hdspm_get_aes_sample_rate(struct hdspm *hdspm, int index)
2354{
2355 int timecode;
2356
2357 switch (hdspm->io_type) {
2358 case AES32:
2359 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
2360 return (timecode >> (4*index)) & 0xF;
2361 break;
2362 default:
2363 break;
2364 }
2365 return 0;
2366}
Adrian Knoth0dca1792011-01-26 19:32:14 +01002367
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002368/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002369 * Returns the sample rate class for input source <idx> for
2370 * 'new style' cards like the AIO and RayDAT.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002371 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002372static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
2373{
2374 int status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2375
2376 return (status >> (idx*4)) & 0xF;
2377}
2378
Adrian Knoth8cea5712013-07-05 11:27:59 +02002379#define ENUMERATED_CTL_INFO(info, texts) \
Adrian Knoth38816542013-07-05 11:28:20 +02002380 snd_ctl_enum_info(info, 1, ARRAY_SIZE(texts), texts)
Adrian Knoth8cea5712013-07-05 11:27:59 +02002381
Adrian Knoth0dca1792011-01-26 19:32:14 +01002382
Adrian Knoth23361422013-07-05 11:28:17 +02002383/* Helper function to query the external sample rate and return the
2384 * corresponding enum to be returned to userspace.
2385 */
2386static int hdspm_external_rate_to_enum(struct hdspm *hdspm)
2387{
2388 int rate = hdspm_external_sample_rate(hdspm);
2389 int i, selected_rate = 0;
2390 for (i = 1; i < 10; i++)
2391 if (HDSPM_bit2freq(i) == rate) {
2392 selected_rate = i;
2393 break;
2394 }
2395 return selected_rate;
2396}
2397
Adrian Knoth0dca1792011-01-26 19:32:14 +01002398
2399#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
2400{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2401 .name = xname, \
2402 .private_value = xindex, \
2403 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2404 .info = snd_hdspm_info_autosync_sample_rate, \
2405 .get = snd_hdspm_get_autosync_sample_rate \
2406}
2407
2408
Takashi Iwai98274f02005-11-17 14:52:34 +01002409static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2410 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002411{
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01002412 ENUMERATED_CTL_INFO(uinfo, texts_freq);
Takashi Iwai763f3562005-06-03 11:25:34 +02002413 return 0;
2414}
2415
Adrian Knoth0dca1792011-01-26 19:32:14 +01002416
Takashi Iwai98274f02005-11-17 14:52:34 +01002417static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2418 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002419 ucontrol)
2420{
Takashi Iwai98274f02005-11-17 14:52:34 +01002421 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002422
Adrian Knoth0dca1792011-01-26 19:32:14 +01002423 switch (hdspm->io_type) {
2424 case RayDAT:
2425 switch (kcontrol->private_value) {
2426 case 0:
2427 ucontrol->value.enumerated.item[0] =
2428 hdspm_get_wc_sample_rate(hdspm);
2429 break;
2430 case 7:
2431 ucontrol->value.enumerated.item[0] =
2432 hdspm_get_tco_sample_rate(hdspm);
2433 break;
2434 case 8:
2435 ucontrol->value.enumerated.item[0] =
2436 hdspm_get_sync_in_sample_rate(hdspm);
2437 break;
2438 default:
2439 ucontrol->value.enumerated.item[0] =
2440 hdspm_get_s1_sample_rate(hdspm,
2441 kcontrol->private_value-1);
2442 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002443 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002444
Adrian Knoth0dca1792011-01-26 19:32:14 +01002445 case AIO:
2446 switch (kcontrol->private_value) {
2447 case 0: /* WC */
2448 ucontrol->value.enumerated.item[0] =
2449 hdspm_get_wc_sample_rate(hdspm);
2450 break;
2451 case 4: /* TCO */
2452 ucontrol->value.enumerated.item[0] =
2453 hdspm_get_tco_sample_rate(hdspm);
2454 break;
2455 case 5: /* SYNC_IN */
2456 ucontrol->value.enumerated.item[0] =
2457 hdspm_get_sync_in_sample_rate(hdspm);
2458 break;
2459 default:
2460 ucontrol->value.enumerated.item[0] =
2461 hdspm_get_s1_sample_rate(hdspm,
Adrian Knoth1cb7dbf2013-07-05 11:28:03 +02002462 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002463 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002464 break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002465
2466 case AES32:
2467
2468 switch (kcontrol->private_value) {
2469 case 0: /* WC */
2470 ucontrol->value.enumerated.item[0] =
2471 hdspm_get_wc_sample_rate(hdspm);
2472 break;
2473 case 9: /* TCO */
2474 ucontrol->value.enumerated.item[0] =
2475 hdspm_get_tco_sample_rate(hdspm);
2476 break;
2477 case 10: /* SYNC_IN */
2478 ucontrol->value.enumerated.item[0] =
2479 hdspm_get_sync_in_sample_rate(hdspm);
2480 break;
Adrian Knoth2d63ec32013-07-05 11:28:18 +02002481 case 11: /* External Rate */
2482 ucontrol->value.enumerated.item[0] =
2483 hdspm_external_rate_to_enum(hdspm);
2484 break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002485 default: /* AES1 to AES8 */
2486 ucontrol->value.enumerated.item[0] =
Adrian Knoth2d63ec32013-07-05 11:28:18 +02002487 hdspm_get_aes_sample_rate(hdspm,
2488 kcontrol->private_value -
2489 HDSPM_AES32_AUTOSYNC_FROM_AES1);
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002490 break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01002491 }
Adrian Knothd681dea2012-10-19 17:42:25 +02002492 break;
Adrian Knothb8812c52012-10-19 17:42:26 +02002493
2494 case MADI:
2495 case MADIface:
Adrian Knoth23361422013-07-05 11:28:17 +02002496 ucontrol->value.enumerated.item[0] =
2497 hdspm_external_rate_to_enum(hdspm);
Adrian Knothb8812c52012-10-19 17:42:26 +02002498 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002499 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002500 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002501 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002502
Takashi Iwai763f3562005-06-03 11:25:34 +02002503 return 0;
2504}
2505
Adrian Knoth0dca1792011-01-26 19:32:14 +01002506
Takashi Iwai763f3562005-06-03 11:25:34 +02002507#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002508{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2509 .name = xname, \
2510 .index = xindex, \
2511 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2512 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2513 .info = snd_hdspm_info_system_clock_mode, \
2514 .get = snd_hdspm_get_system_clock_mode, \
2515 .put = snd_hdspm_put_system_clock_mode, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002516}
2517
2518
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002519/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002520 * Returns the system clock mode for the given card.
2521 * @returns 0 - master, 1 - slave
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002522 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002523static int hdspm_system_clock_mode(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002524{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002525 switch (hdspm->io_type) {
2526 case AIO:
2527 case RayDAT:
2528 if (hdspm->settings_register & HDSPM_c0Master)
2529 return 0;
2530 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002531
Adrian Knoth0dca1792011-01-26 19:32:14 +01002532 default:
2533 if (hdspm->control_register & HDSPM_ClockModeMaster)
2534 return 0;
2535 }
2536
Takashi Iwai763f3562005-06-03 11:25:34 +02002537 return 1;
2538}
2539
Adrian Knoth0dca1792011-01-26 19:32:14 +01002540
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002541/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002542 * Sets the system clock mode.
2543 * @param mode 0 - master, 1 - slave
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002544 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01002545static void hdspm_set_system_clock_mode(struct hdspm *hdspm, int mode)
2546{
Adrian Knoth34be7ebb2013-07-05 11:27:56 +02002547 hdspm_set_toggle_setting(hdspm,
2548 (hdspm_is_raydat_or_aio(hdspm)) ?
2549 HDSPM_c0Master : HDSPM_ClockModeMaster,
2550 (0 == mode));
Adrian Knoth0dca1792011-01-26 19:32:14 +01002551}
2552
2553
Takashi Iwai98274f02005-11-17 14:52:34 +01002554static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
2555 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002556{
Adrian Knoth38816542013-07-05 11:28:20 +02002557 static const char *const texts[] = { "Master", "AutoSync" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01002558 ENUMERATED_CTL_INFO(uinfo, texts);
Takashi Iwai763f3562005-06-03 11:25:34 +02002559 return 0;
2560}
2561
Takashi Iwai98274f02005-11-17 14:52:34 +01002562static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
2563 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002564{
Takashi Iwai98274f02005-11-17 14:52:34 +01002565 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002566
Adrian Knoth0dca1792011-01-26 19:32:14 +01002567 ucontrol->value.enumerated.item[0] = hdspm_system_clock_mode(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002568 return 0;
2569}
2570
Adrian Knoth0dca1792011-01-26 19:32:14 +01002571static int snd_hdspm_put_system_clock_mode(struct snd_kcontrol *kcontrol,
2572 struct snd_ctl_elem_value *ucontrol)
2573{
2574 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2575 int val;
2576
2577 if (!snd_hdspm_use_is_exclusive(hdspm))
2578 return -EBUSY;
2579
2580 val = ucontrol->value.enumerated.item[0];
2581 if (val < 0)
2582 val = 0;
2583 else if (val > 1)
2584 val = 1;
2585
2586 hdspm_set_system_clock_mode(hdspm, val);
2587
2588 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002589}
2590
Adrian Knoth0dca1792011-01-26 19:32:14 +01002591
2592#define HDSPM_INTERNAL_CLOCK(xname, xindex) \
2593{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2594 .name = xname, \
2595 .index = xindex, \
2596 .info = snd_hdspm_info_clock_source, \
2597 .get = snd_hdspm_get_clock_source, \
2598 .put = snd_hdspm_put_clock_source \
2599}
2600
2601
Takashi Iwai98274f02005-11-17 14:52:34 +01002602static int hdspm_clock_source(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002603{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002604 switch (hdspm->system_sample_rate) {
2605 case 32000: return 0;
2606 case 44100: return 1;
2607 case 48000: return 2;
2608 case 64000: return 3;
2609 case 88200: return 4;
2610 case 96000: return 5;
2611 case 128000: return 6;
2612 case 176400: return 7;
2613 case 192000: return 8;
Takashi Iwai763f3562005-06-03 11:25:34 +02002614 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002615
2616 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002617}
2618
Takashi Iwai98274f02005-11-17 14:52:34 +01002619static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
Takashi Iwai763f3562005-06-03 11:25:34 +02002620{
2621 int rate;
2622 switch (mode) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002623 case 0:
2624 rate = 32000; break;
2625 case 1:
2626 rate = 44100; break;
2627 case 2:
2628 rate = 48000; break;
2629 case 3:
2630 rate = 64000; break;
2631 case 4:
2632 rate = 88200; break;
2633 case 5:
2634 rate = 96000; break;
2635 case 6:
2636 rate = 128000; break;
2637 case 7:
2638 rate = 176400; break;
2639 case 8:
2640 rate = 192000; break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002641 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002642 rate = 48000;
Takashi Iwai763f3562005-06-03 11:25:34 +02002643 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002644 hdspm_set_rate(hdspm, rate, 1);
2645 return 0;
2646}
2647
Takashi Iwai98274f02005-11-17 14:52:34 +01002648static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
2649 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002650{
Takashi Iwaic69a6372014-10-20 18:19:41 +02002651 return snd_ctl_enum_info(uinfo, 1, 9, texts_freq + 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02002652}
2653
Takashi Iwai98274f02005-11-17 14:52:34 +01002654static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
2655 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002656{
Takashi Iwai98274f02005-11-17 14:52:34 +01002657 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002658
2659 ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
2660 return 0;
2661}
2662
Takashi Iwai98274f02005-11-17 14:52:34 +01002663static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
2664 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002665{
Takashi Iwai98274f02005-11-17 14:52:34 +01002666 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002667 int change;
2668 int val;
2669
2670 if (!snd_hdspm_use_is_exclusive(hdspm))
2671 return -EBUSY;
2672 val = ucontrol->value.enumerated.item[0];
2673 if (val < 0)
2674 val = 0;
Remy Bruno65345992007-08-31 12:21:08 +02002675 if (val > 9)
2676 val = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002677 spin_lock_irq(&hdspm->lock);
2678 if (val != hdspm_clock_source(hdspm))
2679 change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
2680 else
2681 change = 0;
2682 spin_unlock_irq(&hdspm->lock);
2683 return change;
2684}
2685
Adrian Knoth0dca1792011-01-26 19:32:14 +01002686
Takashi Iwai763f3562005-06-03 11:25:34 +02002687#define HDSPM_PREF_SYNC_REF(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02002688{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002689 .name = xname, \
2690 .index = xindex, \
2691 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2692 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2693 .info = snd_hdspm_info_pref_sync_ref, \
2694 .get = snd_hdspm_get_pref_sync_ref, \
2695 .put = snd_hdspm_put_pref_sync_ref \
Takashi Iwai763f3562005-06-03 11:25:34 +02002696}
2697
Adrian Knoth0dca1792011-01-26 19:32:14 +01002698
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002699/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002700 * Returns the current preferred sync reference setting.
2701 * The semantics of the return value are depending on the
2702 * card, please see the comments for clarification.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002703 */
Takashi Iwai98274f02005-11-17 14:52:34 +01002704static int hdspm_pref_sync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002705{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002706 switch (hdspm->io_type) {
2707 case AES32:
Remy Bruno3cee5a62006-10-16 12:46:32 +02002708 switch (hdspm->control_register & HDSPM_SyncRefMask) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002709 case 0: return 0; /* WC */
2710 case HDSPM_SyncRef0: return 1; /* AES 1 */
2711 case HDSPM_SyncRef1: return 2; /* AES 2 */
2712 case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; /* AES 3 */
2713 case HDSPM_SyncRef2: return 4; /* AES 4 */
2714 case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; /* AES 5 */
2715 case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; /* AES 6 */
2716 case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0:
2717 return 7; /* AES 7 */
2718 case HDSPM_SyncRef3: return 8; /* AES 8 */
2719 case HDSPM_SyncRef3+HDSPM_SyncRef0: return 9; /* TCO */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002720 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002721 break;
2722
2723 case MADI:
2724 case MADIface:
2725 if (hdspm->tco) {
2726 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2727 case 0: return 0; /* WC */
2728 case HDSPM_SyncRef0: return 1; /* MADI */
2729 case HDSPM_SyncRef1: return 2; /* TCO */
2730 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2731 return 3; /* SYNC_IN */
2732 }
2733 } else {
2734 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2735 case 0: return 0; /* WC */
2736 case HDSPM_SyncRef0: return 1; /* MADI */
2737 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2738 return 2; /* SYNC_IN */
2739 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02002740 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002741 break;
2742
2743 case RayDAT:
2744 if (hdspm->tco) {
2745 switch ((hdspm->settings_register &
2746 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2747 case 0: return 0; /* WC */
2748 case 3: return 1; /* ADAT 1 */
2749 case 4: return 2; /* ADAT 2 */
2750 case 5: return 3; /* ADAT 3 */
2751 case 6: return 4; /* ADAT 4 */
2752 case 1: return 5; /* AES */
2753 case 2: return 6; /* SPDIF */
2754 case 9: return 7; /* TCO */
2755 case 10: return 8; /* SYNC_IN */
2756 }
2757 } else {
2758 switch ((hdspm->settings_register &
2759 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2760 case 0: return 0; /* WC */
2761 case 3: return 1; /* ADAT 1 */
2762 case 4: return 2; /* ADAT 2 */
2763 case 5: return 3; /* ADAT 3 */
2764 case 6: return 4; /* ADAT 4 */
2765 case 1: return 5; /* AES */
2766 case 2: return 6; /* SPDIF */
2767 case 10: return 7; /* SYNC_IN */
2768 }
2769 }
2770
2771 break;
2772
2773 case AIO:
2774 if (hdspm->tco) {
2775 switch ((hdspm->settings_register &
2776 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2777 case 0: return 0; /* WC */
2778 case 3: return 1; /* ADAT */
2779 case 1: return 2; /* AES */
2780 case 2: return 3; /* SPDIF */
2781 case 9: return 4; /* TCO */
2782 case 10: return 5; /* SYNC_IN */
2783 }
2784 } else {
2785 switch ((hdspm->settings_register &
2786 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2787 case 0: return 0; /* WC */
2788 case 3: return 1; /* ADAT */
2789 case 1: return 2; /* AES */
2790 case 2: return 3; /* SPDIF */
2791 case 10: return 4; /* SYNC_IN */
2792 }
2793 }
2794
2795 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002796 }
2797
Adrian Knoth0dca1792011-01-26 19:32:14 +01002798 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002799}
2800
Adrian Knoth0dca1792011-01-26 19:32:14 +01002801
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002802/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01002803 * Set the preferred sync reference to <pref>. The semantics
2804 * of <pref> are depending on the card type, see the comments
2805 * for clarification.
Takashi Iwaiddcecf62014-11-10 17:24:26 +01002806 */
Takashi Iwai98274f02005-11-17 14:52:34 +01002807static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
Takashi Iwai763f3562005-06-03 11:25:34 +02002808{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002809 int p = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002810
Adrian Knoth0dca1792011-01-26 19:32:14 +01002811 switch (hdspm->io_type) {
2812 case AES32:
2813 hdspm->control_register &= ~HDSPM_SyncRefMask;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002814 switch (pref) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002815 case 0: /* WC */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002816 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002817 case 1: /* AES 1 */
2818 hdspm->control_register |= HDSPM_SyncRef0;
2819 break;
2820 case 2: /* AES 2 */
2821 hdspm->control_register |= HDSPM_SyncRef1;
2822 break;
2823 case 3: /* AES 3 */
2824 hdspm->control_register |=
2825 HDSPM_SyncRef1+HDSPM_SyncRef0;
2826 break;
2827 case 4: /* AES 4 */
2828 hdspm->control_register |= HDSPM_SyncRef2;
2829 break;
2830 case 5: /* AES 5 */
2831 hdspm->control_register |=
2832 HDSPM_SyncRef2+HDSPM_SyncRef0;
2833 break;
2834 case 6: /* AES 6 */
2835 hdspm->control_register |=
2836 HDSPM_SyncRef2+HDSPM_SyncRef1;
2837 break;
2838 case 7: /* AES 7 */
2839 hdspm->control_register |=
2840 HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
2841 break;
2842 case 8: /* AES 8 */
2843 hdspm->control_register |= HDSPM_SyncRef3;
2844 break;
2845 case 9: /* TCO */
2846 hdspm->control_register |=
2847 HDSPM_SyncRef3+HDSPM_SyncRef0;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002848 break;
2849 default:
2850 return -1;
2851 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002852
2853 break;
2854
2855 case MADI:
2856 case MADIface:
2857 hdspm->control_register &= ~HDSPM_SyncRefMask;
2858 if (hdspm->tco) {
2859 switch (pref) {
2860 case 0: /* WC */
2861 break;
2862 case 1: /* MADI */
2863 hdspm->control_register |= HDSPM_SyncRef0;
2864 break;
2865 case 2: /* TCO */
2866 hdspm->control_register |= HDSPM_SyncRef1;
2867 break;
2868 case 3: /* SYNC_IN */
2869 hdspm->control_register |=
2870 HDSPM_SyncRef0+HDSPM_SyncRef1;
2871 break;
2872 default:
2873 return -1;
2874 }
2875 } else {
2876 switch (pref) {
2877 case 0: /* WC */
2878 break;
2879 case 1: /* MADI */
2880 hdspm->control_register |= HDSPM_SyncRef0;
2881 break;
2882 case 2: /* SYNC_IN */
2883 hdspm->control_register |=
2884 HDSPM_SyncRef0+HDSPM_SyncRef1;
2885 break;
2886 default:
2887 return -1;
2888 }
2889 }
2890
2891 break;
2892
2893 case RayDAT:
2894 if (hdspm->tco) {
2895 switch (pref) {
2896 case 0: p = 0; break; /* WC */
2897 case 1: p = 3; break; /* ADAT 1 */
2898 case 2: p = 4; break; /* ADAT 2 */
2899 case 3: p = 5; break; /* ADAT 3 */
2900 case 4: p = 6; break; /* ADAT 4 */
2901 case 5: p = 1; break; /* AES */
2902 case 6: p = 2; break; /* SPDIF */
2903 case 7: p = 9; break; /* TCO */
2904 case 8: p = 10; break; /* SYNC_IN */
2905 default: return -1;
2906 }
2907 } else {
2908 switch (pref) {
2909 case 0: p = 0; break; /* WC */
2910 case 1: p = 3; break; /* ADAT 1 */
2911 case 2: p = 4; break; /* ADAT 2 */
2912 case 3: p = 5; break; /* ADAT 3 */
2913 case 4: p = 6; break; /* ADAT 4 */
2914 case 5: p = 1; break; /* AES */
2915 case 6: p = 2; break; /* SPDIF */
2916 case 7: p = 10; break; /* SYNC_IN */
2917 default: return -1;
2918 }
2919 }
2920 break;
2921
2922 case AIO:
2923 if (hdspm->tco) {
2924 switch (pref) {
2925 case 0: p = 0; break; /* WC */
2926 case 1: p = 3; break; /* ADAT */
2927 case 2: p = 1; break; /* AES */
2928 case 3: p = 2; break; /* SPDIF */
2929 case 4: p = 9; break; /* TCO */
2930 case 5: p = 10; break; /* SYNC_IN */
2931 default: return -1;
2932 }
2933 } else {
2934 switch (pref) {
2935 case 0: p = 0; break; /* WC */
2936 case 1: p = 3; break; /* ADAT */
2937 case 2: p = 1; break; /* AES */
2938 case 3: p = 2; break; /* SPDIF */
2939 case 4: p = 10; break; /* SYNC_IN */
2940 default: return -1;
2941 }
2942 }
2943 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002944 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002945
2946 switch (hdspm->io_type) {
2947 case RayDAT:
2948 case AIO:
2949 hdspm->settings_register &= ~HDSPM_c0_SyncRefMask;
2950 hdspm->settings_register |= HDSPM_c0_SyncRef0 * p;
2951 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2952 break;
2953
2954 case MADI:
2955 case MADIface:
2956 case AES32:
2957 hdspm_write(hdspm, HDSPM_controlRegister,
2958 hdspm->control_register);
2959 }
2960
Takashi Iwai763f3562005-06-03 11:25:34 +02002961 return 0;
2962}
2963
Adrian Knoth0dca1792011-01-26 19:32:14 +01002964
Takashi Iwai98274f02005-11-17 14:52:34 +01002965static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
2966 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002967{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002968 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002969
Adrian Knotheb0d4db2013-07-05 11:28:21 +02002970 snd_ctl_enum_info(uinfo, 1, hdspm->texts_autosync_items, hdspm->texts_autosync);
Remy Bruno3cee5a62006-10-16 12:46:32 +02002971
Takashi Iwai763f3562005-06-03 11:25:34 +02002972 return 0;
2973}
2974
Takashi Iwai98274f02005-11-17 14:52:34 +01002975static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
2976 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002977{
Takashi Iwai98274f02005-11-17 14:52:34 +01002978 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002979 int psf = hdspm_pref_sync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002980
Adrian Knoth0dca1792011-01-26 19:32:14 +01002981 if (psf >= 0) {
2982 ucontrol->value.enumerated.item[0] = psf;
2983 return 0;
2984 }
2985
2986 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002987}
2988
Takashi Iwai98274f02005-11-17 14:52:34 +01002989static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
2990 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002991{
Takashi Iwai98274f02005-11-17 14:52:34 +01002992 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002993 int val, change = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002994
2995 if (!snd_hdspm_use_is_exclusive(hdspm))
2996 return -EBUSY;
2997
Adrian Knoth0dca1792011-01-26 19:32:14 +01002998 val = ucontrol->value.enumerated.item[0];
2999
3000 if (val < 0)
3001 val = 0;
3002 else if (val >= hdspm->texts_autosync_items)
3003 val = hdspm->texts_autosync_items-1;
Takashi Iwai763f3562005-06-03 11:25:34 +02003004
3005 spin_lock_irq(&hdspm->lock);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003006 if (val != hdspm_pref_sync_ref(hdspm))
3007 change = (0 == hdspm_set_pref_sync_ref(hdspm, val)) ? 1 : 0;
3008
Takashi Iwai763f3562005-06-03 11:25:34 +02003009 spin_unlock_irq(&hdspm->lock);
3010 return change;
3011}
3012
Adrian Knoth0dca1792011-01-26 19:32:14 +01003013
Takashi Iwai763f3562005-06-03 11:25:34 +02003014#define HDSPM_AUTOSYNC_REF(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003015{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3016 .name = xname, \
3017 .index = xindex, \
3018 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
3019 .info = snd_hdspm_info_autosync_ref, \
3020 .get = snd_hdspm_get_autosync_ref, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003021}
3022
Adrian Knoth0dca1792011-01-26 19:32:14 +01003023static int hdspm_autosync_ref(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003024{
Adrian Knoth2d60fc72013-07-05 11:28:15 +02003025 /* This looks at the autosync selected sync reference */
Adrian Knoth0dca1792011-01-26 19:32:14 +01003026 if (AES32 == hdspm->io_type) {
Takashi Iwai763f3562005-06-03 11:25:34 +02003027
Adrian Knoth2d60fc72013-07-05 11:28:15 +02003028 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
3029 unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) & 0xF;
Pierre-Louis Bossartab3ee092020-07-02 14:35:56 -05003030 /* syncref >= HDSPM_AES32_AUTOSYNC_FROM_WORD is always true */
3031 if (syncref <= HDSPM_AES32_AUTOSYNC_FROM_SYNC_IN) {
Adrian Knoth2d60fc72013-07-05 11:28:15 +02003032 return syncref;
3033 }
3034 return HDSPM_AES32_AUTOSYNC_FROM_NONE;
3035
3036 } else if (MADI == hdspm->io_type) {
3037
3038 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003039 switch (status2 & HDSPM_SelSyncRefMask) {
3040 case HDSPM_SelSyncRef_WORD:
3041 return HDSPM_AUTOSYNC_FROM_WORD;
3042 case HDSPM_SelSyncRef_MADI:
3043 return HDSPM_AUTOSYNC_FROM_MADI;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003044 case HDSPM_SelSyncRef_TCO:
3045 return HDSPM_AUTOSYNC_FROM_TCO;
3046 case HDSPM_SelSyncRef_SyncIn:
3047 return HDSPM_AUTOSYNC_FROM_SYNC_IN;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003048 case HDSPM_SelSyncRef_NVALID:
3049 return HDSPM_AUTOSYNC_FROM_NONE;
3050 default:
Adrian Knothe71b95a2013-07-05 11:28:06 +02003051 return HDSPM_AUTOSYNC_FROM_NONE;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003052 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003053
Takashi Iwai763f3562005-06-03 11:25:34 +02003054 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01003055 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02003056}
3057
Adrian Knoth0dca1792011-01-26 19:32:14 +01003058
Takashi Iwai98274f02005-11-17 14:52:34 +01003059static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
3060 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003061{
Remy Bruno3cee5a62006-10-16 12:46:32 +02003062 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003063
Adrian Knoth0dca1792011-01-26 19:32:14 +01003064 if (AES32 == hdspm->io_type) {
Adrian Knoth04659f92013-07-05 11:28:22 +02003065 static const char *const texts[] = { "WordClock", "AES1", "AES2", "AES3",
Adrian Knothdb2d1a92013-07-05 11:28:08 +02003066 "AES4", "AES5", "AES6", "AES7", "AES8", "TCO", "Sync In", "None"};
Remy Bruno3cee5a62006-10-16 12:46:32 +02003067
Adrian Knoth04659f92013-07-05 11:28:22 +02003068 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01003069 } else if (MADI == hdspm->io_type) {
Adrian Knoth04659f92013-07-05 11:28:22 +02003070 static const char *const texts[] = {"Word Clock", "MADI", "TCO",
Adrian Knoth0dca1792011-01-26 19:32:14 +01003071 "Sync In", "None" };
Remy Bruno3cee5a62006-10-16 12:46:32 +02003072
Adrian Knoth04659f92013-07-05 11:28:22 +02003073 ENUMERATED_CTL_INFO(uinfo, texts);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003074 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003075 return 0;
3076}
3077
Takashi Iwai98274f02005-11-17 14:52:34 +01003078static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
3079 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003080{
Takashi Iwai98274f02005-11-17 14:52:34 +01003081 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003082
Remy Bruno65345992007-08-31 12:21:08 +02003083 ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02003084 return 0;
3085}
3086
Adrian Knothf99c7882013-03-10 00:37:26 +01003087
3088
3089#define HDSPM_TCO_VIDEO_INPUT_FORMAT(xname, xindex) \
3090{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3091 .name = xname, \
3092 .access = SNDRV_CTL_ELEM_ACCESS_READ |\
3093 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3094 .info = snd_hdspm_info_tco_video_input_format, \
3095 .get = snd_hdspm_get_tco_video_input_format, \
3096}
3097
3098static int snd_hdspm_info_tco_video_input_format(struct snd_kcontrol *kcontrol,
3099 struct snd_ctl_elem_info *uinfo)
3100{
Adrian Knoth38816542013-07-05 11:28:20 +02003101 static const char *const texts[] = {"No video", "NTSC", "PAL"};
Adrian Knothf99c7882013-03-10 00:37:26 +01003102 ENUMERATED_CTL_INFO(uinfo, texts);
3103 return 0;
3104}
3105
3106static int snd_hdspm_get_tco_video_input_format(struct snd_kcontrol *kcontrol,
3107 struct snd_ctl_elem_value *ucontrol)
3108{
3109 u32 status;
3110 int ret = 0;
3111
3112 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3113 status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
3114 switch (status & (HDSPM_TCO1_Video_Input_Format_NTSC |
3115 HDSPM_TCO1_Video_Input_Format_PAL)) {
3116 case HDSPM_TCO1_Video_Input_Format_NTSC:
3117 /* ntsc */
3118 ret = 1;
3119 break;
3120 case HDSPM_TCO1_Video_Input_Format_PAL:
3121 /* pal */
3122 ret = 2;
3123 break;
3124 default:
3125 /* no video */
3126 ret = 0;
3127 break;
3128 }
3129 ucontrol->value.enumerated.item[0] = ret;
3130 return 0;
3131}
3132
3133
3134
3135#define HDSPM_TCO_LTC_FRAMES(xname, xindex) \
3136{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3137 .name = xname, \
3138 .access = SNDRV_CTL_ELEM_ACCESS_READ |\
3139 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3140 .info = snd_hdspm_info_tco_ltc_frames, \
3141 .get = snd_hdspm_get_tco_ltc_frames, \
3142}
3143
3144static int snd_hdspm_info_tco_ltc_frames(struct snd_kcontrol *kcontrol,
3145 struct snd_ctl_elem_info *uinfo)
3146{
Adrian Knoth38816542013-07-05 11:28:20 +02003147 static const char *const texts[] = {"No lock", "24 fps", "25 fps", "29.97 fps",
Adrian Knothf99c7882013-03-10 00:37:26 +01003148 "30 fps"};
3149 ENUMERATED_CTL_INFO(uinfo, texts);
3150 return 0;
3151}
3152
3153static int hdspm_tco_ltc_frames(struct hdspm *hdspm)
3154{
3155 u32 status;
3156 int ret = 0;
3157
3158 status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
3159 if (status & HDSPM_TCO1_LTC_Input_valid) {
3160 switch (status & (HDSPM_TCO1_LTC_Format_LSB |
3161 HDSPM_TCO1_LTC_Format_MSB)) {
3162 case 0:
3163 /* 24 fps */
Adrian Knoth1568b882013-08-19 17:20:31 +02003164 ret = fps_24;
Adrian Knothf99c7882013-03-10 00:37:26 +01003165 break;
3166 case HDSPM_TCO1_LTC_Format_LSB:
3167 /* 25 fps */
Adrian Knoth1568b882013-08-19 17:20:31 +02003168 ret = fps_25;
Adrian Knothf99c7882013-03-10 00:37:26 +01003169 break;
3170 case HDSPM_TCO1_LTC_Format_MSB:
Adrian Knoth1568b882013-08-19 17:20:31 +02003171 /* 29.97 fps */
3172 ret = fps_2997;
Adrian Knothf99c7882013-03-10 00:37:26 +01003173 break;
3174 default:
3175 /* 30 fps */
Adrian Knoth1568b882013-08-19 17:20:31 +02003176 ret = fps_30;
Adrian Knothf99c7882013-03-10 00:37:26 +01003177 break;
3178 }
3179 }
3180
3181 return ret;
3182}
3183
3184static int snd_hdspm_get_tco_ltc_frames(struct snd_kcontrol *kcontrol,
3185 struct snd_ctl_elem_value *ucontrol)
3186{
3187 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3188
3189 ucontrol->value.enumerated.item[0] = hdspm_tco_ltc_frames(hdspm);
3190 return 0;
3191}
3192
Adrian Knothbf0ff872012-12-03 14:55:49 +01003193#define HDSPM_TOGGLE_SETTING(xname, xindex) \
3194{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3195 .name = xname, \
3196 .private_value = xindex, \
3197 .info = snd_hdspm_info_toggle_setting, \
3198 .get = snd_hdspm_get_toggle_setting, \
3199 .put = snd_hdspm_put_toggle_setting \
3200}
3201
3202static int hdspm_toggle_setting(struct hdspm *hdspm, u32 regmask)
3203{
Adrian Knothce13f3f2013-07-05 11:27:55 +02003204 u32 reg;
3205
3206 if (hdspm_is_raydat_or_aio(hdspm))
3207 reg = hdspm->settings_register;
3208 else
3209 reg = hdspm->control_register;
3210
3211 return (reg & regmask) ? 1 : 0;
Adrian Knothbf0ff872012-12-03 14:55:49 +01003212}
3213
3214static int hdspm_set_toggle_setting(struct hdspm *hdspm, u32 regmask, int out)
3215{
Adrian Knothce13f3f2013-07-05 11:27:55 +02003216 u32 *reg;
3217 u32 target_reg;
3218
3219 if (hdspm_is_raydat_or_aio(hdspm)) {
3220 reg = &(hdspm->settings_register);
3221 target_reg = HDSPM_WR_SETTINGS;
3222 } else {
3223 reg = &(hdspm->control_register);
3224 target_reg = HDSPM_controlRegister;
3225 }
3226
Adrian Knothbf0ff872012-12-03 14:55:49 +01003227 if (out)
Adrian Knothce13f3f2013-07-05 11:27:55 +02003228 *reg |= regmask;
Adrian Knothbf0ff872012-12-03 14:55:49 +01003229 else
Adrian Knothce13f3f2013-07-05 11:27:55 +02003230 *reg &= ~regmask;
3231
3232 hdspm_write(hdspm, target_reg, *reg);
Adrian Knothbf0ff872012-12-03 14:55:49 +01003233
3234 return 0;
3235}
3236
3237#define snd_hdspm_info_toggle_setting snd_ctl_boolean_mono_info
3238
3239static int snd_hdspm_get_toggle_setting(struct snd_kcontrol *kcontrol,
3240 struct snd_ctl_elem_value *ucontrol)
3241{
3242 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3243 u32 regmask = kcontrol->private_value;
3244
3245 spin_lock_irq(&hdspm->lock);
3246 ucontrol->value.integer.value[0] = hdspm_toggle_setting(hdspm, regmask);
3247 spin_unlock_irq(&hdspm->lock);
3248 return 0;
3249}
3250
3251static int snd_hdspm_put_toggle_setting(struct snd_kcontrol *kcontrol,
3252 struct snd_ctl_elem_value *ucontrol)
3253{
3254 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3255 u32 regmask = kcontrol->private_value;
3256 int change;
3257 unsigned int val;
3258
3259 if (!snd_hdspm_use_is_exclusive(hdspm))
3260 return -EBUSY;
3261 val = ucontrol->value.integer.value[0] & 1;
3262 spin_lock_irq(&hdspm->lock);
3263 change = (int) val != hdspm_toggle_setting(hdspm, regmask);
3264 hdspm_set_toggle_setting(hdspm, regmask, val);
3265 spin_unlock_irq(&hdspm->lock);
3266 return change;
3267}
3268
Takashi Iwai763f3562005-06-03 11:25:34 +02003269#define HDSPM_INPUT_SELECT(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003270{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3271 .name = xname, \
3272 .index = xindex, \
3273 .info = snd_hdspm_info_input_select, \
3274 .get = snd_hdspm_get_input_select, \
3275 .put = snd_hdspm_put_input_select \
Takashi Iwai763f3562005-06-03 11:25:34 +02003276}
3277
Takashi Iwai98274f02005-11-17 14:52:34 +01003278static int hdspm_input_select(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003279{
3280 return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
3281}
3282
Takashi Iwai98274f02005-11-17 14:52:34 +01003283static int hdspm_set_input_select(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02003284{
3285 if (out)
3286 hdspm->control_register |= HDSPM_InputSelect0;
3287 else
3288 hdspm->control_register &= ~HDSPM_InputSelect0;
3289 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3290
3291 return 0;
3292}
3293
Takashi Iwai98274f02005-11-17 14:52:34 +01003294static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
3295 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003296{
Adrian Knoth38816542013-07-05 11:28:20 +02003297 static const char *const texts[] = { "optical", "coaxial" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003298 ENUMERATED_CTL_INFO(uinfo, texts);
Takashi Iwai763f3562005-06-03 11:25:34 +02003299 return 0;
3300}
3301
Takashi Iwai98274f02005-11-17 14:52:34 +01003302static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
3303 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003304{
Takashi Iwai98274f02005-11-17 14:52:34 +01003305 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003306
3307 spin_lock_irq(&hdspm->lock);
3308 ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
3309 spin_unlock_irq(&hdspm->lock);
3310 return 0;
3311}
3312
Takashi Iwai98274f02005-11-17 14:52:34 +01003313static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
3314 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003315{
Takashi Iwai98274f02005-11-17 14:52:34 +01003316 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003317 int change;
3318 unsigned int val;
3319
3320 if (!snd_hdspm_use_is_exclusive(hdspm))
3321 return -EBUSY;
3322 val = ucontrol->value.integer.value[0] & 1;
3323 spin_lock_irq(&hdspm->lock);
3324 change = (int) val != hdspm_input_select(hdspm);
3325 hdspm_set_input_select(hdspm, val);
3326 spin_unlock_irq(&hdspm->lock);
3327 return change;
3328}
3329
Adrian Knoth0dca1792011-01-26 19:32:14 +01003330
Remy Bruno3cee5a62006-10-16 12:46:32 +02003331#define HDSPM_DS_WIRE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003332{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3333 .name = xname, \
3334 .index = xindex, \
3335 .info = snd_hdspm_info_ds_wire, \
3336 .get = snd_hdspm_get_ds_wire, \
3337 .put = snd_hdspm_put_ds_wire \
Remy Bruno3cee5a62006-10-16 12:46:32 +02003338}
3339
3340static int hdspm_ds_wire(struct hdspm * hdspm)
3341{
3342 return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
3343}
3344
3345static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
3346{
3347 if (ds)
3348 hdspm->control_register |= HDSPM_DS_DoubleWire;
3349 else
3350 hdspm->control_register &= ~HDSPM_DS_DoubleWire;
3351 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3352
3353 return 0;
3354}
3355
3356static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
3357 struct snd_ctl_elem_info *uinfo)
3358{
Adrian Knoth38816542013-07-05 11:28:20 +02003359 static const char *const texts[] = { "Single", "Double" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003360 ENUMERATED_CTL_INFO(uinfo, texts);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003361 return 0;
3362}
3363
3364static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
3365 struct snd_ctl_elem_value *ucontrol)
3366{
3367 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3368
3369 spin_lock_irq(&hdspm->lock);
3370 ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
3371 spin_unlock_irq(&hdspm->lock);
3372 return 0;
3373}
3374
3375static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
3376 struct snd_ctl_elem_value *ucontrol)
3377{
3378 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3379 int change;
3380 unsigned int val;
3381
3382 if (!snd_hdspm_use_is_exclusive(hdspm))
3383 return -EBUSY;
3384 val = ucontrol->value.integer.value[0] & 1;
3385 spin_lock_irq(&hdspm->lock);
3386 change = (int) val != hdspm_ds_wire(hdspm);
3387 hdspm_set_ds_wire(hdspm, val);
3388 spin_unlock_irq(&hdspm->lock);
3389 return change;
3390}
3391
Adrian Knoth0dca1792011-01-26 19:32:14 +01003392
Remy Bruno3cee5a62006-10-16 12:46:32 +02003393#define HDSPM_QS_WIRE(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003394{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3395 .name = xname, \
3396 .index = xindex, \
3397 .info = snd_hdspm_info_qs_wire, \
3398 .get = snd_hdspm_get_qs_wire, \
3399 .put = snd_hdspm_put_qs_wire \
Remy Bruno3cee5a62006-10-16 12:46:32 +02003400}
3401
3402static int hdspm_qs_wire(struct hdspm * hdspm)
3403{
3404 if (hdspm->control_register & HDSPM_QS_DoubleWire)
3405 return 1;
3406 if (hdspm->control_register & HDSPM_QS_QuadWire)
3407 return 2;
3408 return 0;
3409}
3410
3411static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
3412{
3413 hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
3414 switch (mode) {
3415 case 0:
3416 break;
3417 case 1:
3418 hdspm->control_register |= HDSPM_QS_DoubleWire;
3419 break;
3420 case 2:
3421 hdspm->control_register |= HDSPM_QS_QuadWire;
3422 break;
3423 }
3424 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3425
3426 return 0;
3427}
3428
3429static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
3430 struct snd_ctl_elem_info *uinfo)
3431{
Adrian Knoth38816542013-07-05 11:28:20 +02003432 static const char *const texts[] = { "Single", "Double", "Quad" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003433 ENUMERATED_CTL_INFO(uinfo, texts);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003434 return 0;
3435}
3436
3437static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
3438 struct snd_ctl_elem_value *ucontrol)
3439{
3440 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3441
3442 spin_lock_irq(&hdspm->lock);
3443 ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
3444 spin_unlock_irq(&hdspm->lock);
3445 return 0;
3446}
3447
3448static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
3449 struct snd_ctl_elem_value *ucontrol)
3450{
3451 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3452 int change;
3453 int val;
3454
3455 if (!snd_hdspm_use_is_exclusive(hdspm))
3456 return -EBUSY;
3457 val = ucontrol->value.integer.value[0];
3458 if (val < 0)
3459 val = 0;
3460 if (val > 2)
3461 val = 2;
3462 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003463 change = val != hdspm_qs_wire(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003464 hdspm_set_qs_wire(hdspm, val);
3465 spin_unlock_irq(&hdspm->lock);
3466 return change;
3467}
3468
Adrian Knothacf14762013-07-05 11:28:00 +02003469#define HDSPM_CONTROL_TRISTATE(xname, xindex) \
3470{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3471 .name = xname, \
3472 .private_value = xindex, \
3473 .info = snd_hdspm_info_tristate, \
3474 .get = snd_hdspm_get_tristate, \
3475 .put = snd_hdspm_put_tristate \
3476}
3477
3478static int hdspm_tristate(struct hdspm *hdspm, u32 regmask)
3479{
3480 u32 reg = hdspm->settings_register & (regmask * 3);
3481 return reg / regmask;
3482}
3483
3484static int hdspm_set_tristate(struct hdspm *hdspm, int mode, u32 regmask)
3485{
3486 hdspm->settings_register &= ~(regmask * 3);
3487 hdspm->settings_register |= (regmask * mode);
3488 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
3489
3490 return 0;
3491}
3492
3493static int snd_hdspm_info_tristate(struct snd_kcontrol *kcontrol,
3494 struct snd_ctl_elem_info *uinfo)
3495{
3496 u32 regmask = kcontrol->private_value;
3497
Adrian Knoth38816542013-07-05 11:28:20 +02003498 static const char *const texts_spdif[] = { "Optical", "Coaxial", "Internal" };
3499 static const char *const texts_levels[] = { "Hi Gain", "+4 dBu", "-10 dBV" };
Adrian Knothacf14762013-07-05 11:28:00 +02003500
3501 switch (regmask) {
3502 case HDSPM_c0_Input0:
3503 ENUMERATED_CTL_INFO(uinfo, texts_spdif);
3504 break;
3505 default:
3506 ENUMERATED_CTL_INFO(uinfo, texts_levels);
3507 break;
3508 }
3509 return 0;
3510}
3511
3512static int snd_hdspm_get_tristate(struct snd_kcontrol *kcontrol,
3513 struct snd_ctl_elem_value *ucontrol)
3514{
3515 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3516 u32 regmask = kcontrol->private_value;
3517
3518 spin_lock_irq(&hdspm->lock);
3519 ucontrol->value.enumerated.item[0] = hdspm_tristate(hdspm, regmask);
3520 spin_unlock_irq(&hdspm->lock);
3521 return 0;
3522}
3523
3524static int snd_hdspm_put_tristate(struct snd_kcontrol *kcontrol,
3525 struct snd_ctl_elem_value *ucontrol)
3526{
3527 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3528 u32 regmask = kcontrol->private_value;
3529 int change;
3530 int val;
3531
3532 if (!snd_hdspm_use_is_exclusive(hdspm))
3533 return -EBUSY;
3534 val = ucontrol->value.integer.value[0];
3535 if (val < 0)
3536 val = 0;
3537 if (val > 2)
3538 val = 2;
3539
3540 spin_lock_irq(&hdspm->lock);
3541 change = val != hdspm_tristate(hdspm, regmask);
3542 hdspm_set_tristate(hdspm, val, regmask);
3543 spin_unlock_irq(&hdspm->lock);
3544 return change;
3545}
3546
Adrian Knoth700d1ef2011-07-29 03:11:02 +02003547#define HDSPM_MADI_SPEEDMODE(xname, xindex) \
3548{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3549 .name = xname, \
3550 .index = xindex, \
3551 .info = snd_hdspm_info_madi_speedmode, \
3552 .get = snd_hdspm_get_madi_speedmode, \
3553 .put = snd_hdspm_put_madi_speedmode \
3554}
3555
3556static int hdspm_madi_speedmode(struct hdspm *hdspm)
3557{
3558 if (hdspm->control_register & HDSPM_QuadSpeed)
3559 return 2;
3560 if (hdspm->control_register & HDSPM_DoubleSpeed)
3561 return 1;
3562 return 0;
3563}
3564
3565static int hdspm_set_madi_speedmode(struct hdspm *hdspm, int mode)
3566{
3567 hdspm->control_register &= ~(HDSPM_DoubleSpeed | HDSPM_QuadSpeed);
3568 switch (mode) {
3569 case 0:
3570 break;
3571 case 1:
3572 hdspm->control_register |= HDSPM_DoubleSpeed;
3573 break;
3574 case 2:
3575 hdspm->control_register |= HDSPM_QuadSpeed;
3576 break;
3577 }
3578 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3579
3580 return 0;
3581}
3582
3583static int snd_hdspm_info_madi_speedmode(struct snd_kcontrol *kcontrol,
3584 struct snd_ctl_elem_info *uinfo)
3585{
Adrian Knoth38816542013-07-05 11:28:20 +02003586 static const char *const texts[] = { "Single", "Double", "Quad" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003587 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth700d1ef2011-07-29 03:11:02 +02003588 return 0;
3589}
3590
3591static int snd_hdspm_get_madi_speedmode(struct snd_kcontrol *kcontrol,
3592 struct snd_ctl_elem_value *ucontrol)
3593{
3594 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3595
3596 spin_lock_irq(&hdspm->lock);
3597 ucontrol->value.enumerated.item[0] = hdspm_madi_speedmode(hdspm);
3598 spin_unlock_irq(&hdspm->lock);
3599 return 0;
3600}
3601
3602static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol,
3603 struct snd_ctl_elem_value *ucontrol)
3604{
3605 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3606 int change;
3607 int val;
3608
3609 if (!snd_hdspm_use_is_exclusive(hdspm))
3610 return -EBUSY;
3611 val = ucontrol->value.integer.value[0];
3612 if (val < 0)
3613 val = 0;
3614 if (val > 2)
3615 val = 2;
3616 spin_lock_irq(&hdspm->lock);
3617 change = val != hdspm_madi_speedmode(hdspm);
3618 hdspm_set_madi_speedmode(hdspm, val);
3619 spin_unlock_irq(&hdspm->lock);
3620 return change;
3621}
Takashi Iwai763f3562005-06-03 11:25:34 +02003622
3623#define HDSPM_MIXER(xname, xindex) \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003624{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
3625 .name = xname, \
3626 .index = xindex, \
3627 .device = 0, \
3628 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
3629 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3630 .info = snd_hdspm_info_mixer, \
3631 .get = snd_hdspm_get_mixer, \
3632 .put = snd_hdspm_put_mixer \
Takashi Iwai763f3562005-06-03 11:25:34 +02003633}
3634
Takashi Iwai98274f02005-11-17 14:52:34 +01003635static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
3636 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003637{
3638 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3639 uinfo->count = 3;
3640 uinfo->value.integer.min = 0;
3641 uinfo->value.integer.max = 65535;
3642 uinfo->value.integer.step = 1;
3643 return 0;
3644}
3645
Takashi Iwai98274f02005-11-17 14:52:34 +01003646static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
3647 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003648{
Takashi Iwai98274f02005-11-17 14:52:34 +01003649 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003650 int source;
3651 int destination;
3652
3653 source = ucontrol->value.integer.value[0];
3654 if (source < 0)
3655 source = 0;
3656 else if (source >= 2 * HDSPM_MAX_CHANNELS)
3657 source = 2 * HDSPM_MAX_CHANNELS - 1;
3658
3659 destination = ucontrol->value.integer.value[1];
3660 if (destination < 0)
3661 destination = 0;
3662 else if (destination >= HDSPM_MAX_CHANNELS)
3663 destination = HDSPM_MAX_CHANNELS - 1;
3664
3665 spin_lock_irq(&hdspm->lock);
3666 if (source >= HDSPM_MAX_CHANNELS)
3667 ucontrol->value.integer.value[2] =
3668 hdspm_read_pb_gain(hdspm, destination,
3669 source - HDSPM_MAX_CHANNELS);
3670 else
3671 ucontrol->value.integer.value[2] =
3672 hdspm_read_in_gain(hdspm, destination, source);
3673
3674 spin_unlock_irq(&hdspm->lock);
3675
3676 return 0;
3677}
3678
Takashi Iwai98274f02005-11-17 14:52:34 +01003679static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
3680 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003681{
Takashi Iwai98274f02005-11-17 14:52:34 +01003682 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003683 int change;
3684 int source;
3685 int destination;
3686 int gain;
3687
3688 if (!snd_hdspm_use_is_exclusive(hdspm))
3689 return -EBUSY;
3690
3691 source = ucontrol->value.integer.value[0];
3692 destination = ucontrol->value.integer.value[1];
3693
3694 if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
3695 return -1;
3696 if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
3697 return -1;
3698
3699 gain = ucontrol->value.integer.value[2];
3700
3701 spin_lock_irq(&hdspm->lock);
3702
3703 if (source >= HDSPM_MAX_CHANNELS)
3704 change = gain != hdspm_read_pb_gain(hdspm, destination,
3705 source -
3706 HDSPM_MAX_CHANNELS);
3707 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003708 change = gain != hdspm_read_in_gain(hdspm, destination,
3709 source);
Takashi Iwai763f3562005-06-03 11:25:34 +02003710
3711 if (change) {
3712 if (source >= HDSPM_MAX_CHANNELS)
3713 hdspm_write_pb_gain(hdspm, destination,
3714 source - HDSPM_MAX_CHANNELS,
3715 gain);
3716 else
3717 hdspm_write_in_gain(hdspm, destination, source,
3718 gain);
3719 }
3720 spin_unlock_irq(&hdspm->lock);
3721
3722 return change;
3723}
3724
3725/* The simple mixer control(s) provide gain control for the
3726 basic 1:1 mappings of playback streams to output
Adrian Knoth0dca1792011-01-26 19:32:14 +01003727 streams.
Takashi Iwai763f3562005-06-03 11:25:34 +02003728*/
3729
3730#define HDSPM_PLAYBACK_MIXER \
Adrian Knothf27a64f2012-10-19 17:42:30 +02003731{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3732 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
3733 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3734 .info = snd_hdspm_info_playback_mixer, \
3735 .get = snd_hdspm_get_playback_mixer, \
3736 .put = snd_hdspm_put_playback_mixer \
Takashi Iwai763f3562005-06-03 11:25:34 +02003737}
3738
Takashi Iwai98274f02005-11-17 14:52:34 +01003739static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
3740 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003741{
3742 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3743 uinfo->count = 1;
3744 uinfo->value.integer.min = 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003745 uinfo->value.integer.max = 64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003746 uinfo->value.integer.step = 1;
3747 return 0;
3748}
3749
Takashi Iwai98274f02005-11-17 14:52:34 +01003750static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
3751 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003752{
Takashi Iwai98274f02005-11-17 14:52:34 +01003753 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003754 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003755
3756 channel = ucontrol->id.index - 1;
3757
Takashi Iwaida3cec32008-08-08 17:12:14 +02003758 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3759 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003760
Takashi Iwai763f3562005-06-03 11:25:34 +02003761 spin_lock_irq(&hdspm->lock);
3762 ucontrol->value.integer.value[0] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003763 (hdspm_read_pb_gain(hdspm, channel, channel)*64)/UNITY_GAIN;
Takashi Iwai763f3562005-06-03 11:25:34 +02003764 spin_unlock_irq(&hdspm->lock);
3765
Takashi Iwai763f3562005-06-03 11:25:34 +02003766 return 0;
3767}
3768
Takashi Iwai98274f02005-11-17 14:52:34 +01003769static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
3770 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003771{
Takashi Iwai98274f02005-11-17 14:52:34 +01003772 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003773 int change;
3774 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003775 int gain;
3776
3777 if (!snd_hdspm_use_is_exclusive(hdspm))
3778 return -EBUSY;
3779
3780 channel = ucontrol->id.index - 1;
3781
Takashi Iwaida3cec32008-08-08 17:12:14 +02003782 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3783 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003784
Adrian Knoth0dca1792011-01-26 19:32:14 +01003785 gain = ucontrol->value.integer.value[0]*UNITY_GAIN/64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003786
3787 spin_lock_irq(&hdspm->lock);
3788 change =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003789 gain != hdspm_read_pb_gain(hdspm, channel,
3790 channel);
Takashi Iwai763f3562005-06-03 11:25:34 +02003791 if (change)
Adrian Knoth0dca1792011-01-26 19:32:14 +01003792 hdspm_write_pb_gain(hdspm, channel, channel,
Takashi Iwai763f3562005-06-03 11:25:34 +02003793 gain);
3794 spin_unlock_irq(&hdspm->lock);
3795 return change;
3796}
3797
Adrian Knoth0dca1792011-01-26 19:32:14 +01003798#define HDSPM_SYNC_CHECK(xname, xindex) \
3799{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3800 .name = xname, \
3801 .private_value = xindex, \
3802 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3803 .info = snd_hdspm_info_sync_check, \
3804 .get = snd_hdspm_get_sync_check \
Takashi Iwai763f3562005-06-03 11:25:34 +02003805}
3806
Adrian Knoth34542212013-03-10 00:37:25 +01003807#define HDSPM_TCO_LOCK_CHECK(xname, xindex) \
3808{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3809 .name = xname, \
3810 .private_value = xindex, \
3811 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3812 .info = snd_hdspm_tco_info_lock_check, \
3813 .get = snd_hdspm_get_sync_check \
3814}
3815
3816
Adrian Knoth0dca1792011-01-26 19:32:14 +01003817
Takashi Iwai98274f02005-11-17 14:52:34 +01003818static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
3819 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003820{
Adrian Knoth38816542013-07-05 11:28:20 +02003821 static const char *const texts[] = { "No Lock", "Lock", "Sync", "N/A" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01003822 ENUMERATED_CTL_INFO(uinfo, texts);
Takashi Iwai763f3562005-06-03 11:25:34 +02003823 return 0;
3824}
3825
Adrian Knoth34542212013-03-10 00:37:25 +01003826static int snd_hdspm_tco_info_lock_check(struct snd_kcontrol *kcontrol,
3827 struct snd_ctl_elem_info *uinfo)
3828{
Adrian Knoth38816542013-07-05 11:28:20 +02003829 static const char *const texts[] = { "No Lock", "Lock" };
Adrian Knoth34542212013-03-10 00:37:25 +01003830 ENUMERATED_CTL_INFO(uinfo, texts);
3831 return 0;
3832}
3833
Adrian Knoth0dca1792011-01-26 19:32:14 +01003834static int hdspm_wc_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003835{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003836 int status, status2;
3837
3838 switch (hdspm->io_type) {
3839 case AES32:
3840 status = hdspm_read(hdspm, HDSPM_statusRegister);
Andre Schramm56bde0f2013-01-09 14:40:18 +01003841 if (status & HDSPM_AES32_wcLock) {
3842 if (status & HDSPM_AES32_wcSync)
3843 return 2;
3844 else
3845 return 1;
3846 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02003847 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003848 break;
3849
3850 case MADI:
3851 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003852 if (status2 & HDSPM_wcLock) {
3853 if (status2 & HDSPM_wcSync)
3854 return 2;
3855 else
3856 return 1;
3857 }
3858 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003859 break;
3860
3861 case RayDAT:
3862 case AIO:
3863 status = hdspm_read(hdspm, HDSPM_statusRegister);
3864
3865 if (status & 0x2000000)
3866 return 2;
3867 else if (status & 0x1000000)
3868 return 1;
3869 return 0;
3870
3871 break;
3872
3873 case MADIface:
3874 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02003875 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003876
Takashi Iwai763f3562005-06-03 11:25:34 +02003877
Adrian Knoth0dca1792011-01-26 19:32:14 +01003878 return 3;
Takashi Iwai763f3562005-06-03 11:25:34 +02003879}
3880
3881
Adrian Knoth0dca1792011-01-26 19:32:14 +01003882static int hdspm_madi_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003883{
3884 int status = hdspm_read(hdspm, HDSPM_statusRegister);
3885 if (status & HDSPM_madiLock) {
3886 if (status & HDSPM_madiSync)
3887 return 2;
3888 else
3889 return 1;
3890 }
3891 return 0;
3892}
3893
Adrian Knoth0dca1792011-01-26 19:32:14 +01003894
3895static int hdspm_s1_sync_check(struct hdspm *hdspm, int idx)
3896{
3897 int status, lock, sync;
3898
3899 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3900
3901 lock = (status & (0x1<<idx)) ? 1 : 0;
3902 sync = (status & (0x100<<idx)) ? 1 : 0;
3903
3904 if (lock && sync)
3905 return 2;
3906 else if (lock)
3907 return 1;
3908 return 0;
3909}
3910
3911
3912static int hdspm_sync_in_sync_check(struct hdspm *hdspm)
3913{
3914 int status, lock = 0, sync = 0;
3915
3916 switch (hdspm->io_type) {
3917 case RayDAT:
3918 case AIO:
3919 status = hdspm_read(hdspm, HDSPM_RD_STATUS_3);
3920 lock = (status & 0x400) ? 1 : 0;
3921 sync = (status & 0x800) ? 1 : 0;
3922 break;
3923
3924 case MADI:
Adrian Knoth2e0452f2012-10-19 17:42:27 +02003925 status = hdspm_read(hdspm, HDSPM_statusRegister);
3926 lock = (status & HDSPM_syncInLock) ? 1 : 0;
3927 sync = (status & HDSPM_syncInSync) ? 1 : 0;
3928 break;
3929
Adrian Knoth0dca1792011-01-26 19:32:14 +01003930 case AES32:
3931 status = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth9a215f42012-10-19 17:42:28 +02003932 lock = (status & 0x100000) ? 1 : 0;
3933 sync = (status & 0x200000) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003934 break;
3935
3936 case MADIface:
3937 break;
3938 }
3939
3940 if (lock && sync)
3941 return 2;
3942 else if (lock)
3943 return 1;
3944
3945 return 0;
3946}
3947
3948static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx)
3949{
3950 int status2, lock, sync;
3951 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
3952
3953 lock = (status2 & (0x0080 >> idx)) ? 1 : 0;
3954 sync = (status2 & (0x8000 >> idx)) ? 1 : 0;
3955
3956 if (sync)
3957 return 2;
3958 else if (lock)
3959 return 1;
3960 return 0;
3961}
3962
Adrian Knoth34542212013-03-10 00:37:25 +01003963static int hdspm_tco_input_check(struct hdspm *hdspm, u32 mask)
3964{
3965 u32 status;
3966 status = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
3967
3968 return (status & mask) ? 1 : 0;
3969}
3970
Adrian Knoth0dca1792011-01-26 19:32:14 +01003971
3972static int hdspm_tco_sync_check(struct hdspm *hdspm)
3973{
3974 int status;
3975
3976 if (hdspm->tco) {
3977 switch (hdspm->io_type) {
3978 case MADI:
Adrian Knothb0bf5502013-07-05 11:28:05 +02003979 status = hdspm_read(hdspm, HDSPM_statusRegister);
3980 if (status & HDSPM_tcoLockMadi) {
3981 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 AES32:
3988 status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knothb0bf5502013-07-05 11:28:05 +02003989 if (status & HDSPM_tcoLockAes) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01003990 if (status & HDSPM_tcoSync)
3991 return 2;
3992 else
3993 return 1;
3994 }
3995 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003996 case RayDAT:
3997 case AIO:
3998 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3999
4000 if (status & 0x8000000)
4001 return 2; /* Sync */
4002 if (status & 0x4000000)
4003 return 1; /* Lock */
4004 return 0; /* No signal */
Adrian Knoth0dca1792011-01-26 19:32:14 +01004005
4006 default:
4007 break;
4008 }
4009 }
4010
4011 return 3; /* N/A */
4012}
4013
4014
4015static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
4016 struct snd_ctl_elem_value *ucontrol)
4017{
4018 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4019 int val = -1;
4020
4021 switch (hdspm->io_type) {
4022 case RayDAT:
4023 switch (kcontrol->private_value) {
4024 case 0: /* WC */
4025 val = hdspm_wc_sync_check(hdspm); break;
4026 case 7: /* TCO */
4027 val = hdspm_tco_sync_check(hdspm); break;
4028 case 8: /* SYNC IN */
4029 val = hdspm_sync_in_sync_check(hdspm); break;
4030 default:
Adrian Knothd1a3c982012-11-07 18:00:09 +01004031 val = hdspm_s1_sync_check(hdspm,
4032 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004033 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02004034 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004035
4036 case AIO:
4037 switch (kcontrol->private_value) {
4038 case 0: /* WC */
4039 val = hdspm_wc_sync_check(hdspm); break;
4040 case 4: /* TCO */
4041 val = hdspm_tco_sync_check(hdspm); break;
4042 case 5: /* SYNC IN */
4043 val = hdspm_sync_in_sync_check(hdspm); break;
4044 default:
Adrian Knoth1cb7dbf2013-07-05 11:28:03 +02004045 val = hdspm_s1_sync_check(hdspm,
4046 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004047 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02004048 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004049
4050 case MADI:
4051 switch (kcontrol->private_value) {
4052 case 0: /* WC */
4053 val = hdspm_wc_sync_check(hdspm); break;
4054 case 1: /* MADI */
4055 val = hdspm_madi_sync_check(hdspm); break;
4056 case 2: /* TCO */
4057 val = hdspm_tco_sync_check(hdspm); break;
4058 case 3: /* SYNC_IN */
4059 val = hdspm_sync_in_sync_check(hdspm); break;
4060 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02004061 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004062
4063 case MADIface:
4064 val = hdspm_madi_sync_check(hdspm); /* MADI */
4065 break;
4066
4067 case AES32:
4068 switch (kcontrol->private_value) {
4069 case 0: /* WC */
4070 val = hdspm_wc_sync_check(hdspm); break;
4071 case 9: /* TCO */
4072 val = hdspm_tco_sync_check(hdspm); break;
4073 case 10 /* SYNC IN */:
4074 val = hdspm_sync_in_sync_check(hdspm); break;
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01004075 default: /* AES1 to AES8 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01004076 val = hdspm_aes_sync_check(hdspm,
Adrian Knoth7c4a95b2011-02-23 11:43:13 +01004077 kcontrol->private_value-1);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004078 }
Adrian Knothfba30fd2012-10-19 17:42:24 +02004079 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004080
4081 }
4082
Adrian Knoth34542212013-03-10 00:37:25 +01004083 if (hdspm->tco) {
4084 switch (kcontrol->private_value) {
4085 case 11:
4086 /* Check TCO for lock state of its current input */
4087 val = hdspm_tco_input_check(hdspm, HDSPM_TCO1_TCO_lock);
4088 break;
4089 case 12:
4090 /* Check TCO for valid time code on LTC input. */
4091 val = hdspm_tco_input_check(hdspm,
4092 HDSPM_TCO1_LTC_Input_valid);
4093 break;
4094 default:
4095 break;
4096 }
4097 }
4098
Adrian Knoth0dca1792011-01-26 19:32:14 +01004099 if (-1 == val)
4100 val = 3;
4101
4102 ucontrol->value.enumerated.item[0] = val;
4103 return 0;
4104}
4105
4106
4107
Takashi Iwaiddcecf62014-11-10 17:24:26 +01004108/*
Adrian Knoth0dca1792011-01-26 19:32:14 +01004109 * TCO controls
Takashi Iwaiddcecf62014-11-10 17:24:26 +01004110 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01004111static void hdspm_tco_write(struct hdspm *hdspm)
4112{
4113 unsigned int tc[4] = { 0, 0, 0, 0};
4114
4115 switch (hdspm->tco->input) {
4116 case 0:
4117 tc[2] |= HDSPM_TCO2_set_input_MSB;
4118 break;
4119 case 1:
4120 tc[2] |= HDSPM_TCO2_set_input_LSB;
4121 break;
4122 default:
4123 break;
4124 }
4125
4126 switch (hdspm->tco->framerate) {
4127 case 1:
4128 tc[1] |= HDSPM_TCO1_LTC_Format_LSB;
4129 break;
4130 case 2:
4131 tc[1] |= HDSPM_TCO1_LTC_Format_MSB;
4132 break;
4133 case 3:
4134 tc[1] |= HDSPM_TCO1_LTC_Format_MSB +
4135 HDSPM_TCO1_set_drop_frame_flag;
4136 break;
4137 case 4:
4138 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
4139 HDSPM_TCO1_LTC_Format_MSB;
4140 break;
4141 case 5:
4142 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
4143 HDSPM_TCO1_LTC_Format_MSB +
4144 HDSPM_TCO1_set_drop_frame_flag;
4145 break;
4146 default:
4147 break;
4148 }
4149
4150 switch (hdspm->tco->wordclock) {
4151 case 1:
4152 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_LSB;
4153 break;
4154 case 2:
4155 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_MSB;
4156 break;
4157 default:
4158 break;
4159 }
4160
4161 switch (hdspm->tco->samplerate) {
4162 case 1:
4163 tc[2] |= HDSPM_TCO2_set_freq;
4164 break;
4165 case 2:
4166 tc[2] |= HDSPM_TCO2_set_freq_from_app;
4167 break;
4168 default:
4169 break;
4170 }
4171
4172 switch (hdspm->tco->pull) {
4173 case 1:
4174 tc[2] |= HDSPM_TCO2_set_pull_up;
4175 break;
4176 case 2:
4177 tc[2] |= HDSPM_TCO2_set_pull_down;
4178 break;
4179 case 3:
4180 tc[2] |= HDSPM_TCO2_set_pull_up + HDSPM_TCO2_set_01_4;
4181 break;
4182 case 4:
4183 tc[2] |= HDSPM_TCO2_set_pull_down + HDSPM_TCO2_set_01_4;
4184 break;
4185 default:
4186 break;
4187 }
4188
4189 if (1 == hdspm->tco->term) {
4190 tc[2] |= HDSPM_TCO2_set_term_75R;
4191 }
4192
4193 hdspm_write(hdspm, HDSPM_WR_TCO, tc[0]);
4194 hdspm_write(hdspm, HDSPM_WR_TCO+4, tc[1]);
4195 hdspm_write(hdspm, HDSPM_WR_TCO+8, tc[2]);
4196 hdspm_write(hdspm, HDSPM_WR_TCO+12, tc[3]);
4197}
4198
4199
4200#define HDSPM_TCO_SAMPLE_RATE(xname, xindex) \
4201{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4202 .name = xname, \
4203 .index = xindex, \
4204 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4205 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4206 .info = snd_hdspm_info_tco_sample_rate, \
4207 .get = snd_hdspm_get_tco_sample_rate, \
4208 .put = snd_hdspm_put_tco_sample_rate \
4209}
4210
4211static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol,
4212 struct snd_ctl_elem_info *uinfo)
4213{
Martin Dausel69358fc2013-07-05 11:28:23 +02004214 /* TODO freq from app could be supported here, see tco->samplerate */
Adrian Knoth38816542013-07-05 11:28:20 +02004215 static const char *const texts[] = { "44.1 kHz", "48 kHz" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004216 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004217 return 0;
4218}
4219
4220static int snd_hdspm_get_tco_sample_rate(struct snd_kcontrol *kcontrol,
4221 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02004222{
Takashi Iwai98274f02005-11-17 14:52:34 +01004223 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02004224
Adrian Knoth0dca1792011-01-26 19:32:14 +01004225 ucontrol->value.enumerated.item[0] = hdspm->tco->samplerate;
4226
Takashi Iwai763f3562005-06-03 11:25:34 +02004227 return 0;
4228}
4229
Adrian Knoth0dca1792011-01-26 19:32:14 +01004230static int snd_hdspm_put_tco_sample_rate(struct snd_kcontrol *kcontrol,
4231 struct snd_ctl_elem_value *ucontrol)
Remy Bruno3cee5a62006-10-16 12:46:32 +02004232{
Adrian Knoth0dca1792011-01-26 19:32:14 +01004233 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4234
4235 if (hdspm->tco->samplerate != ucontrol->value.enumerated.item[0]) {
4236 hdspm->tco->samplerate = ucontrol->value.enumerated.item[0];
4237
4238 hdspm_tco_write(hdspm);
4239
4240 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004241 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01004242
Remy Bruno3cee5a62006-10-16 12:46:32 +02004243 return 0;
4244}
4245
Adrian Knoth0dca1792011-01-26 19:32:14 +01004246
4247#define HDSPM_TCO_PULL(xname, xindex) \
4248{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4249 .name = xname, \
4250 .index = xindex, \
4251 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4252 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4253 .info = snd_hdspm_info_tco_pull, \
4254 .get = snd_hdspm_get_tco_pull, \
4255 .put = snd_hdspm_put_tco_pull \
4256}
4257
4258static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol,
4259 struct snd_ctl_elem_info *uinfo)
4260{
Adrian Knoth38816542013-07-05 11:28:20 +02004261 static const char *const texts[] = { "0", "+ 0.1 %", "- 0.1 %",
4262 "+ 4 %", "- 4 %" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004263 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004264 return 0;
4265}
4266
4267static int snd_hdspm_get_tco_pull(struct snd_kcontrol *kcontrol,
4268 struct snd_ctl_elem_value *ucontrol)
4269{
4270 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4271
4272 ucontrol->value.enumerated.item[0] = hdspm->tco->pull;
4273
4274 return 0;
4275}
4276
4277static int snd_hdspm_put_tco_pull(struct snd_kcontrol *kcontrol,
4278 struct snd_ctl_elem_value *ucontrol)
4279{
4280 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4281
4282 if (hdspm->tco->pull != ucontrol->value.enumerated.item[0]) {
4283 hdspm->tco->pull = ucontrol->value.enumerated.item[0];
4284
4285 hdspm_tco_write(hdspm);
4286
4287 return 1;
4288 }
4289
4290 return 0;
4291}
4292
4293#define HDSPM_TCO_WCK_CONVERSION(xname, xindex) \
4294{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4295 .name = xname, \
4296 .index = xindex, \
4297 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4298 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4299 .info = snd_hdspm_info_tco_wck_conversion, \
4300 .get = snd_hdspm_get_tco_wck_conversion, \
4301 .put = snd_hdspm_put_tco_wck_conversion \
4302}
4303
4304static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4305 struct snd_ctl_elem_info *uinfo)
4306{
Adrian Knoth38816542013-07-05 11:28:20 +02004307 static const char *const texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004308 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004309 return 0;
4310}
4311
4312static int snd_hdspm_get_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4313 struct snd_ctl_elem_value *ucontrol)
4314{
4315 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4316
4317 ucontrol->value.enumerated.item[0] = hdspm->tco->wordclock;
4318
4319 return 0;
4320}
4321
4322static int snd_hdspm_put_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4323 struct snd_ctl_elem_value *ucontrol)
4324{
4325 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4326
4327 if (hdspm->tco->wordclock != ucontrol->value.enumerated.item[0]) {
4328 hdspm->tco->wordclock = ucontrol->value.enumerated.item[0];
4329
4330 hdspm_tco_write(hdspm);
4331
4332 return 1;
4333 }
4334
4335 return 0;
4336}
4337
4338
4339#define HDSPM_TCO_FRAME_RATE(xname, xindex) \
4340{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4341 .name = xname, \
4342 .index = xindex, \
4343 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4344 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4345 .info = snd_hdspm_info_tco_frame_rate, \
4346 .get = snd_hdspm_get_tco_frame_rate, \
4347 .put = snd_hdspm_put_tco_frame_rate \
4348}
4349
4350static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol,
4351 struct snd_ctl_elem_info *uinfo)
4352{
Adrian Knoth38816542013-07-05 11:28:20 +02004353 static const char *const texts[] = { "24 fps", "25 fps", "29.97fps",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004354 "29.97 dfps", "30 fps", "30 dfps" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004355 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004356 return 0;
4357}
4358
4359static int snd_hdspm_get_tco_frame_rate(struct snd_kcontrol *kcontrol,
Remy Bruno3cee5a62006-10-16 12:46:32 +02004360 struct snd_ctl_elem_value *ucontrol)
4361{
Remy Bruno3cee5a62006-10-16 12:46:32 +02004362 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4363
Adrian Knoth0dca1792011-01-26 19:32:14 +01004364 ucontrol->value.enumerated.item[0] = hdspm->tco->framerate;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004365
Remy Bruno3cee5a62006-10-16 12:46:32 +02004366 return 0;
4367}
Takashi Iwai763f3562005-06-03 11:25:34 +02004368
Adrian Knoth0dca1792011-01-26 19:32:14 +01004369static int snd_hdspm_put_tco_frame_rate(struct snd_kcontrol *kcontrol,
4370 struct snd_ctl_elem_value *ucontrol)
4371{
4372 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4373
4374 if (hdspm->tco->framerate != ucontrol->value.enumerated.item[0]) {
4375 hdspm->tco->framerate = ucontrol->value.enumerated.item[0];
4376
4377 hdspm_tco_write(hdspm);
4378
4379 return 1;
4380 }
4381
4382 return 0;
4383}
4384
4385
4386#define HDSPM_TCO_SYNC_SOURCE(xname, xindex) \
4387{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4388 .name = xname, \
4389 .index = xindex, \
4390 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4391 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4392 .info = snd_hdspm_info_tco_sync_source, \
4393 .get = snd_hdspm_get_tco_sync_source, \
4394 .put = snd_hdspm_put_tco_sync_source \
4395}
4396
4397static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol,
4398 struct snd_ctl_elem_info *uinfo)
4399{
Adrian Knoth38816542013-07-05 11:28:20 +02004400 static const char *const texts[] = { "LTC", "Video", "WCK" };
Adrian Knothe5b7b1f2013-03-10 00:37:24 +01004401 ENUMERATED_CTL_INFO(uinfo, texts);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004402 return 0;
4403}
4404
4405static int snd_hdspm_get_tco_sync_source(struct snd_kcontrol *kcontrol,
4406 struct snd_ctl_elem_value *ucontrol)
4407{
4408 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4409
4410 ucontrol->value.enumerated.item[0] = hdspm->tco->input;
4411
4412 return 0;
4413}
4414
4415static int snd_hdspm_put_tco_sync_source(struct snd_kcontrol *kcontrol,
4416 struct snd_ctl_elem_value *ucontrol)
4417{
4418 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4419
4420 if (hdspm->tco->input != ucontrol->value.enumerated.item[0]) {
4421 hdspm->tco->input = ucontrol->value.enumerated.item[0];
4422
4423 hdspm_tco_write(hdspm);
4424
4425 return 1;
4426 }
4427
4428 return 0;
4429}
4430
4431
4432#define HDSPM_TCO_WORD_TERM(xname, xindex) \
4433{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4434 .name = xname, \
4435 .index = xindex, \
4436 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4437 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4438 .info = snd_hdspm_info_tco_word_term, \
4439 .get = snd_hdspm_get_tco_word_term, \
4440 .put = snd_hdspm_put_tco_word_term \
4441}
4442
4443static int snd_hdspm_info_tco_word_term(struct snd_kcontrol *kcontrol,
4444 struct snd_ctl_elem_info *uinfo)
4445{
4446 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
4447 uinfo->count = 1;
4448 uinfo->value.integer.min = 0;
4449 uinfo->value.integer.max = 1;
4450
4451 return 0;
4452}
4453
4454
4455static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol,
4456 struct snd_ctl_elem_value *ucontrol)
4457{
4458 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4459
Takashi Iwai537e4812016-02-29 14:25:16 +01004460 ucontrol->value.integer.value[0] = hdspm->tco->term;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004461
4462 return 0;
4463}
4464
4465
4466static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol,
4467 struct snd_ctl_elem_value *ucontrol)
4468{
4469 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4470
Takashi Iwai537e4812016-02-29 14:25:16 +01004471 if (hdspm->tco->term != ucontrol->value.integer.value[0]) {
4472 hdspm->tco->term = ucontrol->value.integer.value[0];
Adrian Knoth0dca1792011-01-26 19:32:14 +01004473
4474 hdspm_tco_write(hdspm);
4475
4476 return 1;
4477 }
4478
4479 return 0;
4480}
4481
4482
4483
Takashi Iwai763f3562005-06-03 11:25:34 +02004484
Takashi Iwaib4e5e702020-01-03 09:16:53 +01004485static const struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004486 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004487 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Takashi Iwai763f3562005-06-03 11:25:34 +02004488 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4489 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4490 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4491 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Adrian Knothb8812c52012-10-19 17:42:26 +02004492 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004493 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4494 HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
Adrian Knoth930f4ff2012-10-19 17:42:29 +02004495 HDSPM_SYNC_CHECK("TCO SyncCheck", 2),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004496 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
Adrian Knothc9e16682012-12-03 14:55:50 +01004497 HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
4498 HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
Adrian Knoth696be0f2013-03-10 00:37:23 +01004499 HDSPM_TOGGLE_SETTING("Disable 96K frames", HDSPM_SMUX),
Adrian Knothc9e16682012-12-03 14:55:50 +01004500 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
4501 HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
Adrian Knoth700d1ef2011-07-29 03:11:02 +02004502 HDSPM_INPUT_SELECT("Input Select", 0),
4503 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004504};
4505
4506
Takashi Iwaib4e5e702020-01-03 09:16:53 +01004507static const struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004508 HDSPM_MIXER("Mixer", 0),
4509 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4510 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4511 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4512 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4513 HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
Adrian Knothc9e16682012-12-03 14:55:50 +01004514 HDSPM_TOGGLE_SETTING("TX 64 channels mode", HDSPM_TX_64ch),
4515 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
4516 HDSPM_TOGGLE_SETTING("Safe Mode", HDSPM_AutoInp),
Adrian Knoth700d1ef2011-07-29 03:11:02 +02004517 HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004518};
4519
Takashi Iwaib4e5e702020-01-03 09:16:53 +01004520static const struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004521 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004522 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004523 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4524 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004525 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004526 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004527 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4528 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4529 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4530 HDSPM_SYNC_CHECK("ADAT SyncCheck", 3),
4531 HDSPM_SYNC_CHECK("TCO SyncCheck", 4),
4532 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 5),
4533 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4534 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4535 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4536 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT Frequency", 3),
4537 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 4),
Adrian Knothfb0f1212013-07-05 11:27:58 +02004538 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5),
Adrian Knoth42f4c122013-07-05 11:28:01 +02004539 HDSPM_CONTROL_TRISTATE("S/PDIF Input", HDSPM_c0_Input0),
Adrian Knothfb0f1212013-07-05 11:27:58 +02004540 HDSPM_TOGGLE_SETTING("S/PDIF Out Optical", HDSPM_c0_Spdif_Opt),
4541 HDSPM_TOGGLE_SETTING("S/PDIF Out Professional", HDSPM_c0_Pro),
4542 HDSPM_TOGGLE_SETTING("ADAT internal (AEB/TEB)", HDSPM_c0_AEB1),
4543 HDSPM_TOGGLE_SETTING("XLR Breakout Cable", HDSPM_c0_Sym6db),
Adrian Knoth42f4c122013-07-05 11:28:01 +02004544 HDSPM_TOGGLE_SETTING("Single Speed WordClock Out", HDSPM_c0_Wck48),
4545 HDSPM_CONTROL_TRISTATE("Input Level", HDSPM_c0_AD_GAIN0),
4546 HDSPM_CONTROL_TRISTATE("Output Level", HDSPM_c0_DA_GAIN0),
4547 HDSPM_CONTROL_TRISTATE("Phones Level", HDSPM_c0_PH_GAIN0)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004548
4549 /*
4550 HDSPM_INPUT_SELECT("Input Select", 0),
4551 HDSPM_SPDIF_OPTICAL("SPDIF Out Optical", 0),
4552 HDSPM_PROFESSIONAL("SPDIF Out Professional", 0);
4553 HDSPM_SPDIF_IN("SPDIF In", 0);
4554 HDSPM_BREAKOUT_CABLE("Breakout Cable", 0);
4555 HDSPM_INPUT_LEVEL("Input Level", 0);
4556 HDSPM_OUTPUT_LEVEL("Output Level", 0);
4557 HDSPM_PHONES("Phones", 0);
4558 */
4559};
4560
Takashi Iwaib4e5e702020-01-03 09:16:53 +01004561static const struct snd_kcontrol_new snd_hdspm_controls_raydat[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004562 HDSPM_MIXER("Mixer", 0),
4563 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4564 HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0),
4565 HDSPM_PREF_SYNC_REF("Pref Sync Ref", 0),
4566 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4567 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4568 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4569 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4570 HDSPM_SYNC_CHECK("ADAT1 SyncCheck", 3),
4571 HDSPM_SYNC_CHECK("ADAT2 SyncCheck", 4),
4572 HDSPM_SYNC_CHECK("ADAT3 SyncCheck", 5),
4573 HDSPM_SYNC_CHECK("ADAT4 SyncCheck", 6),
4574 HDSPM_SYNC_CHECK("TCO SyncCheck", 7),
4575 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 8),
4576 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4577 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4578 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4579 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT1 Frequency", 3),
4580 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT2 Frequency", 4),
4581 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT3 Frequency", 5),
4582 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT4 Frequency", 6),
4583 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 7),
Adrian Knoth11a5cd32013-07-05 11:27:57 +02004584 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8),
4585 HDSPM_TOGGLE_SETTING("S/PDIF Out Professional", HDSPM_c0_Pro),
4586 HDSPM_TOGGLE_SETTING("Single Speed WordClock Out", HDSPM_c0_Wck48)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004587};
4588
Takashi Iwaib4e5e702020-01-03 09:16:53 +01004589static const struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004590 HDSPM_MIXER("Mixer", 0),
4591 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4592 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4593 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4594 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4595 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Adrian Knoth2d63ec32013-07-05 11:28:18 +02004596 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 11),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004597 HDSPM_SYNC_CHECK("WC Sync Check", 0),
4598 HDSPM_SYNC_CHECK("AES1 Sync Check", 1),
4599 HDSPM_SYNC_CHECK("AES2 Sync Check", 2),
4600 HDSPM_SYNC_CHECK("AES3 Sync Check", 3),
4601 HDSPM_SYNC_CHECK("AES4 Sync Check", 4),
4602 HDSPM_SYNC_CHECK("AES5 Sync Check", 5),
4603 HDSPM_SYNC_CHECK("AES6 Sync Check", 6),
4604 HDSPM_SYNC_CHECK("AES7 Sync Check", 7),
4605 HDSPM_SYNC_CHECK("AES8 Sync Check", 8),
4606 HDSPM_SYNC_CHECK("TCO Sync Check", 9),
4607 HDSPM_SYNC_CHECK("SYNC IN Sync Check", 10),
4608 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4609 HDSPM_AUTOSYNC_SAMPLE_RATE("AES1 Frequency", 1),
4610 HDSPM_AUTOSYNC_SAMPLE_RATE("AES2 Frequency", 2),
4611 HDSPM_AUTOSYNC_SAMPLE_RATE("AES3 Frequency", 3),
4612 HDSPM_AUTOSYNC_SAMPLE_RATE("AES4 Frequency", 4),
4613 HDSPM_AUTOSYNC_SAMPLE_RATE("AES5 Frequency", 5),
4614 HDSPM_AUTOSYNC_SAMPLE_RATE("AES6 Frequency", 6),
4615 HDSPM_AUTOSYNC_SAMPLE_RATE("AES7 Frequency", 7),
4616 HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8),
4617 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9),
4618 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10),
Adrian Knothc9e16682012-12-03 14:55:50 +01004619 HDSPM_TOGGLE_SETTING("Line Out", HDSPM_LineOut),
4620 HDSPM_TOGGLE_SETTING("Emphasis", HDSPM_Emphasis),
4621 HDSPM_TOGGLE_SETTING("Non Audio", HDSPM_Dolby),
4622 HDSPM_TOGGLE_SETTING("Professional", HDSPM_Professional),
4623 HDSPM_TOGGLE_SETTING("Clear Track Marker", HDSPM_clr_tms),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004624 HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
4625 HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
4626};
4627
Adrian Knoth0dca1792011-01-26 19:32:14 +01004628
4629
4630/* Control elements for the optional TCO module */
Takashi Iwaib4e5e702020-01-03 09:16:53 +01004631static const struct snd_kcontrol_new snd_hdspm_controls_tco[] = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004632 HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0),
4633 HDSPM_TCO_PULL("TCO Pull", 0),
4634 HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0),
4635 HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0),
4636 HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0),
Adrian Knotha8176502013-03-10 00:37:27 +01004637 HDSPM_TCO_WORD_TERM("TCO Word Term", 0),
4638 HDSPM_TCO_LOCK_CHECK("TCO Input Check", 11),
4639 HDSPM_TCO_LOCK_CHECK("TCO LTC Valid", 12),
4640 HDSPM_TCO_LTC_FRAMES("TCO Detected Frame Rate", 0),
4641 HDSPM_TCO_VIDEO_INPUT_FORMAT("Video Input Format", 0)
Adrian Knoth0dca1792011-01-26 19:32:14 +01004642};
4643
4644
Takashi Iwai98274f02005-11-17 14:52:34 +01004645static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
Takashi Iwai763f3562005-06-03 11:25:34 +02004646
4647
Takashi Iwai98274f02005-11-17 14:52:34 +01004648static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004649{
4650 int i;
4651
Adrian Knoth0dca1792011-01-26 19:32:14 +01004652 for (i = hdspm->ds_out_channels; i < hdspm->ss_out_channels; ++i) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004653 if (hdspm->system_sample_rate > 48000) {
4654 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004655 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
4656 SNDRV_CTL_ELEM_ACCESS_READ |
4657 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004658 } else {
4659 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004660 SNDRV_CTL_ELEM_ACCESS_READWRITE |
4661 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004662 }
4663 snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
Adrian Knoth0dca1792011-01-26 19:32:14 +01004664 SNDRV_CTL_EVENT_MASK_INFO,
4665 &hdspm->playback_mixer_ctls[i]->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02004666 }
4667
4668 return 0;
4669}
4670
4671
Adrian Knoth0dca1792011-01-26 19:32:14 +01004672static int snd_hdspm_create_controls(struct snd_card *card,
4673 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004674{
4675 unsigned int idx, limit;
4676 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01004677 struct snd_kcontrol *kctl;
Takashi Iwaib4e5e702020-01-03 09:16:53 +01004678 const struct snd_kcontrol_new *list = NULL;
Takashi Iwai763f3562005-06-03 11:25:34 +02004679
Adrian Knoth0dca1792011-01-26 19:32:14 +01004680 switch (hdspm->io_type) {
4681 case MADI:
4682 list = snd_hdspm_controls_madi;
4683 limit = ARRAY_SIZE(snd_hdspm_controls_madi);
4684 break;
4685 case MADIface:
4686 list = snd_hdspm_controls_madiface;
4687 limit = ARRAY_SIZE(snd_hdspm_controls_madiface);
4688 break;
4689 case AIO:
4690 list = snd_hdspm_controls_aio;
4691 limit = ARRAY_SIZE(snd_hdspm_controls_aio);
4692 break;
4693 case RayDAT:
4694 list = snd_hdspm_controls_raydat;
4695 limit = ARRAY_SIZE(snd_hdspm_controls_raydat);
4696 break;
4697 case AES32:
4698 list = snd_hdspm_controls_aes32;
4699 limit = ARRAY_SIZE(snd_hdspm_controls_aes32);
4700 break;
4701 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004702
Markus Elfringda2ea372017-08-12 17:07:09 +02004703 if (list) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004704 for (idx = 0; idx < limit; idx++) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004705 err = snd_ctl_add(card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004706 snd_ctl_new1(&list[idx], hdspm));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004707 if (err < 0)
4708 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004709 }
4710 }
4711
Takashi Iwai763f3562005-06-03 11:25:34 +02004712
Adrian Knoth0dca1792011-01-26 19:32:14 +01004713 /* create simple 1:1 playback mixer controls */
Takashi Iwai763f3562005-06-03 11:25:34 +02004714 snd_hdspm_playback_mixer.name = "Chn";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004715 if (hdspm->system_sample_rate >= 128000) {
4716 limit = hdspm->qs_out_channels;
4717 } else if (hdspm->system_sample_rate >= 64000) {
4718 limit = hdspm->ds_out_channels;
4719 } else {
4720 limit = hdspm->ss_out_channels;
4721 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004722 for (idx = 0; idx < limit; ++idx) {
4723 snd_hdspm_playback_mixer.index = idx + 1;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004724 kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm);
4725 err = snd_ctl_add(card, kctl);
4726 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004727 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004728 hdspm->playback_mixer_ctls[idx] = kctl;
4729 }
4730
Adrian Knoth0dca1792011-01-26 19:32:14 +01004731
4732 if (hdspm->tco) {
4733 /* add tco control elements */
4734 list = snd_hdspm_controls_tco;
4735 limit = ARRAY_SIZE(snd_hdspm_controls_tco);
4736 for (idx = 0; idx < limit; idx++) {
4737 err = snd_ctl_add(card,
4738 snd_ctl_new1(&list[idx], hdspm));
4739 if (err < 0)
4740 return err;
4741 }
4742 }
4743
Takashi Iwai763f3562005-06-03 11:25:34 +02004744 return 0;
4745}
4746
4747/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01004748 /proc interface
Takashi Iwai763f3562005-06-03 11:25:34 +02004749 ------------------------------------------------------------*/
4750
4751static void
Adrian Knoth57601072013-07-05 11:28:04 +02004752snd_hdspm_proc_read_tco(struct snd_info_entry *entry,
4753 struct snd_info_buffer *buffer)
Takashi Iwai763f3562005-06-03 11:25:34 +02004754{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004755 struct hdspm *hdspm = entry->private_data;
Adrian Knoth57601072013-07-05 11:28:04 +02004756 unsigned int status, control;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004757 int a, ltc, frames, seconds, minutes, hours;
4758 unsigned int period;
4759 u64 freq_const = 0;
4760 u32 rate;
4761
Adrian Knoth57601072013-07-05 11:28:04 +02004762 snd_iprintf(buffer, "--- TCO ---\n");
4763
Takashi Iwai763f3562005-06-03 11:25:34 +02004764 status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004765 control = hdspm->control_register;
Takashi Iwai763f3562005-06-03 11:25:34 +02004766
Adrian Knoth0dca1792011-01-26 19:32:14 +01004767
Adrian Knoth0dca1792011-01-26 19:32:14 +01004768 if (status & HDSPM_tco_detect) {
4769 snd_iprintf(buffer, "TCO module detected.\n");
4770 a = hdspm_read(hdspm, HDSPM_RD_TCO+4);
4771 if (a & HDSPM_TCO1_LTC_Input_valid) {
4772 snd_iprintf(buffer, " LTC valid, ");
4773 switch (a & (HDSPM_TCO1_LTC_Format_LSB |
4774 HDSPM_TCO1_LTC_Format_MSB)) {
4775 case 0:
4776 snd_iprintf(buffer, "24 fps, ");
4777 break;
4778 case HDSPM_TCO1_LTC_Format_LSB:
4779 snd_iprintf(buffer, "25 fps, ");
4780 break;
4781 case HDSPM_TCO1_LTC_Format_MSB:
4782 snd_iprintf(buffer, "29.97 fps, ");
4783 break;
4784 default:
4785 snd_iprintf(buffer, "30 fps, ");
4786 break;
4787 }
4788 if (a & HDSPM_TCO1_set_drop_frame_flag) {
4789 snd_iprintf(buffer, "drop frame\n");
4790 } else {
4791 snd_iprintf(buffer, "full frame\n");
4792 }
4793 } else {
4794 snd_iprintf(buffer, " no LTC\n");
4795 }
4796 if (a & HDSPM_TCO1_Video_Input_Format_NTSC) {
4797 snd_iprintf(buffer, " Video: NTSC\n");
4798 } else if (a & HDSPM_TCO1_Video_Input_Format_PAL) {
4799 snd_iprintf(buffer, " Video: PAL\n");
4800 } else {
4801 snd_iprintf(buffer, " No video\n");
4802 }
4803 if (a & HDSPM_TCO1_TCO_lock) {
4804 snd_iprintf(buffer, " Sync: lock\n");
4805 } else {
4806 snd_iprintf(buffer, " Sync: no lock\n");
4807 }
4808
4809 switch (hdspm->io_type) {
4810 case MADI:
4811 case AES32:
4812 freq_const = 110069313433624ULL;
4813 break;
4814 case RayDAT:
4815 case AIO:
4816 freq_const = 104857600000000ULL;
4817 break;
4818 case MADIface:
4819 break; /* no TCO possible */
4820 }
4821
4822 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
4823 snd_iprintf(buffer, " period: %u\n", period);
4824
4825
4826 /* rate = freq_const/period; */
4827 rate = div_u64(freq_const, period);
4828
4829 if (control & HDSPM_QuadSpeed) {
4830 rate *= 4;
4831 } else if (control & HDSPM_DoubleSpeed) {
4832 rate *= 2;
4833 }
4834
4835 snd_iprintf(buffer, " Frequency: %u Hz\n",
4836 (unsigned int) rate);
4837
4838 ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
4839 frames = ltc & 0xF;
4840 ltc >>= 4;
4841 frames += (ltc & 0x3) * 10;
4842 ltc >>= 4;
4843 seconds = ltc & 0xF;
4844 ltc >>= 4;
4845 seconds += (ltc & 0x7) * 10;
4846 ltc >>= 4;
4847 minutes = ltc & 0xF;
4848 ltc >>= 4;
4849 minutes += (ltc & 0x7) * 10;
4850 ltc >>= 4;
4851 hours = ltc & 0xF;
4852 ltc >>= 4;
4853 hours += (ltc & 0x3) * 10;
4854 snd_iprintf(buffer,
4855 " LTC In: %02d:%02d:%02d:%02d\n",
4856 hours, minutes, seconds, frames);
4857
4858 } else {
4859 snd_iprintf(buffer, "No TCO module detected.\n");
4860 }
Adrian Knoth57601072013-07-05 11:28:04 +02004861}
4862
4863static void
4864snd_hdspm_proc_read_madi(struct snd_info_entry *entry,
4865 struct snd_info_buffer *buffer)
4866{
4867 struct hdspm *hdspm = entry->private_data;
Sudip Mukherjeedf57de12014-10-29 20:09:45 +05304868 unsigned int status, status2;
Adrian Knoth57601072013-07-05 11:28:04 +02004869
4870 char *pref_sync_ref;
4871 char *autosync_ref;
4872 char *system_clock_mode;
Adrian Knoth57601072013-07-05 11:28:04 +02004873 int x, x2;
4874
4875 status = hdspm_read(hdspm, HDSPM_statusRegister);
4876 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth57601072013-07-05 11:28:04 +02004877
4878 snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
4879 hdspm->card_name, hdspm->card->number + 1,
4880 hdspm->firmware_rev,
4881 (status2 & HDSPM_version0) |
4882 (status2 & HDSPM_version1) | (status2 &
4883 HDSPM_version2));
4884
4885 snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n",
4886 (hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF,
4887 hdspm->serial);
4888
4889 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
4890 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
4891
4892 snd_iprintf(buffer, "--- System ---\n");
4893
4894 snd_iprintf(buffer,
4895 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4896 status & HDSPM_audioIRQPending,
4897 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4898 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4899 hdspm->irq_count);
4900 snd_iprintf(buffer,
4901 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4902 "estimated= %ld (bytes)\n",
4903 ((status & HDSPM_BufferID) ? 1 : 0),
4904 (status & HDSPM_BufferPositionMask),
4905 (status & HDSPM_BufferPositionMask) %
4906 (2 * (int)hdspm->period_bytes),
4907 ((status & HDSPM_BufferPositionMask) - 64) %
4908 (2 * (int)hdspm->period_bytes),
4909 (long) hdspm_hw_pointer(hdspm) * 4);
4910
4911 snd_iprintf(buffer,
4912 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4913 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4914 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4915 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4916 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
4917 snd_iprintf(buffer,
4918 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4919 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4920 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4921 snd_iprintf(buffer,
4922 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4923 "status2=0x%x\n",
4924 hdspm->control_register, hdspm->control2_register,
4925 status, status2);
4926
Takashi Iwai763f3562005-06-03 11:25:34 +02004927
4928 snd_iprintf(buffer, "--- Settings ---\n");
4929
Adrian Knoth7cb155f2011-08-15 00:22:53 +02004930 x = hdspm_get_latency(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02004931
4932 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004933 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4934 x, (unsigned long) hdspm->period_bytes);
Takashi Iwai763f3562005-06-03 11:25:34 +02004935
Adrian Knoth0dca1792011-01-26 19:32:14 +01004936 snd_iprintf(buffer, "Line out: %s\n",
4937 (hdspm->control_register & HDSPM_LineOut) ? "on " : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004938
Takashi Iwai763f3562005-06-03 11:25:34 +02004939 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004940 "ClearTrackMarker = %s, Transmit in %s Channel Mode, "
4941 "Auto Input %s\n",
4942 (hdspm->control_register & HDSPM_clr_tms) ? "on" : "off",
4943 (hdspm->control_register & HDSPM_TX_64ch) ? "64" : "56",
4944 (hdspm->control_register & HDSPM_AutoInp) ? "on" : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004945
Adrian Knoth0dca1792011-01-26 19:32:14 +01004946
Remy Bruno3cee5a62006-10-16 12:46:32 +02004947 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
Adrian Knoth0dca1792011-01-26 19:32:14 +01004948 system_clock_mode = "AutoSync";
Remy Bruno3cee5a62006-10-16 12:46:32 +02004949 else
Takashi Iwai763f3562005-06-03 11:25:34 +02004950 system_clock_mode = "Master";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004951 snd_iprintf(buffer, "AutoSync Reference: %s\n", system_clock_mode);
Takashi Iwai763f3562005-06-03 11:25:34 +02004952
4953 switch (hdspm_pref_sync_ref(hdspm)) {
4954 case HDSPM_SYNC_FROM_WORD:
4955 pref_sync_ref = "Word Clock";
4956 break;
4957 case HDSPM_SYNC_FROM_MADI:
4958 pref_sync_ref = "MADI Sync";
4959 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004960 case HDSPM_SYNC_FROM_TCO:
4961 pref_sync_ref = "TCO";
4962 break;
4963 case HDSPM_SYNC_FROM_SYNC_IN:
4964 pref_sync_ref = "Sync In";
4965 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004966 default:
4967 pref_sync_ref = "XXXX Clock";
4968 break;
4969 }
4970 snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004971 pref_sync_ref);
Takashi Iwai763f3562005-06-03 11:25:34 +02004972
4973 snd_iprintf(buffer, "System Clock Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004974 hdspm->system_sample_rate);
Takashi Iwai763f3562005-06-03 11:25:34 +02004975
4976
4977 snd_iprintf(buffer, "--- Status:\n");
4978
4979 x = status & HDSPM_madiSync;
4980 x2 = status2 & HDSPM_wcSync;
4981
4982 snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004983 (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
4984 "NoLock",
4985 (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
4986 "NoLock");
Takashi Iwai763f3562005-06-03 11:25:34 +02004987
4988 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004989 case HDSPM_AUTOSYNC_FROM_SYNC_IN:
4990 autosync_ref = "Sync In";
4991 break;
4992 case HDSPM_AUTOSYNC_FROM_TCO:
4993 autosync_ref = "TCO";
4994 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004995 case HDSPM_AUTOSYNC_FROM_WORD:
4996 autosync_ref = "Word Clock";
4997 break;
4998 case HDSPM_AUTOSYNC_FROM_MADI:
4999 autosync_ref = "MADI Sync";
5000 break;
5001 case HDSPM_AUTOSYNC_FROM_NONE:
5002 autosync_ref = "Input not valid";
5003 break;
5004 default:
5005 autosync_ref = "---";
5006 break;
5007 }
5008 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005009 "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
5010 autosync_ref, hdspm_external_sample_rate(hdspm),
5011 (status & HDSPM_madiFreqMask) >> 22,
5012 (status2 & HDSPM_wcFreqMask) >> 5);
Takashi Iwai763f3562005-06-03 11:25:34 +02005013
5014 snd_iprintf(buffer, "Input: %s, Mode=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01005015 (status & HDSPM_AB_int) ? "Coax" : "Optical",
5016 (status & HDSPM_RX_64ch) ? "64 channels" :
5017 "56 channels");
Takashi Iwai763f3562005-06-03 11:25:34 +02005018
Adrian Knoth57601072013-07-05 11:28:04 +02005019 /* call readout function for TCO specific status */
5020 snd_hdspm_proc_read_tco(entry, buffer);
5021
Takashi Iwai763f3562005-06-03 11:25:34 +02005022 snd_iprintf(buffer, "\n");
5023}
5024
Remy Bruno3cee5a62006-10-16 12:46:32 +02005025static void
5026snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
5027 struct snd_info_buffer *buffer)
5028{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005029 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005030 unsigned int status;
5031 unsigned int status2;
5032 unsigned int timecode;
Andre Schramm56bde0f2013-01-09 14:40:18 +01005033 unsigned int wcLock, wcSync;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005034 int pref_syncref;
5035 char *autosync_ref;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005036 int x;
5037
5038 status = hdspm_read(hdspm, HDSPM_statusRegister);
5039 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
5040 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
5041
5042 snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
5043 hdspm->card_name, hdspm->card->number + 1,
5044 hdspm->firmware_rev);
5045
5046 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
5047 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
5048
5049 snd_iprintf(buffer, "--- System ---\n");
5050
5051 snd_iprintf(buffer,
5052 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
5053 status & HDSPM_audioIRQPending,
5054 (status & HDSPM_midi0IRQPending) ? 1 : 0,
5055 (status & HDSPM_midi1IRQPending) ? 1 : 0,
5056 hdspm->irq_count);
5057 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005058 "HW pointer: id = %d, rawptr = %d (%d->%d) "
5059 "estimated= %ld (bytes)\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005060 ((status & HDSPM_BufferID) ? 1 : 0),
5061 (status & HDSPM_BufferPositionMask),
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005062 (status & HDSPM_BufferPositionMask) %
5063 (2 * (int)hdspm->period_bytes),
5064 ((status & HDSPM_BufferPositionMask) - 64) %
5065 (2 * (int)hdspm->period_bytes),
Remy Bruno3cee5a62006-10-16 12:46:32 +02005066 (long) hdspm_hw_pointer(hdspm) * 4);
5067
5068 snd_iprintf(buffer,
5069 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
5070 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
5071 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
5072 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
5073 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
5074 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005075 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
5076 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
5077 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
5078 snd_iprintf(buffer,
5079 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
5080 "status2=0x%x\n",
5081 hdspm->control_register, hdspm->control2_register,
5082 status, status2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02005083
5084 snd_iprintf(buffer, "--- Settings ---\n");
5085
Adrian Knoth7cb155f2011-08-15 00:22:53 +02005086 x = hdspm_get_latency(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02005087
5088 snd_iprintf(buffer,
5089 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
5090 x, (unsigned long) hdspm->period_bytes);
5091
Adrian Knoth0dca1792011-01-26 19:32:14 +01005092 snd_iprintf(buffer, "Line out: %s\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005093 (hdspm->
Adrian Knoth0dca1792011-01-26 19:32:14 +01005094 control_register & HDSPM_LineOut) ? "on " : "off");
Remy Bruno3cee5a62006-10-16 12:46:32 +02005095
5096 snd_iprintf(buffer,
5097 "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
5098 (hdspm->
5099 control_register & HDSPM_clr_tms) ? "on" : "off",
5100 (hdspm->
5101 control_register & HDSPM_Emphasis) ? "on" : "off",
5102 (hdspm->
5103 control_register & HDSPM_Dolby) ? "on" : "off");
5104
Remy Bruno3cee5a62006-10-16 12:46:32 +02005105
5106 pref_syncref = hdspm_pref_sync_ref(hdspm);
5107 if (pref_syncref == 0)
5108 snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
5109 else
5110 snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
5111 pref_syncref);
5112
5113 snd_iprintf(buffer, "System Clock Frequency: %d\n",
5114 hdspm->system_sample_rate);
5115
5116 snd_iprintf(buffer, "Double speed: %s\n",
5117 hdspm->control_register & HDSPM_DS_DoubleWire?
5118 "Double wire" : "Single wire");
5119 snd_iprintf(buffer, "Quad speed: %s\n",
5120 hdspm->control_register & HDSPM_QS_DoubleWire?
5121 "Double wire" :
5122 hdspm->control_register & HDSPM_QS_QuadWire?
5123 "Quad wire" : "Single wire");
5124
5125 snd_iprintf(buffer, "--- Status:\n");
5126
Andre Schramm56bde0f2013-01-09 14:40:18 +01005127 wcLock = status & HDSPM_AES32_wcLock;
5128 wcSync = wcLock && (status & HDSPM_AES32_wcSync);
5129
Remy Bruno3cee5a62006-10-16 12:46:32 +02005130 snd_iprintf(buffer, "Word: %s Frequency: %d\n",
Andre Schramm56bde0f2013-01-09 14:40:18 +01005131 (wcLock) ? (wcSync ? "Sync " : "Lock ") : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005132 HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02005133
5134 for (x = 0; x < 8; x++) {
5135 snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005136 x+1,
5137 (status2 & (HDSPM_LockAES >> x)) ?
Adrian Knoth0dca1792011-01-26 19:32:14 +01005138 "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005139 HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02005140 }
5141
5142 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005143 case HDSPM_AES32_AUTOSYNC_FROM_NONE:
5144 autosync_ref = "None"; break;
5145 case HDSPM_AES32_AUTOSYNC_FROM_WORD:
5146 autosync_ref = "Word Clock"; break;
5147 case HDSPM_AES32_AUTOSYNC_FROM_AES1:
5148 autosync_ref = "AES1"; break;
5149 case HDSPM_AES32_AUTOSYNC_FROM_AES2:
5150 autosync_ref = "AES2"; break;
5151 case HDSPM_AES32_AUTOSYNC_FROM_AES3:
5152 autosync_ref = "AES3"; break;
5153 case HDSPM_AES32_AUTOSYNC_FROM_AES4:
5154 autosync_ref = "AES4"; break;
5155 case HDSPM_AES32_AUTOSYNC_FROM_AES5:
5156 autosync_ref = "AES5"; break;
5157 case HDSPM_AES32_AUTOSYNC_FROM_AES6:
5158 autosync_ref = "AES6"; break;
5159 case HDSPM_AES32_AUTOSYNC_FROM_AES7:
5160 autosync_ref = "AES7"; break;
5161 case HDSPM_AES32_AUTOSYNC_FROM_AES8:
5162 autosync_ref = "AES8"; break;
Adrian Knoth194062d2013-07-05 11:28:16 +02005163 case HDSPM_AES32_AUTOSYNC_FROM_TCO:
5164 autosync_ref = "TCO"; break;
5165 case HDSPM_AES32_AUTOSYNC_FROM_SYNC_IN:
5166 autosync_ref = "Sync In"; break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005167 default:
5168 autosync_ref = "---"; break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005169 }
5170 snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
5171
Adrian Knoth194062d2013-07-05 11:28:16 +02005172 /* call readout function for TCO specific status */
5173 snd_hdspm_proc_read_tco(entry, buffer);
5174
Remy Bruno3cee5a62006-10-16 12:46:32 +02005175 snd_iprintf(buffer, "\n");
5176}
5177
Adrian Knoth0dca1792011-01-26 19:32:14 +01005178static void
5179snd_hdspm_proc_read_raydat(struct snd_info_entry *entry,
5180 struct snd_info_buffer *buffer)
5181{
5182 struct hdspm *hdspm = entry->private_data;
Sudip Mukherjeedf57de12014-10-29 20:09:45 +05305183 unsigned int status1, status2, status3, i;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005184 unsigned int lock, sync;
5185
5186 status1 = hdspm_read(hdspm, HDSPM_RD_STATUS_1); /* s1 */
5187 status2 = hdspm_read(hdspm, HDSPM_RD_STATUS_2); /* freq */
5188 status3 = hdspm_read(hdspm, HDSPM_RD_STATUS_3); /* s2 */
5189
Adrian Knoth0dca1792011-01-26 19:32:14 +01005190 snd_iprintf(buffer, "STATUS1: 0x%08x\n", status1);
5191 snd_iprintf(buffer, "STATUS2: 0x%08x\n", status2);
5192 snd_iprintf(buffer, "STATUS3: 0x%08x\n", status3);
5193
5194
5195 snd_iprintf(buffer, "\n*** CLOCK MODE\n\n");
5196
5197 snd_iprintf(buffer, "Clock mode : %s\n",
5198 (hdspm_system_clock_mode(hdspm) == 0) ? "master" : "slave");
5199 snd_iprintf(buffer, "System frequency: %d Hz\n",
5200 hdspm_get_system_sample_rate(hdspm));
5201
5202 snd_iprintf(buffer, "\n*** INPUT STATUS\n\n");
5203
5204 lock = 0x1;
5205 sync = 0x100;
5206
5207 for (i = 0; i < 8; i++) {
5208 snd_iprintf(buffer, "s1_input %d: Lock %d, Sync %d, Freq %s\n",
5209 i,
5210 (status1 & lock) ? 1 : 0,
5211 (status1 & sync) ? 1 : 0,
5212 texts_freq[(status2 >> (i * 4)) & 0xF]);
5213
5214 lock = lock<<1;
5215 sync = sync<<1;
5216 }
5217
5218 snd_iprintf(buffer, "WC input: Lock %d, Sync %d, Freq %s\n",
5219 (status1 & 0x1000000) ? 1 : 0,
5220 (status1 & 0x2000000) ? 1 : 0,
5221 texts_freq[(status1 >> 16) & 0xF]);
5222
5223 snd_iprintf(buffer, "TCO input: Lock %d, Sync %d, Freq %s\n",
5224 (status1 & 0x4000000) ? 1 : 0,
5225 (status1 & 0x8000000) ? 1 : 0,
5226 texts_freq[(status1 >> 20) & 0xF]);
5227
5228 snd_iprintf(buffer, "SYNC IN: Lock %d, Sync %d, Freq %s\n",
5229 (status3 & 0x400) ? 1 : 0,
5230 (status3 & 0x800) ? 1 : 0,
5231 texts_freq[(status2 >> 12) & 0xF]);
5232
5233}
5234
Remy Bruno3cee5a62006-10-16 12:46:32 +02005235#ifdef CONFIG_SND_DEBUG
5236static void
Adrian Knoth0dca1792011-01-26 19:32:14 +01005237snd_hdspm_proc_read_debug(struct snd_info_entry *entry,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005238 struct snd_info_buffer *buffer)
5239{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005240 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005241
5242 int j,i;
5243
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005244 for (i = 0; i < 256 /* 1024*64 */; i += j) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02005245 snd_iprintf(buffer, "0x%08X: ", i);
5246 for (j = 0; j < 16; j += 4)
5247 snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
5248 snd_iprintf(buffer, "\n");
5249 }
5250}
5251#endif
5252
5253
Adrian Knoth0dca1792011-01-26 19:32:14 +01005254static void snd_hdspm_proc_ports_in(struct snd_info_entry *entry,
5255 struct snd_info_buffer *buffer)
5256{
5257 struct hdspm *hdspm = entry->private_data;
5258 int i;
Remy Bruno3cee5a62006-10-16 12:46:32 +02005259
Adrian Knoth0dca1792011-01-26 19:32:14 +01005260 snd_iprintf(buffer, "# generated by hdspm\n");
5261
5262 for (i = 0; i < hdspm->max_channels_in; i++) {
5263 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_in[i]);
5264 }
5265}
5266
5267static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry,
5268 struct snd_info_buffer *buffer)
5269{
5270 struct hdspm *hdspm = entry->private_data;
5271 int i;
5272
5273 snd_iprintf(buffer, "# generated by hdspm\n");
5274
5275 for (i = 0; i < hdspm->max_channels_out; i++) {
5276 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_out[i]);
5277 }
5278}
5279
5280
Bill Pembertone23e7a12012-12-06 12:35:10 -05005281static void snd_hdspm_proc_init(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005282{
Takashi Iwai47f27692019-02-04 16:01:39 +01005283 void (*read)(struct snd_info_entry *, struct snd_info_buffer *) = NULL;
Takashi Iwai763f3562005-06-03 11:25:34 +02005284
Takashi Iwai47f27692019-02-04 16:01:39 +01005285 switch (hdspm->io_type) {
5286 case AES32:
5287 read = snd_hdspm_proc_read_aes32;
5288 break;
5289 case MADI:
5290 read = snd_hdspm_proc_read_madi;
5291 break;
5292 case MADIface:
5293 /* read = snd_hdspm_proc_read_madiface; */
5294 break;
5295 case RayDAT:
5296 read = snd_hdspm_proc_read_raydat;
5297 break;
5298 case AIO:
5299 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005300 }
5301
Takashi Iwai47f27692019-02-04 16:01:39 +01005302 snd_card_ro_proc_new(hdspm->card, "hdspm", hdspm, read);
5303 snd_card_ro_proc_new(hdspm->card, "ports.in", hdspm,
5304 snd_hdspm_proc_ports_in);
5305 snd_card_ro_proc_new(hdspm->card, "ports.out", hdspm,
5306 snd_hdspm_proc_ports_out);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005307
Remy Bruno3cee5a62006-10-16 12:46:32 +02005308#ifdef CONFIG_SND_DEBUG
5309 /* debug file to read all hdspm registers */
Takashi Iwai47f27692019-02-04 16:01:39 +01005310 snd_card_ro_proc_new(hdspm->card, "debug", hdspm,
5311 snd_hdspm_proc_read_debug);
Remy Bruno3cee5a62006-10-16 12:46:32 +02005312#endif
Takashi Iwai763f3562005-06-03 11:25:34 +02005313}
5314
5315/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005316 hdspm intitialize
Takashi Iwai763f3562005-06-03 11:25:34 +02005317 ------------------------------------------------------------*/
5318
Takashi Iwai98274f02005-11-17 14:52:34 +01005319static int snd_hdspm_set_defaults(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005320{
Takashi Iwai763f3562005-06-03 11:25:34 +02005321 /* ASSUMPTION: hdspm->lock is either held, or there is no need to
Joe Perches561de312007-12-18 13:13:47 +01005322 hold it (e.g. during module initialization).
Adrian Knoth0dca1792011-01-26 19:32:14 +01005323 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005324
5325 /* set defaults: */
5326
Adrian Knoth0dca1792011-01-26 19:32:14 +01005327 hdspm->settings_register = 0;
5328
5329 switch (hdspm->io_type) {
5330 case MADI:
5331 case MADIface:
5332 hdspm->control_register =
5333 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5334 break;
5335
5336 case RayDAT:
5337 case AIO:
5338 hdspm->settings_register = 0x1 + 0x1000;
5339 /* Magic values are: LAT_0, LAT_2, Master, freq1, tx64ch, inp_0,
5340 * line_out */
5341 hdspm->control_register =
5342 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5343 break;
5344
5345 case AES32:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005346 hdspm->control_register =
Adrian Knothe71b95a2013-07-05 11:28:06 +02005347 HDSPM_ClockModeMaster | /* Master Clock Mode on */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005348 hdspm_encode_latency(7) | /* latency max=8192samples */
Remy Bruno3cee5a62006-10-16 12:46:32 +02005349 HDSPM_SyncRef0 | /* AES1 is syncclock */
5350 HDSPM_LineOut | /* Analog output in */
5351 HDSPM_Professional; /* Professional mode */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005352 break;
5353 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005354
5355 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5356
Adrian Knoth0dca1792011-01-26 19:32:14 +01005357 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005358 /* No control2 register for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005359#ifdef SNDRV_BIG_ENDIAN
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005360 hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
Takashi Iwai763f3562005-06-03 11:25:34 +02005361#else
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005362 hdspm->control2_register = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005363#endif
5364
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005365 hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
5366 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005367 hdspm_compute_period_size(hdspm);
5368
5369 /* silence everything */
5370
5371 all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
5372
Adrian Knothb2ed6322013-07-05 11:27:54 +02005373 if (hdspm_is_raydat_or_aio(hdspm))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005374 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
Takashi Iwai763f3562005-06-03 11:25:34 +02005375
5376 /* set a default rate so that the channel map is set up. */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005377 hdspm_set_rate(hdspm, 48000, 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02005378
5379 return 0;
5380}
5381
5382
5383/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005384 interrupt
Takashi Iwai763f3562005-06-03 11:25:34 +02005385 ------------------------------------------------------------*/
5386
David Howells7d12e782006-10-05 14:55:46 +01005387static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02005388{
Takashi Iwai98274f02005-11-17 14:52:34 +01005389 struct hdspm *hdspm = (struct hdspm *) dev_id;
Takashi Iwai763f3562005-06-03 11:25:34 +02005390 unsigned int status;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005391 int i, audio, midi, schedule = 0;
5392 /* cycles_t now; */
Takashi Iwai763f3562005-06-03 11:25:34 +02005393
5394 status = hdspm_read(hdspm, HDSPM_statusRegister);
5395
5396 audio = status & HDSPM_audioIRQPending;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005397 midi = status & (HDSPM_midi0IRQPending | HDSPM_midi1IRQPending |
5398 HDSPM_midi2IRQPending | HDSPM_midi3IRQPending);
Takashi Iwai763f3562005-06-03 11:25:34 +02005399
Adrian Knoth0dca1792011-01-26 19:32:14 +01005400 /* now = get_cycles(); */
Takashi Iwaiddcecf62014-11-10 17:24:26 +01005401 /*
Adrian Knoth0dca1792011-01-26 19:32:14 +01005402 * LAT_2..LAT_0 period counter (win) counter (mac)
5403 * 6 4096 ~256053425 ~514672358
5404 * 5 2048 ~128024983 ~257373821
5405 * 4 1024 ~64023706 ~128718089
5406 * 3 512 ~32005945 ~64385999
5407 * 2 256 ~16003039 ~32260176
5408 * 1 128 ~7998738 ~16194507
5409 * 0 64 ~3998231 ~8191558
Takashi Iwaiddcecf62014-11-10 17:24:26 +01005410 */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005411 /*
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005412 dev_info(hdspm->card->dev, "snd_hdspm_interrupt %llu @ %llx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01005413 now-hdspm->last_interrupt, status & 0xFFC0);
5414 hdspm->last_interrupt = now;
5415 */
5416
5417 if (!audio && !midi)
Takashi Iwai763f3562005-06-03 11:25:34 +02005418 return IRQ_NONE;
5419
5420 hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
5421 hdspm->irq_count++;
5422
Takashi Iwai763f3562005-06-03 11:25:34 +02005423
5424 if (audio) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005425 if (hdspm->capture_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005426 snd_pcm_period_elapsed(hdspm->capture_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005427
5428 if (hdspm->playback_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005429 snd_pcm_period_elapsed(hdspm->playback_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005430 }
5431
Adrian Knoth0dca1792011-01-26 19:32:14 +01005432 if (midi) {
5433 i = 0;
5434 while (i < hdspm->midiPorts) {
5435 if ((hdspm_read(hdspm,
5436 hdspm->midi[i].statusIn) & 0xff) &&
5437 (status & hdspm->midi[i].irq)) {
5438 /* we disable interrupts for this input until
5439 * processing is done
5440 */
5441 hdspm->control_register &= ~hdspm->midi[i].ie;
5442 hdspm_write(hdspm, HDSPM_controlRegister,
5443 hdspm->control_register);
5444 hdspm->midi[i].pending = 1;
5445 schedule = 1;
5446 }
5447
5448 i++;
5449 }
5450
5451 if (schedule)
Takashi Iwaia2e527c2020-09-03 12:41:27 +02005452 queue_work(system_highpri_wq, &hdspm->midi_work);
Takashi Iwai763f3562005-06-03 11:25:34 +02005453 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005454
Takashi Iwai763f3562005-06-03 11:25:34 +02005455 return IRQ_HANDLED;
5456}
5457
5458/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005459 pcm interface
Takashi Iwai763f3562005-06-03 11:25:34 +02005460 ------------------------------------------------------------*/
5461
5462
Adrian Knoth0dca1792011-01-26 19:32:14 +01005463static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream
5464 *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005465{
Takashi Iwai98274f02005-11-17 14:52:34 +01005466 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005467 return hdspm_hw_pointer(hdspm);
5468}
5469
Takashi Iwai763f3562005-06-03 11:25:34 +02005470
Takashi Iwai98274f02005-11-17 14:52:34 +01005471static int snd_hdspm_reset(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005472{
Takashi Iwai98274f02005-11-17 14:52:34 +01005473 struct snd_pcm_runtime *runtime = substream->runtime;
5474 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5475 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005476
5477 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5478 other = hdspm->capture_substream;
5479 else
5480 other = hdspm->playback_substream;
5481
5482 if (hdspm->running)
5483 runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
5484 else
5485 runtime->status->hw_ptr = 0;
5486 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005487 struct snd_pcm_substream *s;
5488 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01005489 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005490 if (s == other) {
5491 oruntime->status->hw_ptr =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005492 runtime->status->hw_ptr;
Takashi Iwai763f3562005-06-03 11:25:34 +02005493 break;
5494 }
5495 }
5496 }
5497 return 0;
5498}
5499
Takashi Iwai98274f02005-11-17 14:52:34 +01005500static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
5501 struct snd_pcm_hw_params *params)
Takashi Iwai763f3562005-06-03 11:25:34 +02005502{
Takashi Iwai98274f02005-11-17 14:52:34 +01005503 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005504 int err;
5505 int i;
5506 pid_t this_pid;
5507 pid_t other_pid;
Takashi Iwai763f3562005-06-03 11:25:34 +02005508
5509 spin_lock_irq(&hdspm->lock);
5510
5511 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5512 this_pid = hdspm->playback_pid;
5513 other_pid = hdspm->capture_pid;
5514 } else {
5515 this_pid = hdspm->capture_pid;
5516 other_pid = hdspm->playback_pid;
5517 }
5518
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005519 if (other_pid > 0 && this_pid != other_pid) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005520
5521 /* The other stream is open, and not by the same
5522 task as this one. Make sure that the parameters
5523 that matter are the same.
Adrian Knoth0dca1792011-01-26 19:32:14 +01005524 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005525
5526 if (params_rate(params) != hdspm->system_sample_rate) {
5527 spin_unlock_irq(&hdspm->lock);
5528 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005529 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005530 return -EBUSY;
5531 }
5532
5533 if (params_period_size(params) != hdspm->period_bytes / 4) {
5534 spin_unlock_irq(&hdspm->lock);
5535 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005536 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005537 return -EBUSY;
5538 }
5539
5540 }
5541 /* We're fine. */
5542 spin_unlock_irq(&hdspm->lock);
5543
5544 /* how to make sure that the rate matches an externally-set one ? */
5545
5546 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005547 err = hdspm_set_rate(hdspm, params_rate(params), 0);
5548 if (err < 0) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005549 dev_info(hdspm->card->dev, "err on hdspm_set_rate: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005550 spin_unlock_irq(&hdspm->lock);
5551 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005552 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005553 return err;
5554 }
5555 spin_unlock_irq(&hdspm->lock);
5556
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005557 err = hdspm_set_interrupt_interval(hdspm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005558 params_period_size(params));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005559 if (err < 0) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005560 dev_info(hdspm->card->dev,
5561 "err on hdspm_set_interrupt_interval: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005562 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005563 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005564 return err;
5565 }
5566
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005567 /* Memory allocation, takashi's method, dont know if we should
5568 * spinlock
5569 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005570 /* malloc all buffer even if not enabled to get sure */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005571 /* Update for MADI rev 204: we need to allocate for all channels,
5572 * otherwise it doesn't work at 96kHz */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005573
Takashi Iwai763f3562005-06-03 11:25:34 +02005574 err =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005575 snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
5576 if (err < 0) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005577 dev_info(hdspm->card->dev,
5578 "err on snd_pcm_lib_malloc_pages: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005579 return err;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005580 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005581
Takashi Iwai763f3562005-06-03 11:25:34 +02005582 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5583
Philippe Bekaerte4e07c62019-05-23 23:56:49 +02005584 for (i = 0; i < params_channels(params); ++i) {
5585 int c = hdspm->channel_map_out[i];
Takashi Iwai763f3562005-06-03 11:25:34 +02005586
Philippe Bekaerte4e07c62019-05-23 23:56:49 +02005587 if (c < 0)
5588 continue; /* just make sure */
5589 hdspm_set_channel_dma_addr(hdspm, substream,
5590 HDSPM_pageAddressBufferOut,
5591 c);
5592 snd_hdspm_enable_out(hdspm, c, 1);
5593 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005594
5595 hdspm->playback_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005596 (unsigned char *) substream->runtime->dma_area;
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005597 dev_dbg(hdspm->card->dev,
5598 "Allocated sample buffer for playback at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005599 hdspm->playback_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005600 } else {
Philippe Bekaerte4e07c62019-05-23 23:56:49 +02005601 for (i = 0; i < params_channels(params); ++i) {
5602 int c = hdspm->channel_map_in[i];
Takashi Iwai763f3562005-06-03 11:25:34 +02005603
Philippe Bekaerte4e07c62019-05-23 23:56:49 +02005604 if (c < 0)
5605 continue;
5606 hdspm_set_channel_dma_addr(hdspm, substream,
5607 HDSPM_pageAddressBufferIn,
5608 c);
5609 snd_hdspm_enable_in(hdspm, c, 1);
5610 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005611
5612 hdspm->capture_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005613 (unsigned char *) substream->runtime->dma_area;
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005614 dev_dbg(hdspm->card->dev,
5615 "Allocated sample buffer for capture at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005616 hdspm->capture_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005617 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005618
Remy Bruno3cee5a62006-10-16 12:46:32 +02005619 /*
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005620 dev_dbg(hdspm->card->dev,
5621 "Allocated sample buffer for %s at 0x%08X\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005622 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5623 "playback" : "capture",
Takashi Iwai77a23f22008-08-21 13:00:13 +02005624 snd_pcm_sgbuf_get_addr(substream, 0));
Adrian Knoth0dca1792011-01-26 19:32:14 +01005625 */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005626 /*
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005627 dev_dbg(hdspm->card->dev,
5628 "set_hwparams: %s %d Hz, %d channels, bs = %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01005629 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5630 "playback" : "capture",
5631 params_rate(params), params_channels(params),
5632 params_buffer_size(params));
5633 */
5634
5635
Adrian Knoth3ac9b0a2013-07-05 11:28:13 +02005636 /* For AES cards, the float format bit is the same as the
5637 * preferred sync reference. Since we don't want to break
5638 * sync settings, we have to skip the remaining part of this
5639 * function.
5640 */
5641 if (hdspm->io_type == AES32) {
5642 return 0;
5643 }
5644
5645
Adrian Knoth0dca1792011-01-26 19:32:14 +01005646 /* Switch to native float format if requested */
5647 if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) {
5648 if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT))
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005649 dev_info(hdspm->card->dev,
5650 "Switching to native 32bit LE float format.\n");
Adrian Knoth0dca1792011-01-26 19:32:14 +01005651
5652 hdspm->control_register |= HDSPe_FLOAT_FORMAT;
5653 } else if (SNDRV_PCM_FORMAT_S32_LE == params_format(params)) {
5654 if (hdspm->control_register & HDSPe_FLOAT_FORMAT)
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005655 dev_info(hdspm->card->dev,
5656 "Switching to native 32bit LE integer format.\n");
Adrian Knoth0dca1792011-01-26 19:32:14 +01005657
5658 hdspm->control_register &= ~HDSPe_FLOAT_FORMAT;
5659 }
5660 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5661
Takashi Iwai763f3562005-06-03 11:25:34 +02005662 return 0;
5663}
5664
Takashi Iwai98274f02005-11-17 14:52:34 +01005665static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005666{
5667 int i;
Takashi Iwai98274f02005-11-17 14:52:34 +01005668 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005669
5670 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
Philippe Bekaerte4e07c62019-05-23 23:56:49 +02005671 /* Just disable all channels. The saving when disabling a */
5672 /* smaller set is not worth the trouble. */
5673 for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005674 snd_hdspm_enable_out(hdspm, i, 0);
5675
5676 hdspm->playback_buffer = NULL;
5677 } else {
Philippe Bekaerte4e07c62019-05-23 23:56:49 +02005678 for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005679 snd_hdspm_enable_in(hdspm, i, 0);
5680
5681 hdspm->capture_buffer = NULL;
Takashi Iwai763f3562005-06-03 11:25:34 +02005682 }
5683
5684 snd_pcm_lib_free_pages(substream);
5685
5686 return 0;
5687}
5688
Adrian Knoth0dca1792011-01-26 19:32:14 +01005689
Takashi Iwai98274f02005-11-17 14:52:34 +01005690static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005691 struct snd_pcm_channel_info *info)
Takashi Iwai763f3562005-06-03 11:25:34 +02005692{
Takashi Iwai98274f02005-11-17 14:52:34 +01005693 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai10513142018-04-24 08:03:14 +02005694 unsigned int channel = info->channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02005695
Adrian Knoth0dca1792011-01-26 19:32:14 +01005696 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
Takashi Iwai10513142018-04-24 08:03:14 +02005697 if (snd_BUG_ON(channel >= hdspm->max_channels_out)) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005698 dev_info(hdspm->card->dev,
5699 "snd_hdspm_channel_info: output channel out of range (%d)\n",
Takashi Iwai10513142018-04-24 08:03:14 +02005700 channel);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005701 return -EINVAL;
5702 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005703
Takashi Iwai10513142018-04-24 08:03:14 +02005704 channel = array_index_nospec(channel, hdspm->max_channels_out);
5705 if (hdspm->channel_map_out[channel] < 0) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005706 dev_info(hdspm->card->dev,
5707 "snd_hdspm_channel_info: output channel %d mapped out\n",
Takashi Iwai10513142018-04-24 08:03:14 +02005708 channel);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005709 return -EINVAL;
5710 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005711
Takashi Iwai10513142018-04-24 08:03:14 +02005712 info->offset = hdspm->channel_map_out[channel] *
Adrian Knoth0dca1792011-01-26 19:32:14 +01005713 HDSPM_CHANNEL_BUFFER_BYTES;
5714 } else {
Takashi Iwai10513142018-04-24 08:03:14 +02005715 if (snd_BUG_ON(channel >= hdspm->max_channels_in)) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005716 dev_info(hdspm->card->dev,
5717 "snd_hdspm_channel_info: input channel out of range (%d)\n",
Takashi Iwai10513142018-04-24 08:03:14 +02005718 channel);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005719 return -EINVAL;
5720 }
5721
Takashi Iwai10513142018-04-24 08:03:14 +02005722 channel = array_index_nospec(channel, hdspm->max_channels_in);
5723 if (hdspm->channel_map_in[channel] < 0) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01005724 dev_info(hdspm->card->dev,
5725 "snd_hdspm_channel_info: input channel %d mapped out\n",
Takashi Iwai10513142018-04-24 08:03:14 +02005726 channel);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005727 return -EINVAL;
5728 }
5729
Takashi Iwai10513142018-04-24 08:03:14 +02005730 info->offset = hdspm->channel_map_in[channel] *
Adrian Knoth0dca1792011-01-26 19:32:14 +01005731 HDSPM_CHANNEL_BUFFER_BYTES;
5732 }
5733
Takashi Iwai763f3562005-06-03 11:25:34 +02005734 info->first = 0;
5735 info->step = 32;
5736 return 0;
5737}
5738
Adrian Knoth0dca1792011-01-26 19:32:14 +01005739
Takashi Iwai98274f02005-11-17 14:52:34 +01005740static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005741 unsigned int cmd, void *arg)
Takashi Iwai763f3562005-06-03 11:25:34 +02005742{
5743 switch (cmd) {
5744 case SNDRV_PCM_IOCTL1_RESET:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005745 return snd_hdspm_reset(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005746
5747 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Adrian Knoth0dca1792011-01-26 19:32:14 +01005748 {
5749 struct snd_pcm_channel_info *info = arg;
5750 return snd_hdspm_channel_info(substream, info);
5751 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005752 default:
5753 break;
5754 }
5755
5756 return snd_pcm_lib_ioctl(substream, cmd, arg);
5757}
5758
Takashi Iwai98274f02005-11-17 14:52:34 +01005759static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
Takashi Iwai763f3562005-06-03 11:25:34 +02005760{
Takashi Iwai98274f02005-11-17 14:52:34 +01005761 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5762 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005763 int running;
5764
5765 spin_lock(&hdspm->lock);
5766 running = hdspm->running;
5767 switch (cmd) {
5768 case SNDRV_PCM_TRIGGER_START:
5769 running |= 1 << substream->stream;
5770 break;
5771 case SNDRV_PCM_TRIGGER_STOP:
5772 running &= ~(1 << substream->stream);
5773 break;
5774 default:
5775 snd_BUG();
5776 spin_unlock(&hdspm->lock);
5777 return -EINVAL;
5778 }
5779 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5780 other = hdspm->capture_substream;
5781 else
5782 other = hdspm->playback_substream;
5783
5784 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005785 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01005786 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005787 if (s == other) {
5788 snd_pcm_trigger_done(s, substream);
5789 if (cmd == SNDRV_PCM_TRIGGER_START)
5790 running |= 1 << s->stream;
5791 else
5792 running &= ~(1 << s->stream);
5793 goto _ok;
5794 }
5795 }
5796 if (cmd == SNDRV_PCM_TRIGGER_START) {
5797 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005798 && substream->stream ==
5799 SNDRV_PCM_STREAM_CAPTURE)
Takashi Iwai763f3562005-06-03 11:25:34 +02005800 hdspm_silence_playback(hdspm);
5801 } else {
5802 if (running &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01005803 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Takashi Iwai763f3562005-06-03 11:25:34 +02005804 hdspm_silence_playback(hdspm);
5805 }
5806 } else {
5807 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
5808 hdspm_silence_playback(hdspm);
5809 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005810_ok:
Takashi Iwai763f3562005-06-03 11:25:34 +02005811 snd_pcm_trigger_done(substream, substream);
5812 if (!hdspm->running && running)
5813 hdspm_start_audio(hdspm);
5814 else if (hdspm->running && !running)
5815 hdspm_stop_audio(hdspm);
5816 hdspm->running = running;
5817 spin_unlock(&hdspm->lock);
5818
5819 return 0;
5820}
5821
Takashi Iwai98274f02005-11-17 14:52:34 +01005822static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005823{
5824 return 0;
5825}
5826
Takashi Iwaic1c39812020-01-03 09:16:17 +01005827static const struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005828 .info = (SNDRV_PCM_INFO_MMAP |
5829 SNDRV_PCM_INFO_MMAP_VALID |
5830 SNDRV_PCM_INFO_NONINTERLEAVED |
5831 SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
5832 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5833 .rates = (SNDRV_PCM_RATE_32000 |
5834 SNDRV_PCM_RATE_44100 |
5835 SNDRV_PCM_RATE_48000 |
5836 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005837 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5838 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ),
Takashi Iwai763f3562005-06-03 11:25:34 +02005839 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005840 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005841 .channels_min = 1,
5842 .channels_max = HDSPM_MAX_CHANNELS,
5843 .buffer_bytes_max =
5844 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
Adrian Knoth1b6fa102011-08-15 00:22:51 +02005845 .period_bytes_min = (32 * 4),
Takashi Iwai52e6fb42011-08-15 10:40:59 +02005846 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005847 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005848 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005849 .fifo_size = 0
5850};
5851
Takashi Iwaic1c39812020-01-03 09:16:17 +01005852static const struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005853 .info = (SNDRV_PCM_INFO_MMAP |
5854 SNDRV_PCM_INFO_MMAP_VALID |
5855 SNDRV_PCM_INFO_NONINTERLEAVED |
5856 SNDRV_PCM_INFO_SYNC_START),
5857 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5858 .rates = (SNDRV_PCM_RATE_32000 |
5859 SNDRV_PCM_RATE_44100 |
5860 SNDRV_PCM_RATE_48000 |
5861 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005862 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5863 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
Takashi Iwai763f3562005-06-03 11:25:34 +02005864 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005865 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005866 .channels_min = 1,
5867 .channels_max = HDSPM_MAX_CHANNELS,
5868 .buffer_bytes_max =
5869 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
Adrian Knoth1b6fa102011-08-15 00:22:51 +02005870 .period_bytes_min = (32 * 4),
Takashi Iwai52e6fb42011-08-15 10:40:59 +02005871 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005872 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005873 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005874 .fifo_size = 0
5875};
5876
Adrian Knoth0dca1792011-01-26 19:32:14 +01005877static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
5878 struct snd_pcm_hw_rule *rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005879{
Takashi Iwai98274f02005-11-17 14:52:34 +01005880 struct hdspm *hdspm = rule->private;
5881 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005882 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005883 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005884 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5885
Adrian Knoth0dca1792011-01-26 19:32:14 +01005886 if (r->min > 96000 && r->max <= 192000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005887 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005888 .min = hdspm->qs_in_channels,
5889 .max = hdspm->qs_in_channels,
5890 .integer = 1,
5891 };
5892 return snd_interval_refine(c, &t);
5893 } else if (r->min > 48000 && r->max <= 96000) {
5894 struct snd_interval t = {
5895 .min = hdspm->ds_in_channels,
5896 .max = hdspm->ds_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005897 .integer = 1,
5898 };
5899 return snd_interval_refine(c, &t);
5900 } else if (r->max < 64000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005901 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005902 .min = hdspm->ss_in_channels,
5903 .max = hdspm->ss_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005904 .integer = 1,
5905 };
5906 return snd_interval_refine(c, &t);
5907 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005908
Takashi Iwai763f3562005-06-03 11:25:34 +02005909 return 0;
5910}
5911
Adrian Knoth0dca1792011-01-26 19:32:14 +01005912static int snd_hdspm_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
Takashi Iwai98274f02005-11-17 14:52:34 +01005913 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005914{
Takashi Iwai98274f02005-11-17 14:52:34 +01005915 struct hdspm *hdspm = rule->private;
5916 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005917 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005918 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005919 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5920
Adrian Knoth0dca1792011-01-26 19:32:14 +01005921 if (r->min > 96000 && r->max <= 192000) {
5922 struct snd_interval t = {
5923 .min = hdspm->qs_out_channels,
5924 .max = hdspm->qs_out_channels,
5925 .integer = 1,
5926 };
5927 return snd_interval_refine(c, &t);
5928 } else if (r->min > 48000 && r->max <= 96000) {
5929 struct snd_interval t = {
5930 .min = hdspm->ds_out_channels,
5931 .max = hdspm->ds_out_channels,
5932 .integer = 1,
5933 };
5934 return snd_interval_refine(c, &t);
5935 } else if (r->max < 64000) {
5936 struct snd_interval t = {
5937 .min = hdspm->ss_out_channels,
5938 .max = hdspm->ss_out_channels,
5939 .integer = 1,
5940 };
5941 return snd_interval_refine(c, &t);
5942 } else {
5943 }
5944 return 0;
5945}
5946
5947static int snd_hdspm_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
5948 struct snd_pcm_hw_rule * rule)
5949{
5950 struct hdspm *hdspm = rule->private;
5951 struct snd_interval *c =
5952 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5953 struct snd_interval *r =
5954 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5955
5956 if (c->min >= hdspm->ss_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005957 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005958 .min = 32000,
5959 .max = 48000,
5960 .integer = 1,
5961 };
5962 return snd_interval_refine(r, &t);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005963 } else if (c->max <= hdspm->qs_in_channels) {
5964 struct snd_interval t = {
5965 .min = 128000,
5966 .max = 192000,
5967 .integer = 1,
5968 };
5969 return snd_interval_refine(r, &t);
5970 } else if (c->max <= hdspm->ds_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005971 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005972 .min = 64000,
5973 .max = 96000,
5974 .integer = 1,
5975 };
Takashi Iwai763f3562005-06-03 11:25:34 +02005976 return snd_interval_refine(r, &t);
5977 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005978
5979 return 0;
5980}
5981static int snd_hdspm_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
5982 struct snd_pcm_hw_rule *rule)
5983{
5984 struct hdspm *hdspm = rule->private;
5985 struct snd_interval *c =
5986 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5987 struct snd_interval *r =
5988 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5989
5990 if (c->min >= hdspm->ss_out_channels) {
5991 struct snd_interval t = {
5992 .min = 32000,
5993 .max = 48000,
5994 .integer = 1,
5995 };
5996 return snd_interval_refine(r, &t);
5997 } else if (c->max <= hdspm->qs_out_channels) {
5998 struct snd_interval t = {
5999 .min = 128000,
6000 .max = 192000,
6001 .integer = 1,
6002 };
6003 return snd_interval_refine(r, &t);
6004 } else if (c->max <= hdspm->ds_out_channels) {
6005 struct snd_interval t = {
6006 .min = 64000,
6007 .max = 96000,
6008 .integer = 1,
6009 };
6010 return snd_interval_refine(r, &t);
6011 }
6012
Takashi Iwai763f3562005-06-03 11:25:34 +02006013 return 0;
6014}
6015
Adrian Knoth0dca1792011-01-26 19:32:14 +01006016static int snd_hdspm_hw_rule_in_channels(struct snd_pcm_hw_params *params,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006017 struct snd_pcm_hw_rule *rule)
6018{
6019 unsigned int list[3];
6020 struct hdspm *hdspm = rule->private;
6021 struct snd_interval *c = hw_param_interval(params,
6022 SNDRV_PCM_HW_PARAM_CHANNELS);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006023
6024 list[0] = hdspm->qs_in_channels;
6025 list[1] = hdspm->ds_in_channels;
6026 list[2] = hdspm->ss_in_channels;
6027 return snd_interval_list(c, 3, list, 0);
6028}
6029
6030static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params,
6031 struct snd_pcm_hw_rule *rule)
6032{
6033 unsigned int list[3];
6034 struct hdspm *hdspm = rule->private;
6035 struct snd_interval *c = hw_param_interval(params,
6036 SNDRV_PCM_HW_PARAM_CHANNELS);
6037
6038 list[0] = hdspm->qs_out_channels;
6039 list[1] = hdspm->ds_out_channels;
6040 list[2] = hdspm->ss_out_channels;
6041 return snd_interval_list(c, 3, list, 0);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006042}
6043
6044
Takashi Iwaibdf84db2017-06-07 14:22:35 +02006045static const unsigned int hdspm_aes32_sample_rates[] = {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006046 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000
6047};
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006048
Takashi Iwaibdf84db2017-06-07 14:22:35 +02006049static const struct snd_pcm_hw_constraint_list
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006050hdspm_hw_constraints_aes32_sample_rates = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006051 .count = ARRAY_SIZE(hdspm_aes32_sample_rates),
6052 .list = hdspm_aes32_sample_rates,
6053 .mask = 0
6054};
6055
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006056static int snd_hdspm_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02006057{
Takashi Iwai98274f02005-11-17 14:52:34 +01006058 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
6059 struct snd_pcm_runtime *runtime = substream->runtime;
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006060 bool playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
Takashi Iwai763f3562005-06-03 11:25:34 +02006061
Takashi Iwai763f3562005-06-03 11:25:34 +02006062 spin_lock_irq(&hdspm->lock);
Takashi Iwai763f3562005-06-03 11:25:34 +02006063 snd_pcm_set_sync(substream);
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006064 runtime->hw = (playback) ? snd_hdspm_playback_subinfo :
6065 snd_hdspm_capture_subinfo;
Takashi Iwai763f3562005-06-03 11:25:34 +02006066
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006067 if (playback) {
Markus Elfringda2ea372017-08-12 17:07:09 +02006068 if (!hdspm->capture_substream)
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006069 hdspm_stop_audio(hdspm);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006070
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006071 hdspm->playback_pid = current->pid;
6072 hdspm->playback_substream = substream;
6073 } else {
Markus Elfringda2ea372017-08-12 17:07:09 +02006074 if (!hdspm->playback_substream)
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006075 hdspm_stop_audio(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006076
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006077 hdspm->capture_pid = current->pid;
6078 hdspm->capture_substream = substream;
6079 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006080
6081 spin_unlock_irq(&hdspm->lock);
6082
6083 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Takashi Iwaid8776812011-08-15 10:45:42 +02006084 snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02006085
Adrian Knoth0dca1792011-01-26 19:32:14 +01006086 switch (hdspm->io_type) {
6087 case AIO:
6088 case RayDAT:
Takashi Iwaid8776812011-08-15 10:45:42 +02006089 snd_pcm_hw_constraint_minmax(runtime,
6090 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
6091 32, 4096);
6092 /* RayDAT & AIO have a fixed buffer of 16384 samples per channel */
Lars-Peter Clausenb4ffc1b2015-10-18 15:39:21 +02006093 snd_pcm_hw_constraint_single(runtime,
Takashi Iwaid8776812011-08-15 10:45:42 +02006094 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
Lars-Peter Clausenb4ffc1b2015-10-18 15:39:21 +02006095 16384);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006096 break;
6097
6098 default:
Takashi Iwaid8776812011-08-15 10:45:42 +02006099 snd_pcm_hw_constraint_minmax(runtime,
6100 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
6101 64, 8192);
Lars-Peter Clausenb4ffc1b2015-10-18 15:39:21 +02006102 snd_pcm_hw_constraint_single(runtime,
6103 SNDRV_PCM_HW_PARAM_PERIODS, 2);
Takashi Iwaid8776812011-08-15 10:45:42 +02006104 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006105 }
6106
6107 if (AES32 == hdspm->io_type) {
Takashi Iwai3fa9e3d2011-08-15 10:42:23 +02006108 runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006109 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
6110 &hdspm_hw_constraints_aes32_sample_rates);
6111 } else {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006112 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006113 (playback ?
6114 snd_hdspm_hw_rule_rate_out_channels :
6115 snd_hdspm_hw_rule_rate_in_channels), hdspm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006116 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01006117 }
Adrian Knoth88fabbf2011-02-23 11:43:10 +01006118
6119 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006120 (playback ? snd_hdspm_hw_rule_out_channels :
6121 snd_hdspm_hw_rule_in_channels), hdspm,
Adrian Knoth88fabbf2011-02-23 11:43:10 +01006122 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
6123
6124 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006125 (playback ? snd_hdspm_hw_rule_out_channels_rate :
6126 snd_hdspm_hw_rule_in_channels_rate), hdspm,
Adrian Knoth88fabbf2011-02-23 11:43:10 +01006127 SNDRV_PCM_HW_PARAM_RATE, -1);
6128
Takashi Iwai763f3562005-06-03 11:25:34 +02006129 return 0;
6130}
6131
Adrian Knoth8b73b862015-02-17 00:05:05 +01006132static int snd_hdspm_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02006133{
Takashi Iwai98274f02005-11-17 14:52:34 +01006134 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Adrian Knoth8b73b862015-02-17 00:05:05 +01006135 bool playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
Takashi Iwai763f3562005-06-03 11:25:34 +02006136
6137 spin_lock_irq(&hdspm->lock);
6138
Adrian Knoth8b73b862015-02-17 00:05:05 +01006139 if (playback) {
6140 hdspm->playback_pid = -1;
6141 hdspm->playback_substream = NULL;
6142 } else {
6143 hdspm->capture_pid = -1;
6144 hdspm->capture_substream = NULL;
6145 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006146
6147 spin_unlock_irq(&hdspm->lock);
6148
6149 return 0;
6150}
6151
Adrian Knoth0dca1792011-01-26 19:32:14 +01006152static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
Takashi Iwai763f3562005-06-03 11:25:34 +02006153{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006154 /* we have nothing to initialize but the call is required */
6155 return 0;
6156}
6157
6158static inline int copy_u32_le(void __user *dest, void __iomem *src)
6159{
6160 u32 val = readl(src);
6161 return copy_to_user(dest, &val, 4);
6162}
6163
6164static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006165 unsigned int cmd, unsigned long arg)
Adrian Knoth0dca1792011-01-26 19:32:14 +01006166{
6167 void __user *argp = (void __user *)arg;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006168 struct hdspm *hdspm = hw->private_data;
Takashi Iwai98274f02005-11-17 14:52:34 +01006169 struct hdspm_mixer_ioctl mixer;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006170 struct hdspm_config info;
6171 struct hdspm_status status;
Takashi Iwai98274f02005-11-17 14:52:34 +01006172 struct hdspm_version hdspm_version;
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006173 struct hdspm_peak_rms *levels;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006174 struct hdspm_ltc ltc;
6175 unsigned int statusregister;
6176 long unsigned int s;
6177 int i = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02006178
6179 switch (cmd) {
6180
Takashi Iwai763f3562005-06-03 11:25:34 +02006181 case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006182 levels = &hdspm->peak_rms;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006183 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006184 levels->input_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006185 readl(hdspm->iobase +
6186 HDSPM_MADI_INPUT_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006187 levels->playback_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006188 readl(hdspm->iobase +
6189 HDSPM_MADI_PLAYBACK_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006190 levels->output_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006191 readl(hdspm->iobase +
6192 HDSPM_MADI_OUTPUT_PEAK + i*4);
6193
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006194 levels->input_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006195 ((uint64_t) readl(hdspm->iobase +
6196 HDSPM_MADI_INPUT_RMS_H + i*4) << 32) |
6197 (uint64_t) readl(hdspm->iobase +
6198 HDSPM_MADI_INPUT_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006199 levels->playback_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006200 ((uint64_t)readl(hdspm->iobase +
6201 HDSPM_MADI_PLAYBACK_RMS_H+i*4) << 32) |
6202 (uint64_t)readl(hdspm->iobase +
6203 HDSPM_MADI_PLAYBACK_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006204 levels->output_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006205 ((uint64_t)readl(hdspm->iobase +
6206 HDSPM_MADI_OUTPUT_RMS_H + i*4) << 32) |
6207 (uint64_t)readl(hdspm->iobase +
6208 HDSPM_MADI_OUTPUT_RMS_L + i*4);
6209 }
6210
6211 if (hdspm->system_sample_rate > 96000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006212 levels->speed = qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006213 } else if (hdspm->system_sample_rate > 48000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006214 levels->speed = ds;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006215 } else {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006216 levels->speed = ss;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006217 }
Jaroslav Kysela730a5862011-01-27 13:03:15 +01006218 levels->status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006219
Markus Elfring7dfec502017-08-12 16:50:06 +02006220 s = copy_to_user(argp, levels, sizeof(*levels));
Adrian Knoth0dca1792011-01-26 19:32:14 +01006221 if (0 != s) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006222 /* dev_err(hdspm->card->dev, "copy_to_user(.., .., %lu): %lu
Adrian Knoth0dca1792011-01-26 19:32:14 +01006223 [Levels]\n", sizeof(struct hdspm_peak_rms), s);
6224 */
Takashi Iwai763f3562005-06-03 11:25:34 +02006225 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006226 }
6227 break;
6228
6229 case SNDRV_HDSPM_IOCTL_GET_LTC:
6230 ltc.ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
6231 i = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
6232 if (i & HDSPM_TCO1_LTC_Input_valid) {
6233 switch (i & (HDSPM_TCO1_LTC_Format_LSB |
6234 HDSPM_TCO1_LTC_Format_MSB)) {
6235 case 0:
6236 ltc.format = fps_24;
6237 break;
6238 case HDSPM_TCO1_LTC_Format_LSB:
6239 ltc.format = fps_25;
6240 break;
6241 case HDSPM_TCO1_LTC_Format_MSB:
6242 ltc.format = fps_2997;
6243 break;
6244 default:
Adrian Knoth17d2f002013-08-19 17:20:30 +02006245 ltc.format = fps_30;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006246 break;
6247 }
6248 if (i & HDSPM_TCO1_set_drop_frame_flag) {
6249 ltc.frame = drop_frame;
6250 } else {
6251 ltc.frame = full_frame;
6252 }
6253 } else {
6254 ltc.format = format_invalid;
6255 ltc.frame = frame_invalid;
6256 }
6257 if (i & HDSPM_TCO1_Video_Input_Format_NTSC) {
6258 ltc.input_format = ntsc;
6259 } else if (i & HDSPM_TCO1_Video_Input_Format_PAL) {
6260 ltc.input_format = pal;
6261 } else {
6262 ltc.input_format = no_video;
6263 }
6264
Markus Elfring7dfec502017-08-12 16:50:06 +02006265 s = copy_to_user(argp, &ltc, sizeof(ltc));
Adrian Knoth0dca1792011-01-26 19:32:14 +01006266 if (0 != s) {
6267 /*
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006268 dev_err(hdspm->card->dev, "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */
Takashi Iwai763f3562005-06-03 11:25:34 +02006269 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006270 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006271
6272 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02006273
Adrian Knoth0dca1792011-01-26 19:32:14 +01006274 case SNDRV_HDSPM_IOCTL_GET_CONFIG:
Takashi Iwai763f3562005-06-03 11:25:34 +02006275
Adrian Knoth4ab69a22011-02-23 11:43:14 +01006276 memset(&info, 0, sizeof(info));
Takashi Iwai763f3562005-06-03 11:25:34 +02006277 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006278 info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
6279 info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006280
6281 info.system_sample_rate = hdspm->system_sample_rate;
6282 info.autosync_sample_rate =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006283 hdspm_external_sample_rate(hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006284 info.system_clock_mode = hdspm_system_clock_mode(hdspm);
6285 info.clock_source = hdspm_clock_source(hdspm);
6286 info.autosync_ref = hdspm_autosync_ref(hdspm);
Adrian Knothc9e16682012-12-03 14:55:50 +01006287 info.line_out = hdspm_toggle_setting(hdspm, HDSPM_LineOut);
Takashi Iwai763f3562005-06-03 11:25:34 +02006288 info.passthru = 0;
6289 spin_unlock_irq(&hdspm->lock);
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006290 if (copy_to_user(argp, &info, sizeof(info)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006291 return -EFAULT;
6292 break;
6293
Adrian Knoth0dca1792011-01-26 19:32:14 +01006294 case SNDRV_HDSPM_IOCTL_GET_STATUS:
Dan Carpenter643d6bb2011-09-23 09:24:21 +03006295 memset(&status, 0, sizeof(status));
6296
Adrian Knoth0dca1792011-01-26 19:32:14 +01006297 status.card_type = hdspm->io_type;
6298
6299 status.autosync_source = hdspm_autosync_ref(hdspm);
6300
6301 status.card_clock = 110069313433624ULL;
6302 status.master_period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
6303
6304 switch (hdspm->io_type) {
6305 case MADI:
6306 case MADIface:
6307 status.card_specific.madi.sync_wc =
6308 hdspm_wc_sync_check(hdspm);
6309 status.card_specific.madi.sync_madi =
6310 hdspm_madi_sync_check(hdspm);
6311 status.card_specific.madi.sync_tco =
6312 hdspm_tco_sync_check(hdspm);
6313 status.card_specific.madi.sync_in =
6314 hdspm_sync_in_sync_check(hdspm);
6315
6316 statusregister =
6317 hdspm_read(hdspm, HDSPM_statusRegister);
6318 status.card_specific.madi.madi_input =
6319 (statusregister & HDSPM_AB_int) ? 1 : 0;
6320 status.card_specific.madi.channel_format =
Adrian Knoth9e6ff522011-10-27 21:57:52 +02006321 (statusregister & HDSPM_RX_64ch) ? 1 : 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006322 /* TODO: Mac driver sets it when f_s>48kHz */
6323 status.card_specific.madi.frame_format = 0;
6324
6325 default:
6326 break;
6327 }
6328
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006329 if (copy_to_user(argp, &status, sizeof(status)))
Adrian Knoth0dca1792011-01-26 19:32:14 +01006330 return -EFAULT;
6331
6332
6333 break;
6334
Takashi Iwai763f3562005-06-03 11:25:34 +02006335 case SNDRV_HDSPM_IOCTL_GET_VERSION:
Dan Carpenter643d6bb2011-09-23 09:24:21 +03006336 memset(&hdspm_version, 0, sizeof(hdspm_version));
6337
Adrian Knoth0dca1792011-01-26 19:32:14 +01006338 hdspm_version.card_type = hdspm->io_type;
Takashi Iwai57a44512013-10-29 15:26:12 +01006339 strlcpy(hdspm_version.cardname, hdspm->card_name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006340 sizeof(hdspm_version.cardname));
Adrian Knoth7d53a632012-01-04 14:31:16 +01006341 hdspm_version.serial = hdspm->serial;
Takashi Iwai763f3562005-06-03 11:25:34 +02006342 hdspm_version.firmware_rev = hdspm->firmware_rev;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006343 hdspm_version.addons = 0;
6344 if (hdspm->tco)
6345 hdspm_version.addons |= HDSPM_ADDON_TCO;
6346
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006347 if (copy_to_user(argp, &hdspm_version,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006348 sizeof(hdspm_version)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006349 return -EFAULT;
6350 break;
6351
6352 case SNDRV_HDSPM_IOCTL_GET_MIXER:
Dan Carpenter2ca595a2011-09-23 09:25:05 +03006353 if (copy_from_user(&mixer, argp, sizeof(mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006354 return -EFAULT;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006355 if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
Markus Elfring7dfec502017-08-12 16:50:06 +02006356 sizeof(*mixer.mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006357 return -EFAULT;
6358 break;
6359
6360 default:
6361 return -EINVAL;
6362 }
6363 return 0;
6364}
6365
Julia Lawall6769e9882016-09-02 00:13:10 +02006366static const struct snd_pcm_ops snd_hdspm_ops = {
Adrian Knoth5ecc5dc2015-02-17 00:05:04 +01006367 .open = snd_hdspm_open,
Adrian Knoth8b73b862015-02-17 00:05:05 +01006368 .close = snd_hdspm_release,
Takashi Iwai763f3562005-06-03 11:25:34 +02006369 .ioctl = snd_hdspm_ioctl,
6370 .hw_params = snd_hdspm_hw_params,
6371 .hw_free = snd_hdspm_hw_free,
6372 .prepare = snd_hdspm_prepare,
6373 .trigger = snd_hdspm_trigger,
6374 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006375};
6376
Bill Pembertone23e7a12012-12-06 12:35:10 -05006377static int snd_hdspm_create_hwdep(struct snd_card *card,
6378 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006379{
Takashi Iwai98274f02005-11-17 14:52:34 +01006380 struct snd_hwdep *hw;
Takashi Iwai763f3562005-06-03 11:25:34 +02006381 int err;
6382
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006383 err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw);
6384 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006385 return err;
6386
6387 hdspm->hwdep = hw;
6388 hw->private_data = hdspm;
6389 strcpy(hw->name, "HDSPM hwdep interface");
6390
Adrian Knoth0dca1792011-01-26 19:32:14 +01006391 hw->ops.open = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006392 hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
Adrian Knoth8de5d6f2012-03-08 15:38:04 +01006393 hw->ops.ioctl_compat = snd_hdspm_hwdep_ioctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006394 hw->ops.release = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006395
6396 return 0;
6397}
6398
6399
6400/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01006401 memory interface
Takashi Iwai763f3562005-06-03 11:25:34 +02006402 ------------------------------------------------------------*/
Bill Pembertone23e7a12012-12-06 12:35:10 -05006403static int snd_hdspm_preallocate_memory(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006404{
Takashi Iwai98274f02005-11-17 14:52:34 +01006405 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006406 size_t wanted;
6407
6408 pcm = hdspm->pcm;
6409
Remy Bruno3cee5a62006-10-16 12:46:32 +02006410 wanted = HDSPM_DMA_AREA_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02006411
Takashi Iwai5116b942019-02-04 16:32:09 +01006412 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
Takashi Iwai1a810432019-11-05 16:18:54 +01006413 &hdspm->pci->dev,
Takashi Iwai5116b942019-02-04 16:32:09 +01006414 wanted, wanted);
6415 dev_dbg(hdspm->card->dev, " Preallocated %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006416 return 0;
6417}
6418
Philippe Bekaerte4e07c62019-05-23 23:56:49 +02006419/* Inform the card what DMA addresses to use for the indicated channel. */
6420/* Each channel got 16 4K pages allocated for DMA transfers. */
6421static void hdspm_set_channel_dma_addr(struct hdspm *hdspm,
6422 struct snd_pcm_substream *substream,
6423 unsigned int reg, int channel)
Takashi Iwai763f3562005-06-03 11:25:34 +02006424{
6425 int i;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006426
Philippe Bekaerte4e07c62019-05-23 23:56:49 +02006427 for (i = channel * 16; i < channel * 16 + 16; i++)
Takashi Iwai763f3562005-06-03 11:25:34 +02006428 hdspm_write(hdspm, reg + 4 * i,
Philippe Bekaerte4e07c62019-05-23 23:56:49 +02006429 snd_pcm_sgbuf_get_addr(substream, 4096 * i));
Takashi Iwai763f3562005-06-03 11:25:34 +02006430}
6431
Adrian Knoth0dca1792011-01-26 19:32:14 +01006432
Takashi Iwai763f3562005-06-03 11:25:34 +02006433/* ------------- ALSA Devices ---------------------------- */
Bill Pembertone23e7a12012-12-06 12:35:10 -05006434static int snd_hdspm_create_pcm(struct snd_card *card,
6435 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006436{
Takashi Iwai98274f02005-11-17 14:52:34 +01006437 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006438 int err;
6439
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006440 err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm);
6441 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006442 return err;
6443
6444 hdspm->pcm = pcm;
6445 pcm->private_data = hdspm;
6446 strcpy(pcm->name, hdspm->card_name);
6447
6448 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
Adrian Knoth0c8d9482015-02-17 00:05:06 +01006449 &snd_hdspm_ops);
Takashi Iwai763f3562005-06-03 11:25:34 +02006450 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
Adrian Knoth0c8d9482015-02-17 00:05:06 +01006451 &snd_hdspm_ops);
Takashi Iwai763f3562005-06-03 11:25:34 +02006452
6453 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
6454
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006455 err = snd_hdspm_preallocate_memory(hdspm);
6456 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006457 return err;
6458
6459 return 0;
6460}
6461
Takashi Iwai98274f02005-11-17 14:52:34 +01006462static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006463{
Adrian Knoth7c7102b2011-02-28 15:14:50 +01006464 int i;
6465
6466 for (i = 0; i < hdspm->midiPorts; i++)
6467 snd_hdspm_flush_midi_input(hdspm, i);
Takashi Iwai763f3562005-06-03 11:25:34 +02006468}
6469
Bill Pembertone23e7a12012-12-06 12:35:10 -05006470static int snd_hdspm_create_alsa_devices(struct snd_card *card,
6471 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006472{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006473 int err, i;
Takashi Iwai763f3562005-06-03 11:25:34 +02006474
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006475 dev_dbg(card->dev, "Create card...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006476 err = snd_hdspm_create_pcm(card, hdspm);
6477 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006478 return err;
6479
Adrian Knoth0dca1792011-01-26 19:32:14 +01006480 i = 0;
6481 while (i < hdspm->midiPorts) {
6482 err = snd_hdspm_create_midi(card, hdspm, i);
6483 if (err < 0) {
6484 return err;
6485 }
6486 i++;
6487 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006488
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006489 err = snd_hdspm_create_controls(card, hdspm);
6490 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006491 return err;
6492
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006493 err = snd_hdspm_create_hwdep(card, hdspm);
6494 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006495 return err;
6496
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006497 dev_dbg(card->dev, "proc init...\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02006498 snd_hdspm_proc_init(hdspm);
6499
6500 hdspm->system_sample_rate = -1;
6501 hdspm->last_external_sample_rate = -1;
6502 hdspm->last_internal_sample_rate = -1;
6503 hdspm->playback_pid = -1;
6504 hdspm->capture_pid = -1;
6505 hdspm->capture_substream = NULL;
6506 hdspm->playback_substream = NULL;
6507
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006508 dev_dbg(card->dev, "Set defaults...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006509 err = snd_hdspm_set_defaults(hdspm);
6510 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006511 return err;
6512
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006513 dev_dbg(card->dev, "Update mixer controls...\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02006514 hdspm_update_simple_mixer_controls(hdspm);
6515
Colin Ian King1bb6d9e2018-08-26 23:09:52 +01006516 dev_dbg(card->dev, "Initializing complete?\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02006517
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006518 err = snd_card_register(card);
6519 if (err < 0) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006520 dev_err(card->dev, "error registering card\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02006521 return err;
6522 }
6523
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006524 dev_dbg(card->dev, "... yes now\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02006525
6526 return 0;
6527}
6528
Bill Pembertone23e7a12012-12-06 12:35:10 -05006529static int snd_hdspm_create(struct snd_card *card,
6530 struct hdspm *hdspm)
6531{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006532
Takashi Iwai763f3562005-06-03 11:25:34 +02006533 struct pci_dev *pci = hdspm->pci;
6534 int err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006535 unsigned long io_extent;
6536
6537 hdspm->irq = -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02006538 hdspm->card = card;
6539
6540 spin_lock_init(&hdspm->lock);
Takashi Iwaia2e527c2020-09-03 12:41:27 +02006541 INIT_WORK(&hdspm->midi_work, hdspm_midi_work);
Takashi Iwai763f3562005-06-03 11:25:34 +02006542
Takashi Iwai763f3562005-06-03 11:25:34 +02006543 pci_read_config_word(hdspm->pci,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006544 PCI_CLASS_REVISION, &hdspm->firmware_rev);
Remy Bruno3cee5a62006-10-16 12:46:32 +02006545
Takashi Iwai763f3562005-06-03 11:25:34 +02006546 strcpy(card->mixername, "Xilinx FPGA");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006547 strcpy(card->driver, "HDSPM");
6548
6549 switch (hdspm->firmware_rev) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01006550 case HDSPM_RAYDAT_REV:
6551 hdspm->io_type = RayDAT;
6552 hdspm->card_name = "RME RayDAT";
6553 hdspm->midiPorts = 2;
6554 break;
6555 case HDSPM_AIO_REV:
6556 hdspm->io_type = AIO;
6557 hdspm->card_name = "RME AIO";
6558 hdspm->midiPorts = 1;
6559 break;
6560 case HDSPM_MADIFACE_REV:
6561 hdspm->io_type = MADIface;
6562 hdspm->card_name = "RME MADIface";
6563 hdspm->midiPorts = 1;
6564 break;
Adrian Knoth5027f342011-02-28 15:14:49 +01006565 default:
Adrian Knothc09403d2011-10-27 21:57:54 +02006566 if ((hdspm->firmware_rev == 0xf0) ||
6567 ((hdspm->firmware_rev >= 0xe6) &&
6568 (hdspm->firmware_rev <= 0xea))) {
6569 hdspm->io_type = AES32;
6570 hdspm->card_name = "RME AES32";
6571 hdspm->midiPorts = 2;
Adrian Knoth05c7cc92011-11-21 16:15:36 +01006572 } else if ((hdspm->firmware_rev == 0xd2) ||
Adrian Knothc09403d2011-10-27 21:57:54 +02006573 ((hdspm->firmware_rev >= 0xc8) &&
6574 (hdspm->firmware_rev <= 0xcf))) {
6575 hdspm->io_type = MADI;
6576 hdspm->card_name = "RME MADI";
6577 hdspm->midiPorts = 3;
6578 } else {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006579 dev_err(card->dev,
6580 "unknown firmware revision %x\n",
Adrian Knoth5027f342011-02-28 15:14:49 +01006581 hdspm->firmware_rev);
Adrian Knothc09403d2011-10-27 21:57:54 +02006582 return -ENODEV;
6583 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02006584 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006585
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006586 err = pci_enable_device(pci);
6587 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006588 return err;
6589
6590 pci_set_master(hdspm->pci);
6591
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006592 err = pci_request_regions(pci, "hdspm");
6593 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006594 return err;
6595
6596 hdspm->port = pci_resource_start(pci, 0);
6597 io_extent = pci_resource_len(pci, 0);
6598
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006599 dev_dbg(card->dev, "grabbed memory region 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006600 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006601
Christoph Hellwig4bdc0d62020-01-06 09:43:50 +01006602 hdspm->iobase = ioremap(hdspm->port, io_extent);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006603 if (!hdspm->iobase) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006604 dev_err(card->dev, "unable to remap region 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006605 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006606 return -EBUSY;
6607 }
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006608 dev_dbg(card->dev, "remapped region (0x%lx) 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006609 (unsigned long)hdspm->iobase, hdspm->port,
6610 hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006611
6612 if (request_irq(pci->irq, snd_hdspm_interrupt,
Takashi Iwai934c2b62011-06-10 16:36:37 +02006613 IRQF_SHARED, KBUILD_MODNAME, hdspm)) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006614 dev_err(card->dev, "unable to use IRQ %d\n", pci->irq);
Takashi Iwai763f3562005-06-03 11:25:34 +02006615 return -EBUSY;
6616 }
6617
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006618 dev_dbg(card->dev, "use IRQ %d\n", pci->irq);
Takashi Iwai763f3562005-06-03 11:25:34 +02006619
6620 hdspm->irq = pci->irq;
Takashi Iwai39cccf42019-12-10 07:34:32 +01006621 card->sync_irq = hdspm->irq;
Takashi Iwai763f3562005-06-03 11:25:34 +02006622
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006623 dev_dbg(card->dev, "kmalloc Mixer memory of %zd Bytes\n",
Markus Elfring7dfec502017-08-12 16:50:06 +02006624 sizeof(*hdspm->mixer));
6625 hdspm->mixer = kzalloc(sizeof(*hdspm->mixer), GFP_KERNEL);
Markus Elfring9dba5422017-08-12 16:10:32 +02006626 if (!hdspm->mixer)
Julia Lawallb17cbdd2012-08-19 09:02:54 +02006627 return -ENOMEM;
Takashi Iwai763f3562005-06-03 11:25:34 +02006628
Adrian Knoth0dca1792011-01-26 19:32:14 +01006629 hdspm->port_names_in = NULL;
6630 hdspm->port_names_out = NULL;
6631
6632 switch (hdspm->io_type) {
6633 case AES32:
Adrian Knothd2d10a22011-02-28 15:14:47 +01006634 hdspm->ss_in_channels = hdspm->ss_out_channels = AES32_CHANNELS;
6635 hdspm->ds_in_channels = hdspm->ds_out_channels = AES32_CHANNELS;
6636 hdspm->qs_in_channels = hdspm->qs_out_channels = AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006637
6638 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6639 channel_map_aes32;
6640 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6641 channel_map_aes32;
6642 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6643 channel_map_aes32;
6644 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6645 texts_ports_aes32;
6646 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6647 texts_ports_aes32;
6648 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6649 texts_ports_aes32;
6650
Adrian Knothd2d10a22011-02-28 15:14:47 +01006651 hdspm->max_channels_out = hdspm->max_channels_in =
6652 AES32_CHANNELS;
Adrian Knoth432d2502011-02-23 11:43:08 +01006653 hdspm->port_names_in = hdspm->port_names_out =
6654 texts_ports_aes32;
6655 hdspm->channel_map_in = hdspm->channel_map_out =
6656 channel_map_aes32;
6657
Adrian Knoth0dca1792011-01-26 19:32:14 +01006658 break;
6659
6660 case MADI:
6661 case MADIface:
6662 hdspm->ss_in_channels = hdspm->ss_out_channels =
6663 MADI_SS_CHANNELS;
6664 hdspm->ds_in_channels = hdspm->ds_out_channels =
6665 MADI_DS_CHANNELS;
6666 hdspm->qs_in_channels = hdspm->qs_out_channels =
6667 MADI_QS_CHANNELS;
6668
6669 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6670 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006671 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006672 channel_map_unity_ss;
Adrian Knoth01e96072011-02-23 11:43:11 +01006673 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006674 channel_map_unity_ss;
6675
6676 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6677 texts_ports_madi;
6678 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6679 texts_ports_madi;
6680 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6681 texts_ports_madi;
6682 break;
6683
6684 case AIO:
Adrian Knoth0dca1792011-01-26 19:32:14 +01006685 hdspm->ss_in_channels = AIO_IN_SS_CHANNELS;
6686 hdspm->ds_in_channels = AIO_IN_DS_CHANNELS;
6687 hdspm->qs_in_channels = AIO_IN_QS_CHANNELS;
6688 hdspm->ss_out_channels = AIO_OUT_SS_CHANNELS;
6689 hdspm->ds_out_channels = AIO_OUT_DS_CHANNELS;
6690 hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS;
6691
Adrian Knoth3de9db22013-07-05 11:28:02 +02006692 if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006693 dev_info(card->dev, "AEB input board found\n");
Adrian Knoth3de9db22013-07-05 11:28:02 +02006694 hdspm->ss_in_channels += 4;
6695 hdspm->ds_in_channels += 4;
6696 hdspm->qs_in_channels += 4;
6697 }
6698
6699 if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBO_D)) {
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006700 dev_info(card->dev, "AEB output board found\n");
Adrian Knoth3de9db22013-07-05 11:28:02 +02006701 hdspm->ss_out_channels += 4;
6702 hdspm->ds_out_channels += 4;
6703 hdspm->qs_out_channels += 4;
6704 }
6705
Adrian Knoth0dca1792011-01-26 19:32:14 +01006706 hdspm->channel_map_out_ss = channel_map_aio_out_ss;
6707 hdspm->channel_map_out_ds = channel_map_aio_out_ds;
6708 hdspm->channel_map_out_qs = channel_map_aio_out_qs;
6709
6710 hdspm->channel_map_in_ss = channel_map_aio_in_ss;
6711 hdspm->channel_map_in_ds = channel_map_aio_in_ds;
6712 hdspm->channel_map_in_qs = channel_map_aio_in_qs;
6713
6714 hdspm->port_names_in_ss = texts_ports_aio_in_ss;
6715 hdspm->port_names_out_ss = texts_ports_aio_out_ss;
6716 hdspm->port_names_in_ds = texts_ports_aio_in_ds;
6717 hdspm->port_names_out_ds = texts_ports_aio_out_ds;
6718 hdspm->port_names_in_qs = texts_ports_aio_in_qs;
6719 hdspm->port_names_out_qs = texts_ports_aio_out_qs;
6720
6721 break;
6722
6723 case RayDAT:
6724 hdspm->ss_in_channels = hdspm->ss_out_channels =
6725 RAYDAT_SS_CHANNELS;
6726 hdspm->ds_in_channels = hdspm->ds_out_channels =
6727 RAYDAT_DS_CHANNELS;
6728 hdspm->qs_in_channels = hdspm->qs_out_channels =
6729 RAYDAT_QS_CHANNELS;
6730
6731 hdspm->max_channels_in = RAYDAT_SS_CHANNELS;
6732 hdspm->max_channels_out = RAYDAT_SS_CHANNELS;
6733
6734 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6735 channel_map_raydat_ss;
6736 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6737 channel_map_raydat_ds;
6738 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6739 channel_map_raydat_qs;
6740 hdspm->channel_map_in = hdspm->channel_map_out =
6741 channel_map_raydat_ss;
6742
6743 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6744 texts_ports_raydat_ss;
6745 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6746 texts_ports_raydat_ds;
6747 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6748 texts_ports_raydat_qs;
6749
6750
6751 break;
6752
6753 }
6754
6755 /* TCO detection */
6756 switch (hdspm->io_type) {
6757 case AIO:
6758 case RayDAT:
6759 if (hdspm_read(hdspm, HDSPM_statusRegister2) &
6760 HDSPM_s2_tco_detect) {
6761 hdspm->midiPorts++;
Markus Elfring7dfec502017-08-12 16:50:06 +02006762 hdspm->tco = kzalloc(sizeof(*hdspm->tco), GFP_KERNEL);
Markus Elfringda2ea372017-08-12 17:07:09 +02006763 if (hdspm->tco)
Adrian Knoth0dca1792011-01-26 19:32:14 +01006764 hdspm_tco_write(hdspm);
Markus Elfringda2ea372017-08-12 17:07:09 +02006765
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006766 dev_info(card->dev, "AIO/RayDAT TCO module found\n");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006767 } else {
6768 hdspm->tco = NULL;
6769 }
6770 break;
6771
6772 case MADI:
Adrian Knoth0dc831b2013-07-05 11:28:19 +02006773 case AES32:
Adrian Knoth0dca1792011-01-26 19:32:14 +01006774 if (hdspm_read(hdspm, HDSPM_statusRegister) & HDSPM_tco_detect) {
6775 hdspm->midiPorts++;
Markus Elfring7dfec502017-08-12 16:50:06 +02006776 hdspm->tco = kzalloc(sizeof(*hdspm->tco), GFP_KERNEL);
Markus Elfringda2ea372017-08-12 17:07:09 +02006777 if (hdspm->tco)
Adrian Knoth0dca1792011-01-26 19:32:14 +01006778 hdspm_tco_write(hdspm);
Markus Elfringda2ea372017-08-12 17:07:09 +02006779
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006780 dev_info(card->dev, "MADI/AES TCO module found\n");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006781 } else {
6782 hdspm->tco = NULL;
6783 }
6784 break;
6785
6786 default:
6787 hdspm->tco = NULL;
6788 }
6789
6790 /* texts */
6791 switch (hdspm->io_type) {
6792 case AES32:
6793 if (hdspm->tco) {
6794 hdspm->texts_autosync = texts_autosync_aes_tco;
Adrian Knothe71b95a2013-07-05 11:28:06 +02006795 hdspm->texts_autosync_items =
6796 ARRAY_SIZE(texts_autosync_aes_tco);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006797 } else {
6798 hdspm->texts_autosync = texts_autosync_aes;
Adrian Knothe71b95a2013-07-05 11:28:06 +02006799 hdspm->texts_autosync_items =
6800 ARRAY_SIZE(texts_autosync_aes);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006801 }
6802 break;
6803
6804 case MADI:
6805 if (hdspm->tco) {
6806 hdspm->texts_autosync = texts_autosync_madi_tco;
6807 hdspm->texts_autosync_items = 4;
6808 } else {
6809 hdspm->texts_autosync = texts_autosync_madi;
6810 hdspm->texts_autosync_items = 3;
6811 }
6812 break;
6813
6814 case MADIface:
6815
6816 break;
6817
6818 case RayDAT:
6819 if (hdspm->tco) {
6820 hdspm->texts_autosync = texts_autosync_raydat_tco;
6821 hdspm->texts_autosync_items = 9;
6822 } else {
6823 hdspm->texts_autosync = texts_autosync_raydat;
6824 hdspm->texts_autosync_items = 8;
6825 }
6826 break;
6827
6828 case AIO:
6829 if (hdspm->tco) {
6830 hdspm->texts_autosync = texts_autosync_aio_tco;
6831 hdspm->texts_autosync_items = 6;
6832 } else {
6833 hdspm->texts_autosync = texts_autosync_aio;
6834 hdspm->texts_autosync_items = 5;
6835 }
6836 break;
6837
6838 }
6839
Adrian Knothf7de8ba2012-01-10 20:58:40 +01006840 if (hdspm->io_type != MADIface) {
6841 hdspm->serial = (hdspm_read(hdspm,
6842 HDSPM_midiStatusIn0)>>8) & 0xFFFFFF;
6843 /* id contains either a user-provided value or the default
6844 * NULL. If it's the default, we're safe to
6845 * fill card->id with the serial number.
6846 *
6847 * If the serial number is 0xFFFFFF, then we're dealing with
6848 * an old PCI revision that comes without a sane number. In
6849 * this case, we don't set card->id to avoid collisions
6850 * when running with multiple cards.
6851 */
Markus Elfringda2ea372017-08-12 17:07:09 +02006852 if (!id[hdspm->dev] && hdspm->serial != 0xFFFFFF) {
Arnd Bergmann7ad210a2017-07-18 13:48:09 +02006853 snprintf(card->id, sizeof(card->id),
6854 "HDSPMx%06x", hdspm->serial);
Adrian Knothf7de8ba2012-01-10 20:58:40 +01006855 snd_card_set_id(card, card->id);
6856 }
6857 }
6858
Takashi Iwaie3a471d62014-02-26 12:05:40 +01006859 dev_dbg(card->dev, "create alsa devices.\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006860 err = snd_hdspm_create_alsa_devices(card, hdspm);
6861 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006862 return err;
6863
6864 snd_hdspm_initialize_midi_flush(hdspm);
6865
6866 return 0;
6867}
6868
Adrian Knoth0dca1792011-01-26 19:32:14 +01006869
Takashi Iwai98274f02005-11-17 14:52:34 +01006870static int snd_hdspm_free(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006871{
6872
6873 if (hdspm->port) {
Takashi Iwaia2e527c2020-09-03 12:41:27 +02006874 cancel_work_sync(&hdspm->midi_work);
Takashi Iwai763f3562005-06-03 11:25:34 +02006875
6876 /* stop th audio, and cancel all interrupts */
6877 hdspm->control_register &=
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006878 ~(HDSPM_Start | HDSPM_AudioInterruptEnable |
Adrian Knoth0dca1792011-01-26 19:32:14 +01006879 HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable |
6880 HDSPM_Midi2InterruptEnable | HDSPM_Midi3InterruptEnable);
Takashi Iwai763f3562005-06-03 11:25:34 +02006881 hdspm_write(hdspm, HDSPM_controlRegister,
6882 hdspm->control_register);
6883 }
6884
6885 if (hdspm->irq >= 0)
6886 free_irq(hdspm->irq, (void *) hdspm);
6887
Jesper Juhlfc584222005-10-24 15:11:28 +02006888 kfree(hdspm->mixer);
Markus Elfringff6defa2015-01-03 22:55:54 +01006889 iounmap(hdspm->iobase);
Takashi Iwai763f3562005-06-03 11:25:34 +02006890
Takashi Iwai763f3562005-06-03 11:25:34 +02006891 if (hdspm->port)
6892 pci_release_regions(hdspm->pci);
6893
6894 pci_disable_device(hdspm->pci);
6895 return 0;
6896}
6897
Adrian Knoth0dca1792011-01-26 19:32:14 +01006898
Takashi Iwai98274f02005-11-17 14:52:34 +01006899static void snd_hdspm_card_free(struct snd_card *card)
Takashi Iwai763f3562005-06-03 11:25:34 +02006900{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006901 struct hdspm *hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006902
6903 if (hdspm)
6904 snd_hdspm_free(hdspm);
6905}
6906
Adrian Knoth0dca1792011-01-26 19:32:14 +01006907
Bill Pembertone23e7a12012-12-06 12:35:10 -05006908static int snd_hdspm_probe(struct pci_dev *pci,
6909 const struct pci_device_id *pci_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02006910{
6911 static int dev;
Takashi Iwai98274f02005-11-17 14:52:34 +01006912 struct hdspm *hdspm;
6913 struct snd_card *card;
Takashi Iwai763f3562005-06-03 11:25:34 +02006914 int err;
6915
6916 if (dev >= SNDRV_CARDS)
6917 return -ENODEV;
6918 if (!enable[dev]) {
6919 dev++;
6920 return -ENOENT;
6921 }
6922
Takashi Iwai60c57722014-01-29 14:20:19 +01006923 err = snd_card_new(&pci->dev, index[dev], id[dev],
Markus Elfring7dfec502017-08-12 16:50:06 +02006924 THIS_MODULE, sizeof(*hdspm), &card);
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006925 if (err < 0)
6926 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006927
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006928 hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006929 card->private_free = snd_hdspm_card_free;
6930 hdspm->dev = dev;
6931 hdspm->pci = pci;
6932
Adrian Knoth0dca1792011-01-26 19:32:14 +01006933 err = snd_hdspm_create(card, hdspm);
Markus Elfringe35e9dd2017-09-05 22:22:21 +02006934 if (err < 0)
6935 goto free_card;
Takashi Iwai763f3562005-06-03 11:25:34 +02006936
Adrian Knoth0dca1792011-01-26 19:32:14 +01006937 if (hdspm->io_type != MADIface) {
Arnd Bergmann7ad210a2017-07-18 13:48:09 +02006938 snprintf(card->shortname, sizeof(card->shortname), "%s_%x",
6939 hdspm->card_name, hdspm->serial);
6940 snprintf(card->longname, sizeof(card->longname),
6941 "%s S/N 0x%x at 0x%lx, irq %d",
6942 hdspm->card_name, hdspm->serial,
6943 hdspm->port, hdspm->irq);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006944 } else {
Arnd Bergmann7ad210a2017-07-18 13:48:09 +02006945 snprintf(card->shortname, sizeof(card->shortname), "%s",
6946 hdspm->card_name);
6947 snprintf(card->longname, sizeof(card->longname),
6948 "%s at 0x%lx, irq %d",
6949 hdspm->card_name, hdspm->port, hdspm->irq);
Adrian Knoth0dca1792011-01-26 19:32:14 +01006950 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006951
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006952 err = snd_card_register(card);
Markus Elfringe35e9dd2017-09-05 22:22:21 +02006953 if (err < 0)
6954 goto free_card;
Takashi Iwai763f3562005-06-03 11:25:34 +02006955
6956 pci_set_drvdata(pci, card);
6957
6958 dev++;
6959 return 0;
Markus Elfringe35e9dd2017-09-05 22:22:21 +02006960
6961free_card:
6962 snd_card_free(card);
6963 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006964}
6965
Bill Pembertone23e7a12012-12-06 12:35:10 -05006966static void snd_hdspm_remove(struct pci_dev *pci)
Takashi Iwai763f3562005-06-03 11:25:34 +02006967{
6968 snd_card_free(pci_get_drvdata(pci));
Takashi Iwai763f3562005-06-03 11:25:34 +02006969}
6970
Takashi Iwaie9f66d92012-04-24 12:25:00 +02006971static struct pci_driver hdspm_driver = {
Takashi Iwai3733e422011-06-10 16:20:20 +02006972 .name = KBUILD_MODNAME,
Takashi Iwai763f3562005-06-03 11:25:34 +02006973 .id_table = snd_hdspm_ids,
6974 .probe = snd_hdspm_probe,
Bill Pembertone23e7a12012-12-06 12:35:10 -05006975 .remove = snd_hdspm_remove,
Takashi Iwai763f3562005-06-03 11:25:34 +02006976};
6977
Takashi Iwaie9f66d92012-04-24 12:25:00 +02006978module_pci_driver(hdspm_driver);