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