xref: /linux/sound/firewire/motu/motu.h (revision ffe66bbee1526cd7abd4e77eb3ff27527aace8f6) !
1da607e19SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
26c3cef48STakashi Sakamoto /*
36c3cef48STakashi Sakamoto  * motu.h - a part of driver for MOTU FireWire series
46c3cef48STakashi Sakamoto  *
56c3cef48STakashi Sakamoto  * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
66c3cef48STakashi Sakamoto  */
76c3cef48STakashi Sakamoto 
86c3cef48STakashi Sakamoto #ifndef SOUND_FIREWIRE_MOTU_H_INCLUDED
96c3cef48STakashi Sakamoto #define SOUND_FIREWIRE_MOTU_H_INCLUDED
106c3cef48STakashi Sakamoto 
116c3cef48STakashi Sakamoto #include <linux/device.h>
126c3cef48STakashi Sakamoto #include <linux/firewire.h>
136c3cef48STakashi Sakamoto #include <linux/firewire-constants.h>
146c3cef48STakashi Sakamoto #include <linux/module.h>
156c3cef48STakashi Sakamoto #include <linux/mod_devicetable.h>
166c3cef48STakashi Sakamoto #include <linux/mutex.h>
176c3cef48STakashi Sakamoto #include <linux/slab.h>
1871c37977STakashi Sakamoto #include <linux/compat.h>
1971c37977STakashi Sakamoto #include <linux/sched/signal.h>
206c3cef48STakashi Sakamoto 
216c3cef48STakashi Sakamoto #include <sound/control.h>
226c3cef48STakashi Sakamoto #include <sound/core.h>
234641c939STakashi Sakamoto #include <sound/pcm.h>
244638ec6eSTakashi Sakamoto #include <sound/info.h>
259e796e7dSTakashi Sakamoto #include <sound/rawmidi.h>
2671c37977STakashi Sakamoto #include <sound/firewire.h>
2771c37977STakashi Sakamoto #include <sound/hwdep.h>
286c3cef48STakashi Sakamoto 
298865a31eSTakashi Sakamoto #include "../lib.h"
304641c939STakashi Sakamoto #include "../amdtp-stream.h"
319b2bb4f2STakashi Sakamoto #include "../iso-resources.h"
328865a31eSTakashi Sakamoto 
3359f6482cSTakashi Sakamoto struct snd_motu_packet_format {
349e796e7dSTakashi Sakamoto 	unsigned char midi_flag_offset;
359e796e7dSTakashi Sakamoto 	unsigned char midi_byte_offset;
3659f6482cSTakashi Sakamoto 	unsigned char pcm_byte_offset;
3759f6482cSTakashi Sakamoto 
3859f6482cSTakashi Sakamoto 	unsigned char msg_chunks;
3928c8d3c9STakashi Sakamoto 	unsigned char pcm_chunks[3];
4059f6482cSTakashi Sakamoto };
4159f6482cSTakashi Sakamoto 
426c3cef48STakashi Sakamoto struct snd_motu {
436c3cef48STakashi Sakamoto 	struct snd_card *card;
446c3cef48STakashi Sakamoto 	struct fw_unit *unit;
456c3cef48STakashi Sakamoto 	struct mutex mutex;
469e796e7dSTakashi Sakamoto 	spinlock_t lock;
478865a31eSTakashi Sakamoto 
488865a31eSTakashi Sakamoto 	bool registered;
498865a31eSTakashi Sakamoto 	struct delayed_work dwork;
505e03c33eSTakashi Sakamoto 
515e03c33eSTakashi Sakamoto 	/* Model dependent information. */
525e03c33eSTakashi Sakamoto 	const struct snd_motu_spec *spec;
5359f6482cSTakashi Sakamoto 
5459f6482cSTakashi Sakamoto 	/* For packet streaming */
5559f6482cSTakashi Sakamoto 	struct snd_motu_packet_format tx_packet_formats;
5659f6482cSTakashi Sakamoto 	struct snd_motu_packet_format rx_packet_formats;
574641c939STakashi Sakamoto 	struct amdtp_stream tx_stream;
584641c939STakashi Sakamoto 	struct amdtp_stream rx_stream;
599b2bb4f2STakashi Sakamoto 	struct fw_iso_resources tx_resources;
609b2bb4f2STakashi Sakamoto 	struct fw_iso_resources rx_resources;
6118f26034STakashi Sakamoto 	unsigned int substreams_counter;
622e76701bSTakashi Sakamoto 
632e76701bSTakashi Sakamoto 	/* For notification. */
642e76701bSTakashi Sakamoto 	struct fw_address_handler async_handler;
652e76701bSTakashi Sakamoto 	u32 msg;
6671c37977STakashi Sakamoto 
6771c37977STakashi Sakamoto 	/* For uapi */
6871c37977STakashi Sakamoto 	int dev_lock_count;
6971c37977STakashi Sakamoto 	bool dev_lock_changed;
7071c37977STakashi Sakamoto 	wait_queue_head_t hwdep_wait;
71ccc6c1b0STakashi Sakamoto 
72ccc6c1b0STakashi Sakamoto 	struct amdtp_domain domain;
735e03c33eSTakashi Sakamoto };
745e03c33eSTakashi Sakamoto 
755e03c33eSTakashi Sakamoto enum snd_motu_spec_flags {
76739bdbaeSTakashi Sakamoto 	SND_MOTU_SPEC_RX_MIDI_2ND_Q	= 0x0001,
77739bdbaeSTakashi Sakamoto 	SND_MOTU_SPEC_RX_MIDI_3RD_Q	= 0x0002,
78739bdbaeSTakashi Sakamoto 	SND_MOTU_SPEC_TX_MIDI_2ND_Q	= 0x0004,
79739bdbaeSTakashi Sakamoto 	SND_MOTU_SPEC_TX_MIDI_3RD_Q	= 0x0008,
805e03c33eSTakashi Sakamoto };
815e03c33eSTakashi Sakamoto 
8259f6482cSTakashi Sakamoto #define SND_MOTU_CLOCK_RATE_COUNT	6
8359f6482cSTakashi Sakamoto extern const unsigned int snd_motu_clock_rates[SND_MOTU_CLOCK_RATE_COUNT];
8459f6482cSTakashi Sakamoto 
8559f6482cSTakashi Sakamoto enum snd_motu_clock_source {
8659f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_INTERNAL,
8759f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_ADAT_ON_DSUB,
8859f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT,
8959f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_A,
9059f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_B,
9159f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT,
9259f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_A,
9359f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_B,
9459f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX,
9559f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_AESEBU_ON_XLR,
9659f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC,
973f58f004STakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_SPH,
9859f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_UNKNOWN,
9959f6482cSTakashi Sakamoto };
10059f6482cSTakashi Sakamoto 
10161d79c70STakashi Sakamoto enum snd_motu_protocol_version {
10261d79c70STakashi Sakamoto 	SND_MOTU_PROTOCOL_V2,
10361d79c70STakashi Sakamoto 	SND_MOTU_PROTOCOL_V3,
10461d79c70STakashi Sakamoto };
10561d79c70STakashi Sakamoto 
1065e03c33eSTakashi Sakamoto struct snd_motu_spec {
1075e03c33eSTakashi Sakamoto 	const char *const name;
10861d79c70STakashi Sakamoto 	enum snd_motu_protocol_version protocol_version;
109ffe66bbeSTakashi Sakamoto 	// The combination of snd_motu_spec_flags enumeration-constants.
110ffe66bbeSTakashi Sakamoto 	unsigned int flags;
1115e03c33eSTakashi Sakamoto 
112dfbaa4dcSTakashi Sakamoto 	unsigned char tx_fixed_pcm_chunks[3];
113dfbaa4dcSTakashi Sakamoto 	unsigned char rx_fixed_pcm_chunks[3];
1146c3cef48STakashi Sakamoto };
1156c3cef48STakashi Sakamoto 
116bd107372STakashi Sakamoto extern const struct snd_motu_spec snd_motu_spec_828mk2;
1170a7c7b47STakashi Sakamoto extern const struct snd_motu_spec snd_motu_spec_traveler;
1180a7c7b47STakashi Sakamoto extern const struct snd_motu_spec snd_motu_spec_ultralite;
1190a7c7b47STakashi Sakamoto extern const struct snd_motu_spec snd_motu_spec_8pre;
1206c5e1ac0STakashi Sakamoto 
121c806a0e2STakashi Sakamoto extern const struct snd_motu_spec snd_motu_spec_828mk3;
122e0b2db35STakashi Sakamoto extern const struct snd_motu_spec snd_motu_spec_ultralite_mk3;
123c806a0e2STakashi Sakamoto extern const struct snd_motu_spec snd_motu_spec_audio_express;
124c806a0e2STakashi Sakamoto extern const struct snd_motu_spec snd_motu_spec_4pre;
125c806a0e2STakashi Sakamoto 
1264641c939STakashi Sakamoto int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit,
1274641c939STakashi Sakamoto 		    enum amdtp_stream_direction dir,
12861d79c70STakashi Sakamoto 		    const struct snd_motu_spec *spec);
1294641c939STakashi Sakamoto int amdtp_motu_set_parameters(struct amdtp_stream *s, unsigned int rate,
1309e796e7dSTakashi Sakamoto 			      unsigned int midi_ports,
1314641c939STakashi Sakamoto 			      struct snd_motu_packet_format *formats);
1324641c939STakashi Sakamoto int amdtp_motu_add_pcm_hw_constraints(struct amdtp_stream *s,
1334641c939STakashi Sakamoto 				      struct snd_pcm_runtime *runtime);
1349e796e7dSTakashi Sakamoto void amdtp_motu_midi_trigger(struct amdtp_stream *s, unsigned int port,
1359e796e7dSTakashi Sakamoto 			     struct snd_rawmidi_substream *midi);
1362e76701bSTakashi Sakamoto 
1372e76701bSTakashi Sakamoto int snd_motu_transaction_read(struct snd_motu *motu, u32 offset, __be32 *reg,
1382e76701bSTakashi Sakamoto 			      size_t size);
1392e76701bSTakashi Sakamoto int snd_motu_transaction_write(struct snd_motu *motu, u32 offset, __be32 *reg,
1402e76701bSTakashi Sakamoto 			       size_t size);
1412e76701bSTakashi Sakamoto int snd_motu_transaction_register(struct snd_motu *motu);
1422e76701bSTakashi Sakamoto int snd_motu_transaction_reregister(struct snd_motu *motu);
1432e76701bSTakashi Sakamoto void snd_motu_transaction_unregister(struct snd_motu *motu);
1449b2bb4f2STakashi Sakamoto 
1459b2bb4f2STakashi Sakamoto int snd_motu_stream_init_duplex(struct snd_motu *motu);
1469b2bb4f2STakashi Sakamoto void snd_motu_stream_destroy_duplex(struct snd_motu *motu);
1478b460c76STakashi Sakamoto int snd_motu_stream_cache_packet_formats(struct snd_motu *motu);
1480d39cd0eSTakashi Sakamoto int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate,
1490f5482e7STakashi Sakamoto 				   unsigned int frames_per_period,
1500f5482e7STakashi Sakamoto 				   unsigned int frames_per_buffer);
1518edc56ecSTakashi Sakamoto int snd_motu_stream_start_duplex(struct snd_motu *motu);
1529b2bb4f2STakashi Sakamoto void snd_motu_stream_stop_duplex(struct snd_motu *motu);
15371c37977STakashi Sakamoto int snd_motu_stream_lock_try(struct snd_motu *motu);
15471c37977STakashi Sakamoto void snd_motu_stream_lock_release(struct snd_motu *motu);
1554638ec6eSTakashi Sakamoto 
1564638ec6eSTakashi Sakamoto void snd_motu_proc_init(struct snd_motu *motu);
157dd49b2d1STakashi Sakamoto 
158dd49b2d1STakashi Sakamoto int snd_motu_create_pcm_devices(struct snd_motu *motu);
1599e796e7dSTakashi Sakamoto 
1609e796e7dSTakashi Sakamoto int snd_motu_create_midi_devices(struct snd_motu *motu);
16171c37977STakashi Sakamoto 
16271c37977STakashi Sakamoto int snd_motu_create_hwdep_device(struct snd_motu *motu);
163ff222b7eSTakashi Sakamoto 
164ff222b7eSTakashi Sakamoto int snd_motu_protocol_v2_get_clock_rate(struct snd_motu *motu,
165ff222b7eSTakashi Sakamoto 					unsigned int *rate);
166ff222b7eSTakashi Sakamoto int snd_motu_protocol_v2_set_clock_rate(struct snd_motu *motu,
167ff222b7eSTakashi Sakamoto 					unsigned int rate);
168ff222b7eSTakashi Sakamoto int snd_motu_protocol_v2_get_clock_source(struct snd_motu *motu,
169ff222b7eSTakashi Sakamoto 					  enum snd_motu_clock_source *src);
170ff222b7eSTakashi Sakamoto int snd_motu_protocol_v2_switch_fetching_mode(struct snd_motu *motu,
171ff222b7eSTakashi Sakamoto 					      bool enable);
172ff222b7eSTakashi Sakamoto int snd_motu_protocol_v2_cache_packet_formats(struct snd_motu *motu);
173ff222b7eSTakashi Sakamoto 
174ff222b7eSTakashi Sakamoto int snd_motu_protocol_v3_get_clock_rate(struct snd_motu *motu,
175ff222b7eSTakashi Sakamoto 					unsigned int *rate);
176ff222b7eSTakashi Sakamoto int snd_motu_protocol_v3_set_clock_rate(struct snd_motu *motu,
177ff222b7eSTakashi Sakamoto 					unsigned int rate);
178ff222b7eSTakashi Sakamoto int snd_motu_protocol_v3_get_clock_source(struct snd_motu *motu,
179ff222b7eSTakashi Sakamoto 					  enum snd_motu_clock_source *src);
180ff222b7eSTakashi Sakamoto int snd_motu_protocol_v3_switch_fetching_mode(struct snd_motu *motu,
181ff222b7eSTakashi Sakamoto 					      bool enable);
182ff222b7eSTakashi Sakamoto int snd_motu_protocol_v3_cache_packet_formats(struct snd_motu *motu);
183ff222b7eSTakashi Sakamoto 
184ff222b7eSTakashi Sakamoto static inline int snd_motu_protocol_get_clock_rate(struct snd_motu *motu,
185ff222b7eSTakashi Sakamoto 						   unsigned int *rate)
186ff222b7eSTakashi Sakamoto {
187ff222b7eSTakashi Sakamoto 	if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
188ff222b7eSTakashi Sakamoto 		return snd_motu_protocol_v2_get_clock_rate(motu, rate);
189ff222b7eSTakashi Sakamoto 	else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
190ff222b7eSTakashi Sakamoto 		return snd_motu_protocol_v3_get_clock_rate(motu, rate);
191ff222b7eSTakashi Sakamoto 	else
192ff222b7eSTakashi Sakamoto 		return -ENXIO;
193ff222b7eSTakashi Sakamoto }
194ff222b7eSTakashi Sakamoto 
195ff222b7eSTakashi Sakamoto static inline int snd_motu_protocol_set_clock_rate(struct snd_motu *motu,
196ff222b7eSTakashi Sakamoto 						   unsigned int rate)
197ff222b7eSTakashi Sakamoto {
198ff222b7eSTakashi Sakamoto 	if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
199ff222b7eSTakashi Sakamoto 		return snd_motu_protocol_v2_set_clock_rate(motu, rate);
200ff222b7eSTakashi Sakamoto 	else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
201ff222b7eSTakashi Sakamoto 		return snd_motu_protocol_v3_set_clock_rate(motu, rate);
202ff222b7eSTakashi Sakamoto 	else
203ff222b7eSTakashi Sakamoto 		return -ENXIO;
204ff222b7eSTakashi Sakamoto }
205ff222b7eSTakashi Sakamoto 
206ff222b7eSTakashi Sakamoto static inline int snd_motu_protocol_get_clock_source(struct snd_motu *motu,
207ff222b7eSTakashi Sakamoto 					enum snd_motu_clock_source *source)
208ff222b7eSTakashi Sakamoto {
209ff222b7eSTakashi Sakamoto 	if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
210ff222b7eSTakashi Sakamoto 		return snd_motu_protocol_v2_get_clock_source(motu, source);
211ff222b7eSTakashi Sakamoto 	else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
212ff222b7eSTakashi Sakamoto 		return snd_motu_protocol_v3_get_clock_source(motu, source);
213ff222b7eSTakashi Sakamoto 	else
214ff222b7eSTakashi Sakamoto 		return -ENXIO;
215ff222b7eSTakashi Sakamoto }
216ff222b7eSTakashi Sakamoto 
217ff222b7eSTakashi Sakamoto static inline int snd_motu_protocol_switch_fetching_mode(struct snd_motu *motu,
218ff222b7eSTakashi Sakamoto 							 bool enable)
219ff222b7eSTakashi Sakamoto {
220ff222b7eSTakashi Sakamoto 	if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
221ff222b7eSTakashi Sakamoto 		return snd_motu_protocol_v2_switch_fetching_mode(motu, enable);
222ff222b7eSTakashi Sakamoto 	else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
223ff222b7eSTakashi Sakamoto 		return snd_motu_protocol_v3_switch_fetching_mode(motu, enable);
224ff222b7eSTakashi Sakamoto 	else
225ff222b7eSTakashi Sakamoto 		return -ENXIO;
226ff222b7eSTakashi Sakamoto }
227ff222b7eSTakashi Sakamoto 
228ff222b7eSTakashi Sakamoto static inline int snd_motu_protocol_cache_packet_formats(struct snd_motu *motu)
229ff222b7eSTakashi Sakamoto {
230ff222b7eSTakashi Sakamoto 	if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
231ff222b7eSTakashi Sakamoto 		return snd_motu_protocol_v2_cache_packet_formats(motu);
232ff222b7eSTakashi Sakamoto 	else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
233ff222b7eSTakashi Sakamoto 		return snd_motu_protocol_v3_cache_packet_formats(motu);
234ff222b7eSTakashi Sakamoto 	else
235ff222b7eSTakashi Sakamoto 		return -ENXIO;
236ff222b7eSTakashi Sakamoto }
237ff222b7eSTakashi Sakamoto 
2386c3cef48STakashi Sakamoto #endif
239