Merge tag 'for-6.3-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
[linux-block.git] / sound / firewire / motu / motu.h
CommitLineData
da607e19 1/* SPDX-License-Identifier: GPL-2.0-only */
6c3cef48
TS
2/*
3 * motu.h - a part of driver for MOTU FireWire series
4 *
5 * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
6c3cef48
TS
6 */
7
8#ifndef SOUND_FIREWIRE_MOTU_H_INCLUDED
9#define SOUND_FIREWIRE_MOTU_H_INCLUDED
10
11#include <linux/device.h>
12#include <linux/firewire.h>
13#include <linux/firewire-constants.h>
14#include <linux/module.h>
15#include <linux/mod_devicetable.h>
16#include <linux/mutex.h>
17#include <linux/slab.h>
71c37977
TS
18#include <linux/compat.h>
19#include <linux/sched/signal.h>
6c3cef48
TS
20
21#include <sound/control.h>
22#include <sound/core.h>
4641c939 23#include <sound/pcm.h>
4638ec6e 24#include <sound/info.h>
9e796e7d 25#include <sound/rawmidi.h>
71c37977
TS
26#include <sound/firewire.h>
27#include <sound/hwdep.h>
6c3cef48 28
8865a31e 29#include "../lib.h"
4641c939 30#include "../amdtp-stream.h"
9b2bb4f2 31#include "../iso-resources.h"
8865a31e 32
59f6482c 33struct snd_motu_packet_format {
9e796e7d
TS
34 unsigned char midi_flag_offset;
35 unsigned char midi_byte_offset;
59f6482c
TS
36 unsigned char pcm_byte_offset;
37
38 unsigned char msg_chunks;
28c8d3c9 39 unsigned char pcm_chunks[3];
59f6482c
TS
40};
41
e50dfac8
TS
42struct amdtp_motu_cache {
43 unsigned int *event_offsets;
44 unsigned int size;
45 unsigned int tail;
46 unsigned int tx_cycle_count;
f2ac3b83
TS
47 unsigned int head;
48 unsigned int rx_cycle_count;
e50dfac8
TS
49};
50
6c3cef48
TS
51struct snd_motu {
52 struct snd_card *card;
53 struct fw_unit *unit;
54 struct mutex mutex;
9e796e7d 55 spinlock_t lock;
8865a31e 56
5e03c33e
TS
57 /* Model dependent information. */
58 const struct snd_motu_spec *spec;
59f6482c
TS
59
60 /* For packet streaming */
61 struct snd_motu_packet_format tx_packet_formats;
62 struct snd_motu_packet_format rx_packet_formats;
4641c939
TS
63 struct amdtp_stream tx_stream;
64 struct amdtp_stream rx_stream;
9b2bb4f2
TS
65 struct fw_iso_resources tx_resources;
66 struct fw_iso_resources rx_resources;
18f26034 67 unsigned int substreams_counter;
2e76701b
TS
68
69 /* For notification. */
70 struct fw_address_handler async_handler;
71 u32 msg;
71c37977
TS
72
73 /* For uapi */
74 int dev_lock_count;
75 bool dev_lock_changed;
76 wait_queue_head_t hwdep_wait;
4c9eda8f 77 struct snd_hwdep *hwdep;
ccc6c1b0
TS
78
79 struct amdtp_domain domain;
e50dfac8
TS
80
81 struct amdtp_motu_cache cache;
bea36afa
TS
82
83 void *message_parser;
5e03c33e
TS
84};
85
86enum snd_motu_spec_flags {
739bdbae
TS
87 SND_MOTU_SPEC_RX_MIDI_2ND_Q = 0x0001,
88 SND_MOTU_SPEC_RX_MIDI_3RD_Q = 0x0002,
89 SND_MOTU_SPEC_TX_MIDI_2ND_Q = 0x0004,
90 SND_MOTU_SPEC_TX_MIDI_3RD_Q = 0x0008,
bea36afa 91 SND_MOTU_SPEC_REGISTER_DSP = 0x0010,
90b28f3b 92 SND_MOTU_SPEC_COMMAND_DSP = 0x0020,
5e03c33e
TS
93};
94
59f6482c
TS
95#define SND_MOTU_CLOCK_RATE_COUNT 6
96extern const unsigned int snd_motu_clock_rates[SND_MOTU_CLOCK_RATE_COUNT];
97
98enum snd_motu_clock_source {
99 SND_MOTU_CLOCK_SOURCE_INTERNAL,
100 SND_MOTU_CLOCK_SOURCE_ADAT_ON_DSUB,
101 SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT,
102 SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_A,
103 SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_B,
104 SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT,
105 SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_A,
106 SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_B,
107 SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX,
108 SND_MOTU_CLOCK_SOURCE_AESEBU_ON_XLR,
109 SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC,
3f58f004 110 SND_MOTU_CLOCK_SOURCE_SPH,
59f6482c
TS
111 SND_MOTU_CLOCK_SOURCE_UNKNOWN,
112};
113
61d79c70 114enum snd_motu_protocol_version {
d13d6b28 115 SND_MOTU_PROTOCOL_V1,
61d79c70
TS
116 SND_MOTU_PROTOCOL_V2,
117 SND_MOTU_PROTOCOL_V3,
118};
119
5e03c33e
TS
120struct snd_motu_spec {
121 const char *const name;
61d79c70 122 enum snd_motu_protocol_version protocol_version;
ffe66bbe
TS
123 // The combination of snd_motu_spec_flags enumeration-constants.
124 unsigned int flags;
5e03c33e 125
dfbaa4dc
TS
126 unsigned char tx_fixed_pcm_chunks[3];
127 unsigned char rx_fixed_pcm_chunks[3];
6c3cef48
TS
128};
129
d13d6b28 130extern const struct snd_motu_spec snd_motu_spec_828;
b431f16f 131extern const struct snd_motu_spec snd_motu_spec_896;
d13d6b28 132
bd107372 133extern const struct snd_motu_spec snd_motu_spec_828mk2;
23c671be 134extern const struct snd_motu_spec snd_motu_spec_896hd;
0a7c7b47
TS
135extern const struct snd_motu_spec snd_motu_spec_traveler;
136extern const struct snd_motu_spec snd_motu_spec_ultralite;
137extern const struct snd_motu_spec snd_motu_spec_8pre;
6c5e1ac0 138
5b24119e
TS
139extern const struct snd_motu_spec snd_motu_spec_828mk3_fw;
140extern const struct snd_motu_spec snd_motu_spec_828mk3_hybrid;
bf868be7 141extern const struct snd_motu_spec snd_motu_spec_traveler_mk3;
e0b2db35 142extern const struct snd_motu_spec snd_motu_spec_ultralite_mk3;
c806a0e2 143extern const struct snd_motu_spec snd_motu_spec_audio_express;
411ac298 144extern const struct snd_motu_spec snd_motu_spec_track16;
c806a0e2
TS
145extern const struct snd_motu_spec snd_motu_spec_4pre;
146
4641c939
TS
147int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit,
148 enum amdtp_stream_direction dir,
e50dfac8
TS
149 const struct snd_motu_spec *spec,
150 struct amdtp_motu_cache *cache);
4641c939 151int amdtp_motu_set_parameters(struct amdtp_stream *s, unsigned int rate,
9e796e7d 152 unsigned int midi_ports,
4641c939
TS
153 struct snd_motu_packet_format *formats);
154int amdtp_motu_add_pcm_hw_constraints(struct amdtp_stream *s,
155 struct snd_pcm_runtime *runtime);
9e796e7d
TS
156void amdtp_motu_midi_trigger(struct amdtp_stream *s, unsigned int port,
157 struct snd_rawmidi_substream *midi);
2e76701b
TS
158
159int snd_motu_transaction_read(struct snd_motu *motu, u32 offset, __be32 *reg,
160 size_t size);
161int snd_motu_transaction_write(struct snd_motu *motu, u32 offset, __be32 *reg,
162 size_t size);
163int snd_motu_transaction_register(struct snd_motu *motu);
164int snd_motu_transaction_reregister(struct snd_motu *motu);
165void snd_motu_transaction_unregister(struct snd_motu *motu);
9b2bb4f2
TS
166
167int snd_motu_stream_init_duplex(struct snd_motu *motu);
168void snd_motu_stream_destroy_duplex(struct snd_motu *motu);
8b460c76 169int snd_motu_stream_cache_packet_formats(struct snd_motu *motu);
0d39cd0e 170int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate,
0f5482e7
TS
171 unsigned int frames_per_period,
172 unsigned int frames_per_buffer);
8edc56ec 173int snd_motu_stream_start_duplex(struct snd_motu *motu);
9b2bb4f2 174void snd_motu_stream_stop_duplex(struct snd_motu *motu);
71c37977
TS
175int snd_motu_stream_lock_try(struct snd_motu *motu);
176void snd_motu_stream_lock_release(struct snd_motu *motu);
4638ec6e
TS
177
178void snd_motu_proc_init(struct snd_motu *motu);
dd49b2d1
TS
179
180int snd_motu_create_pcm_devices(struct snd_motu *motu);
9e796e7d
TS
181
182int snd_motu_create_midi_devices(struct snd_motu *motu);
71c37977
TS
183
184int snd_motu_create_hwdep_device(struct snd_motu *motu);
ff222b7e 185
d13d6b28
TS
186int snd_motu_protocol_v1_get_clock_rate(struct snd_motu *motu,
187 unsigned int *rate);
188int snd_motu_protocol_v1_set_clock_rate(struct snd_motu *motu,
189 unsigned int rate);
190int snd_motu_protocol_v1_get_clock_source(struct snd_motu *motu,
191 enum snd_motu_clock_source *src);
192int snd_motu_protocol_v1_switch_fetching_mode(struct snd_motu *motu,
193 bool enable);
194int snd_motu_protocol_v1_cache_packet_formats(struct snd_motu *motu);
195
ff222b7e
TS
196int snd_motu_protocol_v2_get_clock_rate(struct snd_motu *motu,
197 unsigned int *rate);
198int snd_motu_protocol_v2_set_clock_rate(struct snd_motu *motu,
199 unsigned int rate);
200int snd_motu_protocol_v2_get_clock_source(struct snd_motu *motu,
201 enum snd_motu_clock_source *src);
202int snd_motu_protocol_v2_switch_fetching_mode(struct snd_motu *motu,
203 bool enable);
204int snd_motu_protocol_v2_cache_packet_formats(struct snd_motu *motu);
205
206int snd_motu_protocol_v3_get_clock_rate(struct snd_motu *motu,
207 unsigned int *rate);
208int snd_motu_protocol_v3_set_clock_rate(struct snd_motu *motu,
209 unsigned int rate);
210int snd_motu_protocol_v3_get_clock_source(struct snd_motu *motu,
211 enum snd_motu_clock_source *src);
212int snd_motu_protocol_v3_switch_fetching_mode(struct snd_motu *motu,
213 bool enable);
214int snd_motu_protocol_v3_cache_packet_formats(struct snd_motu *motu);
215
216static inline int snd_motu_protocol_get_clock_rate(struct snd_motu *motu,
217 unsigned int *rate)
218{
219 if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
220 return snd_motu_protocol_v2_get_clock_rate(motu, rate);
221 else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
222 return snd_motu_protocol_v3_get_clock_rate(motu, rate);
d13d6b28
TS
223 else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V1)
224 return snd_motu_protocol_v1_get_clock_rate(motu, rate);
ff222b7e
TS
225 else
226 return -ENXIO;
227}
228
229static inline int snd_motu_protocol_set_clock_rate(struct snd_motu *motu,
230 unsigned int rate)
231{
232 if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
233 return snd_motu_protocol_v2_set_clock_rate(motu, rate);
234 else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
235 return snd_motu_protocol_v3_set_clock_rate(motu, rate);
d13d6b28
TS
236 else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V1)
237 return snd_motu_protocol_v1_set_clock_rate(motu, rate);
ff222b7e
TS
238 else
239 return -ENXIO;
240}
241
242static inline int snd_motu_protocol_get_clock_source(struct snd_motu *motu,
243 enum snd_motu_clock_source *source)
244{
245 if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
246 return snd_motu_protocol_v2_get_clock_source(motu, source);
247 else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
248 return snd_motu_protocol_v3_get_clock_source(motu, source);
d13d6b28
TS
249 else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V1)
250 return snd_motu_protocol_v1_get_clock_source(motu, source);
ff222b7e
TS
251 else
252 return -ENXIO;
253}
254
255static inline int snd_motu_protocol_switch_fetching_mode(struct snd_motu *motu,
256 bool enable)
257{
258 if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
259 return snd_motu_protocol_v2_switch_fetching_mode(motu, enable);
260 else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
261 return snd_motu_protocol_v3_switch_fetching_mode(motu, enable);
d13d6b28
TS
262 else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V1)
263 return snd_motu_protocol_v1_switch_fetching_mode(motu, enable);
ff222b7e
TS
264 else
265 return -ENXIO;
266}
267
268static inline int snd_motu_protocol_cache_packet_formats(struct snd_motu *motu)
269{
270 if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
271 return snd_motu_protocol_v2_cache_packet_formats(motu);
272 else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
273 return snd_motu_protocol_v3_cache_packet_formats(motu);
d13d6b28
TS
274 else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V1)
275 return snd_motu_protocol_v1_cache_packet_formats(motu);
ff222b7e
TS
276 else
277 return -ENXIO;
278}
279
bea36afa
TS
280int snd_motu_register_dsp_message_parser_new(struct snd_motu *motu);
281int snd_motu_register_dsp_message_parser_init(struct snd_motu *motu);
0cac60c7
TS
282void snd_motu_register_dsp_message_parser_parse(const struct amdtp_stream *s,
283 const struct pkt_desc *descs, unsigned int count);
58b62ab7
TS
284void snd_motu_register_dsp_message_parser_copy_meter(struct snd_motu *motu,
285 struct snd_firewire_motu_register_dsp_meter *meter);
ca15a09c
TS
286void snd_motu_register_dsp_message_parser_copy_parameter(struct snd_motu *motu,
287 struct snd_firewire_motu_register_dsp_parameter *params);
634ec0b2
TS
288unsigned int snd_motu_register_dsp_message_parser_count_event(struct snd_motu *motu);
289bool snd_motu_register_dsp_message_parser_copy_event(struct snd_motu *motu, u32 *event);
90b28f3b
TS
290
291int snd_motu_command_dsp_message_parser_new(struct snd_motu *motu);
292int snd_motu_command_dsp_message_parser_init(struct snd_motu *motu, enum cip_sfc sfc);
0cac60c7
TS
293void snd_motu_command_dsp_message_parser_parse(const struct amdtp_stream *s,
294 const struct pkt_desc *descs, unsigned int count);
58b62ab7
TS
295void snd_motu_command_dsp_message_parser_copy_meter(struct snd_motu *motu,
296 struct snd_firewire_motu_command_dsp_meter *meter);
90b28f3b 297
6c3cef48 298#endif