Thomas Gleixner | da607e1 | 2019-05-29 16:57:59 -0700 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Takashi Sakamoto | 17c4e5e | 2017-03-31 22:05:59 +0900 | [diff] [blame] | 2 | /* |
| 3 | * ff.h - a part of driver for RME Fireface series |
| 4 | * |
| 5 | * Copyright (c) 2015-2017 Takashi Sakamoto |
Takashi Sakamoto | 17c4e5e | 2017-03-31 22:05:59 +0900 | [diff] [blame] | 6 | */ |
| 7 | |
| 8 | #ifndef SOUND_FIREFACE_H_INCLUDED |
| 9 | #define SOUND_FIREFACE_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> |
| 18 | #include <linux/compat.h> |
Takashi Sakamoto | f656edd | 2017-03-31 22:06:11 +0900 | [diff] [blame] | 19 | #include <linux/sched/signal.h> |
Takashi Sakamoto | 17c4e5e | 2017-03-31 22:05:59 +0900 | [diff] [blame] | 20 | |
| 21 | #include <sound/core.h> |
Takashi Sakamoto | 53eb086 | 2017-03-31 22:06:02 +0900 | [diff] [blame] | 22 | #include <sound/info.h> |
Takashi Sakamoto | 1917429 | 2017-03-31 22:06:03 +0900 | [diff] [blame] | 23 | #include <sound/rawmidi.h> |
Takashi Sakamoto | 4b31643 | 2017-03-31 22:06:10 +0900 | [diff] [blame] | 24 | #include <sound/pcm.h> |
| 25 | #include <sound/pcm_params.h> |
Takashi Sakamoto | f656edd | 2017-03-31 22:06:11 +0900 | [diff] [blame] | 26 | #include <sound/hwdep.h> |
| 27 | #include <sound/firewire.h> |
Takashi Sakamoto | 17c4e5e | 2017-03-31 22:05:59 +0900 | [diff] [blame] | 28 | |
Takashi Sakamoto | 324540c | 2017-03-31 22:06:00 +0900 | [diff] [blame] | 29 | #include "../lib.h" |
Takashi Sakamoto | 6fb7db9 | 2017-03-31 22:06:08 +0900 | [diff] [blame] | 30 | #include "../amdtp-stream.h" |
Takashi Sakamoto | 75d6d89 | 2017-03-31 22:06:09 +0900 | [diff] [blame] | 31 | #include "../iso-resources.h" |
Takashi Sakamoto | 324540c | 2017-03-31 22:06:00 +0900 | [diff] [blame] | 32 | |
Takashi Sakamoto | 1917429 | 2017-03-31 22:06:03 +0900 | [diff] [blame] | 33 | #define SND_FF_MAXIMIM_MIDI_QUADS 9 |
| 34 | #define SND_FF_IN_MIDI_PORTS 2 |
| 35 | #define SND_FF_OUT_MIDI_PORTS 2 |
| 36 | |
Takashi Sakamoto | c52f232 | 2020-05-10 16:42:58 +0900 | [diff] [blame] | 37 | enum snd_ff_unit_version { |
| 38 | SND_FF_UNIT_VERSION_FF800 = 0x000001, |
| 39 | SND_FF_UNIT_VERSION_FF400 = 0x000002, |
Takashi Sakamoto | 1f65e66 | 2020-05-10 16:43:01 +0900 | [diff] [blame] | 40 | SND_FF_UNIT_VERSION_UFX = 0x000003, |
Takashi Sakamoto | c52f232 | 2020-05-10 16:42:58 +0900 | [diff] [blame] | 41 | SND_FF_UNIT_VERSION_UCX = 0x000004, |
Takashi Sakamoto | 062bb45 | 2020-05-10 16:43:00 +0900 | [diff] [blame] | 42 | SND_FF_UNIT_VERSION_802 = 0x000005, |
Takashi Sakamoto | c52f232 | 2020-05-10 16:42:58 +0900 | [diff] [blame] | 43 | }; |
| 44 | |
Takashi Sakamoto | 76ea468 | 2018-12-16 17:32:30 +0900 | [diff] [blame] | 45 | enum snd_ff_stream_mode { |
| 46 | SND_FF_STREAM_MODE_LOW = 0, |
| 47 | SND_FF_STREAM_MODE_MID, |
| 48 | SND_FF_STREAM_MODE_HIGH, |
| 49 | SND_FF_STREAM_MODE_COUNT, |
| 50 | }; |
| 51 | |
Takashi Sakamoto | 53eb086 | 2017-03-31 22:06:02 +0900 | [diff] [blame] | 52 | struct snd_ff_protocol; |
Takashi Sakamoto | ed90f91 | 2017-03-31 22:06:01 +0900 | [diff] [blame] | 53 | struct snd_ff_spec { |
Takashi Sakamoto | 76ea468 | 2018-12-16 17:32:30 +0900 | [diff] [blame] | 54 | const unsigned int pcm_capture_channels[SND_FF_STREAM_MODE_COUNT]; |
| 55 | const unsigned int pcm_playback_channels[SND_FF_STREAM_MODE_COUNT]; |
Takashi Sakamoto | ed90f91 | 2017-03-31 22:06:01 +0900 | [diff] [blame] | 56 | |
| 57 | unsigned int midi_in_ports; |
| 58 | unsigned int midi_out_ports; |
Takashi Sakamoto | 53eb086 | 2017-03-31 22:06:02 +0900 | [diff] [blame] | 59 | |
Takashi Sakamoto | 782fbec | 2017-08-22 22:58:15 +0900 | [diff] [blame] | 60 | const struct snd_ff_protocol *protocol; |
Takashi Sakamoto | 6d1ef1b | 2018-12-16 17:32:33 +0900 | [diff] [blame] | 61 | u64 midi_high_addr; |
Takashi Sakamoto | 9008967 | 2019-01-22 22:17:01 +0900 | [diff] [blame] | 62 | u8 midi_addr_range; |
Takashi Sakamoto | 481e09a | 2019-01-22 22:17:03 +0900 | [diff] [blame] | 63 | u64 midi_rx_addrs[SND_FF_OUT_MIDI_PORTS]; |
Takashi Sakamoto | ed90f91 | 2017-03-31 22:06:01 +0900 | [diff] [blame] | 64 | }; |
| 65 | |
Takashi Sakamoto | 17c4e5e | 2017-03-31 22:05:59 +0900 | [diff] [blame] | 66 | struct snd_ff { |
| 67 | struct snd_card *card; |
| 68 | struct fw_unit *unit; |
| 69 | struct mutex mutex; |
Takashi Sakamoto | ff2c293 | 2017-03-31 22:06:04 +0900 | [diff] [blame] | 70 | spinlock_t lock; |
Takashi Sakamoto | 324540c | 2017-03-31 22:06:00 +0900 | [diff] [blame] | 71 | |
Takashi Sakamoto | 782222b | 2020-05-10 16:42:59 +0900 | [diff] [blame] | 72 | enum snd_ff_unit_version unit_version; |
Takashi Sakamoto | ed90f91 | 2017-03-31 22:06:01 +0900 | [diff] [blame] | 73 | const struct snd_ff_spec *spec; |
Takashi Sakamoto | 1917429 | 2017-03-31 22:06:03 +0900 | [diff] [blame] | 74 | |
| 75 | /* To handle MIDI tx. */ |
| 76 | struct snd_rawmidi_substream *tx_midi_substreams[SND_FF_IN_MIDI_PORTS]; |
| 77 | struct fw_address_handler async_handler; |
| 78 | |
| 79 | /* TO handle MIDI rx. */ |
| 80 | struct snd_rawmidi_substream *rx_midi_substreams[SND_FF_OUT_MIDI_PORTS]; |
Takashi Sakamoto | f0f9f49 | 2019-01-22 22:17:05 +0900 | [diff] [blame] | 81 | bool on_sysex[SND_FF_OUT_MIDI_PORTS]; |
Takashi Sakamoto | 1917429 | 2017-03-31 22:06:03 +0900 | [diff] [blame] | 82 | __le32 msg_buf[SND_FF_OUT_MIDI_PORTS][SND_FF_MAXIMIM_MIDI_QUADS]; |
| 83 | struct work_struct rx_midi_work[SND_FF_OUT_MIDI_PORTS]; |
| 84 | struct fw_transaction transactions[SND_FF_OUT_MIDI_PORTS]; |
| 85 | ktime_t next_ktime[SND_FF_OUT_MIDI_PORTS]; |
| 86 | bool rx_midi_error[SND_FF_OUT_MIDI_PORTS]; |
| 87 | unsigned int rx_bytes[SND_FF_OUT_MIDI_PORTS]; |
Takashi Sakamoto | 75d6d89 | 2017-03-31 22:06:09 +0900 | [diff] [blame] | 88 | |
| 89 | unsigned int substreams_counter; |
| 90 | struct amdtp_stream tx_stream; |
| 91 | struct amdtp_stream rx_stream; |
| 92 | struct fw_iso_resources tx_resources; |
| 93 | struct fw_iso_resources rx_resources; |
Takashi Sakamoto | f656edd | 2017-03-31 22:06:11 +0900 | [diff] [blame] | 94 | |
| 95 | int dev_lock_count; |
| 96 | bool dev_lock_changed; |
| 97 | wait_queue_head_t hwdep_wait; |
Takashi Sakamoto | c9a9ce8 | 2019-08-04 15:21:37 +0900 | [diff] [blame] | 98 | |
| 99 | struct amdtp_domain domain; |
Takashi Sakamoto | c31909f | 2023-01-12 21:09:53 +0900 | [diff] [blame] | 100 | |
| 101 | void *msg_parser; |
Takashi Sakamoto | 17c4e5e | 2017-03-31 22:05:59 +0900 | [diff] [blame] | 102 | }; |
Takashi Sakamoto | 53eb086 | 2017-03-31 22:06:02 +0900 | [diff] [blame] | 103 | |
| 104 | enum snd_ff_clock_src { |
| 105 | SND_FF_CLOCK_SRC_INTERNAL, |
| 106 | SND_FF_CLOCK_SRC_SPDIF, |
Takashi Sakamoto | 5bfb841 | 2018-12-11 19:17:31 +0900 | [diff] [blame] | 107 | SND_FF_CLOCK_SRC_ADAT1, |
| 108 | SND_FF_CLOCK_SRC_ADAT2, |
Takashi Sakamoto | 53eb086 | 2017-03-31 22:06:02 +0900 | [diff] [blame] | 109 | SND_FF_CLOCK_SRC_WORD, |
| 110 | SND_FF_CLOCK_SRC_LTC, |
Takashi Sakamoto | 5bfb841 | 2018-12-11 19:17:31 +0900 | [diff] [blame] | 111 | /* TODO: perhaps TCO exists. */ |
Takashi Sakamoto | 53eb086 | 2017-03-31 22:06:02 +0900 | [diff] [blame] | 112 | }; |
| 113 | |
| 114 | struct snd_ff_protocol { |
Takashi Sakamoto | c31909f | 2023-01-12 21:09:53 +0900 | [diff] [blame] | 115 | size_t msg_parser_size; |
| 116 | bool (*has_msg)(struct snd_ff *ff); |
| 117 | long (*copy_msg_to_user)(struct snd_ff *ff, char __user *buf, long count); |
Takashi Sakamoto | 50c597c | 2023-01-12 21:09:49 +0900 | [diff] [blame] | 118 | void (*handle_msg)(struct snd_ff *ff, unsigned int offset, const __le32 *buf, |
Takashi Sakamoto | 4bdcb8d | 2023-01-12 21:09:50 +0900 | [diff] [blame] | 119 | size_t length, u32 tstamp); |
Takashi Sakamoto | 82b6297 | 2019-01-22 22:17:04 +0900 | [diff] [blame] | 120 | int (*fill_midi_msg)(struct snd_ff *ff, |
| 121 | struct snd_rawmidi_substream *substream, |
| 122 | unsigned int port); |
Takashi Sakamoto | b1d0cb0 | 2019-01-20 17:25:50 +0900 | [diff] [blame] | 123 | int (*get_clock)(struct snd_ff *ff, unsigned int *rate, |
| 124 | enum snd_ff_clock_src *src); |
Takashi Sakamoto | ae3053c2 | 2019-01-20 17:25:49 +0900 | [diff] [blame] | 125 | int (*switch_fetching_mode)(struct snd_ff *ff, bool enable); |
Takashi Sakamoto | 47b87c8 | 2019-06-02 16:12:52 +0900 | [diff] [blame] | 126 | int (*allocate_resources)(struct snd_ff *ff, unsigned int rate); |
Takashi Sakamoto | 53eb086 | 2017-03-31 22:06:02 +0900 | [diff] [blame] | 127 | int (*begin_session)(struct snd_ff *ff, unsigned int rate); |
| 128 | void (*finish_session)(struct snd_ff *ff); |
Takashi Sakamoto | e9e29cf | 2019-01-20 17:25:48 +0900 | [diff] [blame] | 129 | void (*dump_status)(struct snd_ff *ff, struct snd_info_buffer *buffer); |
Takashi Sakamoto | 53eb086 | 2017-03-31 22:06:02 +0900 | [diff] [blame] | 130 | }; |
| 131 | |
Takashi Sakamoto | a91f676 | 2018-12-11 19:17:35 +0900 | [diff] [blame] | 132 | extern const struct snd_ff_protocol snd_ff_protocol_ff800; |
Takashi Sakamoto | 782fbec | 2017-08-22 22:58:15 +0900 | [diff] [blame] | 133 | extern const struct snd_ff_protocol snd_ff_protocol_ff400; |
Takashi Sakamoto | fd1cc9d | 2019-01-20 17:25:53 +0900 | [diff] [blame] | 134 | extern const struct snd_ff_protocol snd_ff_protocol_latter; |
Takashi Sakamoto | 76fdb3a9 | 2017-03-31 22:06:12 +0900 | [diff] [blame] | 135 | |
Takashi Sakamoto | 1917429 | 2017-03-31 22:06:03 +0900 | [diff] [blame] | 136 | int snd_ff_transaction_register(struct snd_ff *ff); |
| 137 | int snd_ff_transaction_reregister(struct snd_ff *ff); |
| 138 | void snd_ff_transaction_unregister(struct snd_ff *ff); |
| 139 | |
Takashi Sakamoto | 6fb7db9 | 2017-03-31 22:06:08 +0900 | [diff] [blame] | 140 | int amdtp_ff_set_parameters(struct amdtp_stream *s, unsigned int rate, |
| 141 | unsigned int pcm_channels); |
| 142 | int amdtp_ff_add_pcm_hw_constraints(struct amdtp_stream *s, |
| 143 | struct snd_pcm_runtime *runtime); |
| 144 | int amdtp_ff_init(struct amdtp_stream *s, struct fw_unit *unit, |
| 145 | enum amdtp_stream_direction dir); |
| 146 | |
Takashi Sakamoto | 76ea468 | 2018-12-16 17:32:30 +0900 | [diff] [blame] | 147 | int snd_ff_stream_get_multiplier_mode(enum cip_sfc sfc, |
| 148 | enum snd_ff_stream_mode *mode); |
Takashi Sakamoto | 75d6d89 | 2017-03-31 22:06:09 +0900 | [diff] [blame] | 149 | int snd_ff_stream_init_duplex(struct snd_ff *ff); |
| 150 | void snd_ff_stream_destroy_duplex(struct snd_ff *ff); |
Takashi Sakamoto | 9d9ff58 | 2019-10-07 20:05:24 +0900 | [diff] [blame] | 151 | int snd_ff_stream_reserve_duplex(struct snd_ff *ff, unsigned int rate, |
Takashi Sakamoto | 4de3eb0 | 2019-10-18 00:54:21 +0900 | [diff] [blame] | 152 | unsigned int frames_per_period, |
| 153 | unsigned int frames_per_buffer); |
Takashi Sakamoto | 75d6d89 | 2017-03-31 22:06:09 +0900 | [diff] [blame] | 154 | int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate); |
| 155 | void snd_ff_stream_stop_duplex(struct snd_ff *ff); |
| 156 | void snd_ff_stream_update_duplex(struct snd_ff *ff); |
| 157 | |
Takashi Sakamoto | f656edd | 2017-03-31 22:06:11 +0900 | [diff] [blame] | 158 | void snd_ff_stream_lock_changed(struct snd_ff *ff); |
| 159 | int snd_ff_stream_lock_try(struct snd_ff *ff); |
| 160 | void snd_ff_stream_lock_release(struct snd_ff *ff); |
| 161 | |
Takashi Sakamoto | d3fc7aa | 2017-03-31 22:06:05 +0900 | [diff] [blame] | 162 | void snd_ff_proc_init(struct snd_ff *ff); |
Takashi Sakamoto | 4c4871a | 2019-01-20 17:25:52 +0900 | [diff] [blame] | 163 | const char *snd_ff_proc_get_clk_label(enum snd_ff_clock_src src); |
Takashi Sakamoto | d3fc7aa | 2017-03-31 22:06:05 +0900 | [diff] [blame] | 164 | |
Takashi Sakamoto | ff2c293 | 2017-03-31 22:06:04 +0900 | [diff] [blame] | 165 | int snd_ff_create_midi_devices(struct snd_ff *ff); |
| 166 | |
Takashi Sakamoto | 4b31643 | 2017-03-31 22:06:10 +0900 | [diff] [blame] | 167 | int snd_ff_create_pcm_devices(struct snd_ff *ff); |
| 168 | |
Takashi Sakamoto | f656edd | 2017-03-31 22:06:11 +0900 | [diff] [blame] | 169 | int snd_ff_create_hwdep_devices(struct snd_ff *ff); |
| 170 | |
Takashi Sakamoto | 17c4e5e | 2017-03-31 22:05:59 +0900 | [diff] [blame] | 171 | #endif |