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