xref: /linux/sound/firewire/motu/motu.h (revision dfbaa4dc11eb93e3662dcefbf00a14235c4c1e8e)
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;
3959f6482cSTakashi Sakamoto 	unsigned char fixed_part_pcm_chunks[3];
4059f6482cSTakashi Sakamoto 	unsigned char differed_part_pcm_chunks[3];
4159f6482cSTakashi Sakamoto };
4259f6482cSTakashi Sakamoto 
436c3cef48STakashi Sakamoto struct snd_motu {
446c3cef48STakashi Sakamoto 	struct snd_card *card;
456c3cef48STakashi Sakamoto 	struct fw_unit *unit;
466c3cef48STakashi Sakamoto 	struct mutex mutex;
479e796e7dSTakashi Sakamoto 	spinlock_t lock;
488865a31eSTakashi Sakamoto 
498865a31eSTakashi Sakamoto 	bool registered;
508865a31eSTakashi Sakamoto 	struct delayed_work dwork;
515e03c33eSTakashi Sakamoto 
525e03c33eSTakashi Sakamoto 	/* Model dependent information. */
535e03c33eSTakashi Sakamoto 	const struct snd_motu_spec *spec;
5459f6482cSTakashi Sakamoto 
5559f6482cSTakashi Sakamoto 	/* For packet streaming */
5659f6482cSTakashi Sakamoto 	struct snd_motu_packet_format tx_packet_formats;
5759f6482cSTakashi Sakamoto 	struct snd_motu_packet_format rx_packet_formats;
584641c939STakashi Sakamoto 	struct amdtp_stream tx_stream;
594641c939STakashi Sakamoto 	struct amdtp_stream rx_stream;
609b2bb4f2STakashi Sakamoto 	struct fw_iso_resources tx_resources;
619b2bb4f2STakashi Sakamoto 	struct fw_iso_resources rx_resources;
6218f26034STakashi Sakamoto 	unsigned int substreams_counter;
632e76701bSTakashi Sakamoto 
642e76701bSTakashi Sakamoto 	/* For notification. */
652e76701bSTakashi Sakamoto 	struct fw_address_handler async_handler;
662e76701bSTakashi Sakamoto 	u32 msg;
6771c37977STakashi Sakamoto 
6871c37977STakashi Sakamoto 	/* For uapi */
6971c37977STakashi Sakamoto 	int dev_lock_count;
7071c37977STakashi Sakamoto 	bool dev_lock_changed;
7171c37977STakashi Sakamoto 	wait_queue_head_t hwdep_wait;
72ccc6c1b0STakashi Sakamoto 
73ccc6c1b0STakashi Sakamoto 	struct amdtp_domain domain;
745e03c33eSTakashi Sakamoto };
755e03c33eSTakashi Sakamoto 
765e03c33eSTakashi Sakamoto enum snd_motu_spec_flags {
775e03c33eSTakashi Sakamoto 	SND_MOTU_SPEC_SUPPORT_CLOCK_X2	= 0x0001,
785e03c33eSTakashi Sakamoto 	SND_MOTU_SPEC_SUPPORT_CLOCK_X4	= 0x0002,
795e03c33eSTakashi Sakamoto 	SND_MOTU_SPEC_TX_MICINST_CHUNK	= 0x0004,
805e03c33eSTakashi Sakamoto 	SND_MOTU_SPEC_TX_RETURN_CHUNK	= 0x0008,
815e03c33eSTakashi Sakamoto 	SND_MOTU_SPEC_TX_REVERB_CHUNK	= 0x0010,
8206ac0b6fSTakashi Sakamoto 	SND_MOTU_SPEC_HAS_AESEBU_IFACE	= 0x0020,
835e03c33eSTakashi Sakamoto 	SND_MOTU_SPEC_HAS_OPT_IFACE_A	= 0x0040,
845e03c33eSTakashi Sakamoto 	SND_MOTU_SPEC_HAS_OPT_IFACE_B	= 0x0080,
858b460c76STakashi Sakamoto 	SND_MOTU_SPEC_RX_MIDI_2ND_Q	= 0x0100,
868b460c76STakashi Sakamoto 	SND_MOTU_SPEC_RX_MIDI_3RD_Q	= 0x0200,
878b460c76STakashi Sakamoto 	SND_MOTU_SPEC_TX_MIDI_2ND_Q	= 0x0400,
888b460c76STakashi Sakamoto 	SND_MOTU_SPEC_TX_MIDI_3RD_Q	= 0x0800,
892644df63STakashi Sakamoto 	SND_MOTU_SPEC_RX_SEPARATED_MAIN	= 0x1000,
905e03c33eSTakashi Sakamoto };
915e03c33eSTakashi Sakamoto 
9259f6482cSTakashi Sakamoto #define SND_MOTU_CLOCK_RATE_COUNT	6
9359f6482cSTakashi Sakamoto extern const unsigned int snd_motu_clock_rates[SND_MOTU_CLOCK_RATE_COUNT];
9459f6482cSTakashi Sakamoto 
9559f6482cSTakashi Sakamoto enum snd_motu_clock_source {
9659f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_INTERNAL,
9759f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_ADAT_ON_DSUB,
9859f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT,
9959f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_A,
10059f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_B,
10159f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT,
10259f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_A,
10359f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_B,
10459f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX,
10559f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_AESEBU_ON_XLR,
10659f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC,
1073f58f004STakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_SPH,
10859f6482cSTakashi Sakamoto 	SND_MOTU_CLOCK_SOURCE_UNKNOWN,
10959f6482cSTakashi Sakamoto };
11059f6482cSTakashi Sakamoto 
11161d79c70STakashi Sakamoto enum snd_motu_protocol_version {
11261d79c70STakashi Sakamoto 	SND_MOTU_PROTOCOL_V2,
11361d79c70STakashi Sakamoto 	SND_MOTU_PROTOCOL_V3,
11461d79c70STakashi Sakamoto };
11561d79c70STakashi Sakamoto 
1165e03c33eSTakashi Sakamoto struct snd_motu_spec {
1175e03c33eSTakashi Sakamoto 	const char *const name;
11861d79c70STakashi Sakamoto 	enum snd_motu_protocol_version protocol_version;
1195e03c33eSTakashi Sakamoto 	enum snd_motu_spec_flags flags;
1205e03c33eSTakashi Sakamoto 
121*dfbaa4dcSTakashi Sakamoto 	unsigned char tx_fixed_pcm_chunks[3];
122*dfbaa4dcSTakashi Sakamoto 	unsigned char rx_fixed_pcm_chunks[3];
123*dfbaa4dcSTakashi Sakamoto 
1245e03c33eSTakashi Sakamoto 	unsigned char analog_in_ports;
1255e03c33eSTakashi Sakamoto 	unsigned char analog_out_ports;
1266c3cef48STakashi Sakamoto };
1276c3cef48STakashi Sakamoto 
128bd107372STakashi Sakamoto extern const struct snd_motu_spec snd_motu_spec_828mk2;
1290a7c7b47STakashi Sakamoto extern const struct snd_motu_spec snd_motu_spec_traveler;
1300a7c7b47STakashi Sakamoto extern const struct snd_motu_spec snd_motu_spec_ultralite;
1310a7c7b47STakashi Sakamoto extern const struct snd_motu_spec snd_motu_spec_8pre;
1326c5e1ac0STakashi Sakamoto 
133c806a0e2STakashi Sakamoto extern const struct snd_motu_spec snd_motu_spec_828mk3;
134c806a0e2STakashi Sakamoto extern const struct snd_motu_spec snd_motu_spec_audio_express;
135c806a0e2STakashi Sakamoto extern const struct snd_motu_spec snd_motu_spec_4pre;
136c806a0e2STakashi Sakamoto 
1374641c939STakashi Sakamoto int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit,
1384641c939STakashi Sakamoto 		    enum amdtp_stream_direction dir,
13961d79c70STakashi Sakamoto 		    const struct snd_motu_spec *spec);
1404641c939STakashi Sakamoto int amdtp_motu_set_parameters(struct amdtp_stream *s, unsigned int rate,
1419e796e7dSTakashi Sakamoto 			      unsigned int midi_ports,
1424641c939STakashi Sakamoto 			      struct snd_motu_packet_format *formats);
1434641c939STakashi Sakamoto int amdtp_motu_add_pcm_hw_constraints(struct amdtp_stream *s,
1444641c939STakashi Sakamoto 				      struct snd_pcm_runtime *runtime);
1459e796e7dSTakashi Sakamoto void amdtp_motu_midi_trigger(struct amdtp_stream *s, unsigned int port,
1469e796e7dSTakashi Sakamoto 			     struct snd_rawmidi_substream *midi);
1472e76701bSTakashi Sakamoto 
1482e76701bSTakashi Sakamoto int snd_motu_transaction_read(struct snd_motu *motu, u32 offset, __be32 *reg,
1492e76701bSTakashi Sakamoto 			      size_t size);
1502e76701bSTakashi Sakamoto int snd_motu_transaction_write(struct snd_motu *motu, u32 offset, __be32 *reg,
1512e76701bSTakashi Sakamoto 			       size_t size);
1522e76701bSTakashi Sakamoto int snd_motu_transaction_register(struct snd_motu *motu);
1532e76701bSTakashi Sakamoto int snd_motu_transaction_reregister(struct snd_motu *motu);
1542e76701bSTakashi Sakamoto void snd_motu_transaction_unregister(struct snd_motu *motu);
1559b2bb4f2STakashi Sakamoto 
1569b2bb4f2STakashi Sakamoto int snd_motu_stream_init_duplex(struct snd_motu *motu);
1579b2bb4f2STakashi Sakamoto void snd_motu_stream_destroy_duplex(struct snd_motu *motu);
1588b460c76STakashi Sakamoto int snd_motu_stream_cache_packet_formats(struct snd_motu *motu);
1590d39cd0eSTakashi Sakamoto int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate,
1600f5482e7STakashi Sakamoto 				   unsigned int frames_per_period,
1610f5482e7STakashi Sakamoto 				   unsigned int frames_per_buffer);
1628edc56ecSTakashi Sakamoto int snd_motu_stream_start_duplex(struct snd_motu *motu);
1639b2bb4f2STakashi Sakamoto void snd_motu_stream_stop_duplex(struct snd_motu *motu);
16471c37977STakashi Sakamoto int snd_motu_stream_lock_try(struct snd_motu *motu);
16571c37977STakashi Sakamoto void snd_motu_stream_lock_release(struct snd_motu *motu);
1664638ec6eSTakashi Sakamoto 
1674638ec6eSTakashi Sakamoto void snd_motu_proc_init(struct snd_motu *motu);
168dd49b2d1STakashi Sakamoto 
169dd49b2d1STakashi Sakamoto int snd_motu_create_pcm_devices(struct snd_motu *motu);
1709e796e7dSTakashi Sakamoto 
1719e796e7dSTakashi Sakamoto int snd_motu_create_midi_devices(struct snd_motu *motu);
17271c37977STakashi Sakamoto 
17371c37977STakashi Sakamoto int snd_motu_create_hwdep_device(struct snd_motu *motu);
174ff222b7eSTakashi Sakamoto 
175ff222b7eSTakashi Sakamoto int snd_motu_protocol_v2_get_clock_rate(struct snd_motu *motu,
176ff222b7eSTakashi Sakamoto 					unsigned int *rate);
177ff222b7eSTakashi Sakamoto int snd_motu_protocol_v2_set_clock_rate(struct snd_motu *motu,
178ff222b7eSTakashi Sakamoto 					unsigned int rate);
179ff222b7eSTakashi Sakamoto int snd_motu_protocol_v2_get_clock_source(struct snd_motu *motu,
180ff222b7eSTakashi Sakamoto 					  enum snd_motu_clock_source *src);
181ff222b7eSTakashi Sakamoto int snd_motu_protocol_v2_switch_fetching_mode(struct snd_motu *motu,
182ff222b7eSTakashi Sakamoto 					      bool enable);
183ff222b7eSTakashi Sakamoto int snd_motu_protocol_v2_cache_packet_formats(struct snd_motu *motu);
184ff222b7eSTakashi Sakamoto 
185ff222b7eSTakashi Sakamoto int snd_motu_protocol_v3_get_clock_rate(struct snd_motu *motu,
186ff222b7eSTakashi Sakamoto 					unsigned int *rate);
187ff222b7eSTakashi Sakamoto int snd_motu_protocol_v3_set_clock_rate(struct snd_motu *motu,
188ff222b7eSTakashi Sakamoto 					unsigned int rate);
189ff222b7eSTakashi Sakamoto int snd_motu_protocol_v3_get_clock_source(struct snd_motu *motu,
190ff222b7eSTakashi Sakamoto 					  enum snd_motu_clock_source *src);
191ff222b7eSTakashi Sakamoto int snd_motu_protocol_v3_switch_fetching_mode(struct snd_motu *motu,
192ff222b7eSTakashi Sakamoto 					      bool enable);
193ff222b7eSTakashi Sakamoto int snd_motu_protocol_v3_cache_packet_formats(struct snd_motu *motu);
194ff222b7eSTakashi Sakamoto 
195ff222b7eSTakashi Sakamoto static inline int snd_motu_protocol_get_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_get_clock_rate(motu, rate);
200ff222b7eSTakashi Sakamoto 	else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
201ff222b7eSTakashi Sakamoto 		return snd_motu_protocol_v3_get_clock_rate(motu, rate);
202ff222b7eSTakashi Sakamoto 	else
203ff222b7eSTakashi Sakamoto 		return -ENXIO;
204ff222b7eSTakashi Sakamoto }
205ff222b7eSTakashi Sakamoto 
206ff222b7eSTakashi Sakamoto static inline int snd_motu_protocol_set_clock_rate(struct snd_motu *motu,
207ff222b7eSTakashi Sakamoto 						   unsigned int rate)
208ff222b7eSTakashi Sakamoto {
209ff222b7eSTakashi Sakamoto 	if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
210ff222b7eSTakashi Sakamoto 		return snd_motu_protocol_v2_set_clock_rate(motu, rate);
211ff222b7eSTakashi Sakamoto 	else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
212ff222b7eSTakashi Sakamoto 		return snd_motu_protocol_v3_set_clock_rate(motu, rate);
213ff222b7eSTakashi Sakamoto 	else
214ff222b7eSTakashi Sakamoto 		return -ENXIO;
215ff222b7eSTakashi Sakamoto }
216ff222b7eSTakashi Sakamoto 
217ff222b7eSTakashi Sakamoto static inline int snd_motu_protocol_get_clock_source(struct snd_motu *motu,
218ff222b7eSTakashi Sakamoto 					enum snd_motu_clock_source *source)
219ff222b7eSTakashi Sakamoto {
220ff222b7eSTakashi Sakamoto 	if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
221ff222b7eSTakashi Sakamoto 		return snd_motu_protocol_v2_get_clock_source(motu, source);
222ff222b7eSTakashi Sakamoto 	else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
223ff222b7eSTakashi Sakamoto 		return snd_motu_protocol_v3_get_clock_source(motu, source);
224ff222b7eSTakashi Sakamoto 	else
225ff222b7eSTakashi Sakamoto 		return -ENXIO;
226ff222b7eSTakashi Sakamoto }
227ff222b7eSTakashi Sakamoto 
228ff222b7eSTakashi Sakamoto static inline int snd_motu_protocol_switch_fetching_mode(struct snd_motu *motu,
229ff222b7eSTakashi Sakamoto 							 bool enable)
230ff222b7eSTakashi Sakamoto {
231ff222b7eSTakashi Sakamoto 	if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
232ff222b7eSTakashi Sakamoto 		return snd_motu_protocol_v2_switch_fetching_mode(motu, enable);
233ff222b7eSTakashi Sakamoto 	else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
234ff222b7eSTakashi Sakamoto 		return snd_motu_protocol_v3_switch_fetching_mode(motu, enable);
235ff222b7eSTakashi Sakamoto 	else
236ff222b7eSTakashi Sakamoto 		return -ENXIO;
237ff222b7eSTakashi Sakamoto }
238ff222b7eSTakashi Sakamoto 
239ff222b7eSTakashi Sakamoto static inline int snd_motu_protocol_cache_packet_formats(struct snd_motu *motu)
240ff222b7eSTakashi Sakamoto {
241ff222b7eSTakashi Sakamoto 	if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V2)
242ff222b7eSTakashi Sakamoto 		return snd_motu_protocol_v2_cache_packet_formats(motu);
243ff222b7eSTakashi Sakamoto 	else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3)
244ff222b7eSTakashi Sakamoto 		return snd_motu_protocol_v3_cache_packet_formats(motu);
245ff222b7eSTakashi Sakamoto 	else
246ff222b7eSTakashi Sakamoto 		return -ENXIO;
247ff222b7eSTakashi Sakamoto }
248ff222b7eSTakashi Sakamoto 
2496c3cef48STakashi Sakamoto #endif
250