summaryrefslogtreecommitdiffstats
path: root/sound/firewire/motu
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2019-03-17 03:50:24 -0400
committerTakashi Iwai <tiwai@suse.de>2019-03-18 09:50:16 -0400
commit35033d8cb71b4dd4fa8d8d28a534af1ee921b9a0 (patch)
tree4221762bf1487d95124c1e41bd302661e304c496 /sound/firewire/motu
parentb3f5c0f3333b44107d5e6924e428a2dfe8d47c82 (diff)
ALSA: firewire-motu: add support MOTU 8pre FireWire
This commit adds support for MOTU 8pre FireWire, which was shipped 2007 and nowadays already discontinued. Userspace applications can transmit and receive PCM frames and MIDI messages for this model via ALSA PCM interface and RawMidi/Sequencer interfaces. Like the other models of MOTU FireWire series, this model has many quirks in its CIP. At first, data channels for two pairs of optical interfaces. At lower sampling transmission frequency, i.e. 44.1 and 48.0 kHz, one pair is available for ADAT data, thus 8 data chunks are transferred by CIP. At middle sampling transmission frequency, i.e. 88.2 and 96.0 kHz, two pairs are available to keep 8 chunks for ADAT data, thus CIP still includes 8 data chunks. Apart from data chunks for optical interface, CIP includes fixed number of data chunks. In tx stream, two chunks for status message, eight chunks for samples from analog 1-8 input, two chunks for mix-return. In rx stream, two chunks for control message, two chunks for main 1-2 output, two chunks for phone 1-2 output, two chunks for dummy 1-2. CIP header in tx stream includes quirks for its dbs and dbc fields. The value of dbs field is fixed to 0x13, against its actual size. The value of dbc field is firstly updated to 0x07 from zero, then it's incremented continuously according to actual number of data h blocks. Finally, the model has own bits to disable frame fetch. This commit uses several options to absorb the above quirks. $ python2 crpp < /sys/bus/firewire/devices/fw1/config_rom ROM header and bus information block ----------------------------------------------------------------- 400 0410b57d bus_info_length 4, crc_length 16, crc 46461 404 31333934 bus_name "1394" 408 20001000 irmc 0, cmc 0, isc 1, bmc 0, cyc_clk_acc 0, max_rec 1 (4) 40c 0001f200 company_id 0001f2 | 410 00083dfb device_id 0000083dfb | EUI-64 0001f20000083dfb root directory ----------------------------------------------------------------- 414 0004c65c directory_length 4, crc 50780 418 030001f2 vendor 41c 0c0083c0 node capabilities per IEEE 1394 420 8d000006 --> eui-64 leaf at 438 424 d1000001 --> unit directory at 428 unit directory at 428 ----------------------------------------------------------------- 428 0003991c directory_length 3, crc 39196 42c 120001f2 specifier id 430 1300000f version 434 17103800 model eui-64 leaf at 438 ----------------------------------------------------------------- 438 00022681 leaf_length 2, crc 9857 43c 0001f200 company_id 0001f2 | 440 00083dfb device_id 0000083dfb | EUI-64 0001f20000083dfb Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire/motu')
-rw-r--r--sound/firewire/motu/amdtp-motu.c6
-rw-r--r--sound/firewire/motu/motu-protocol-v2.c43
-rw-r--r--sound/firewire/motu/motu.c15
-rw-r--r--sound/firewire/motu/motu.h1
4 files changed, 53 insertions, 12 deletions
diff --git a/sound/firewire/motu/amdtp-motu.c b/sound/firewire/motu/amdtp-motu.c
index 6c9b743ea74b..cb0c967dea63 100644
--- a/sound/firewire/motu/amdtp-motu.c
+++ b/sound/firewire/motu/amdtp-motu.c
@@ -412,6 +412,12 @@ int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit,
412 CIP_HEADER_WITHOUT_EOH; 412 CIP_HEADER_WITHOUT_EOH;
413 fmt = CIP_FMT_MOTU_TX_V3; 413 fmt = CIP_FMT_MOTU_TX_V3;
414 } 414 }
415
416 if (protocol == &snd_motu_protocol_v2) {
417 // 8pre has some quirks.
418 flags |= CIP_WRONG_DBS |
419 CIP_SKIP_DBC_ZERO_CHECK;
420 }
415 } else { 421 } else {
416 process_data_blocks = process_rx_data_blocks; 422 process_data_blocks = process_rx_data_blocks;
417 flags |= CIP_DBC_IS_END_EVENT; 423 flags |= CIP_DBC_IS_END_EVENT;
diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c
index 453fc29fade7..848fffe7387e 100644
--- a/sound/firewire/motu/motu-protocol-v2.c
+++ b/sound/firewire/motu/motu-protocol-v2.c
@@ -15,6 +15,8 @@
15#define V2_CLOCK_SRC_SHIFT 0 15#define V2_CLOCK_SRC_SHIFT 0
16#define V2_CLOCK_TRAVELER_FETCH_DISABLE 0x04000000 16#define V2_CLOCK_TRAVELER_FETCH_DISABLE 0x04000000
17#define V2_CLOCK_TRAVELER_FETCH_ENABLE 0x03000000 17#define V2_CLOCK_TRAVELER_FETCH_ENABLE 0x03000000
18#define V2_CLOCK_8PRE_FETCH_DISABLE 0x02000000
19#define V2_CLOCK_8PRE_FETCH_ENABLE 0x00000000
18 20
19#define V2_IN_OUT_CONF_OFFSET 0x0c04 21#define V2_IN_OUT_CONF_OFFSET 0x0c04
20#define V2_OPT_OUT_IFACE_MASK 0x00000c00 22#define V2_OPT_OUT_IFACE_MASK 0x00000c00
@@ -132,20 +134,31 @@ static int v2_switch_fetching_mode(struct snd_motu *motu, bool enable)
132 u32 data; 134 u32 data;
133 int err = 0; 135 int err = 0;
134 136
135 if (motu->spec == &snd_motu_spec_traveler) { 137 if (motu->spec == &snd_motu_spec_traveler ||
138 motu->spec == &snd_motu_spec_8pre) {
136 err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET, 139 err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET,
137 &reg, sizeof(reg)); 140 &reg, sizeof(reg));
138 if (err < 0) 141 if (err < 0)
139 return err; 142 return err;
140 data = be32_to_cpu(reg); 143 data = be32_to_cpu(reg);
141 144
142 data &= ~(V2_CLOCK_TRAVELER_FETCH_DISABLE | 145 if (motu->spec == &snd_motu_spec_traveler) {
143 V2_CLOCK_TRAVELER_FETCH_ENABLE); 146 data &= ~(V2_CLOCK_TRAVELER_FETCH_DISABLE |
144 147 V2_CLOCK_TRAVELER_FETCH_ENABLE);
145 if (enable) 148
146 data |= V2_CLOCK_TRAVELER_FETCH_ENABLE; 149 if (enable)
147 else 150 data |= V2_CLOCK_TRAVELER_FETCH_ENABLE;
148 data |= V2_CLOCK_TRAVELER_FETCH_DISABLE; 151 else
152 data |= V2_CLOCK_TRAVELER_FETCH_DISABLE;
153 } else if (motu->spec == &snd_motu_spec_8pre) {
154 data &= ~(V2_CLOCK_8PRE_FETCH_DISABLE |
155 V2_CLOCK_8PRE_FETCH_ENABLE);
156
157 if (enable)
158 data |= V2_CLOCK_8PRE_FETCH_DISABLE;
159 else
160 data |= V2_CLOCK_8PRE_FETCH_ENABLE;
161 }
149 162
150 reg = cpu_to_be32(data); 163 reg = cpu_to_be32(data);
151 err = snd_motu_transaction_write(motu, V2_CLOCK_STATUS_OFFSET, 164 err = snd_motu_transaction_write(motu, V2_CLOCK_STATUS_OFFSET,
@@ -220,10 +233,16 @@ static void calculate_differed_part(struct snd_motu_packet_format *formats,
220 * interfaces. 233 * interfaces.
221 */ 234 */
222 data = (data & mask) >> shift; 235 data = (data & mask) >> shift;
223 if ((flags & SND_MOTU_SPEC_HAS_OPT_IFACE_A) && 236 if (data == V2_OPT_IFACE_MODE_ADAT) {
224 data == V2_OPT_IFACE_MODE_ADAT) { 237 if (flags & SND_MOTU_SPEC_HAS_OPT_IFACE_A) {
225 pcm_chunks[0] += 8; 238 pcm_chunks[0] += 8;
226 pcm_chunks[1] += 4; 239 pcm_chunks[1] += 4;
240 }
241 // 8pre has two sets of optical interface and doesn't reduce
242 // chunks for ADAT signals.
243 if (flags & SND_MOTU_SPEC_HAS_OPT_IFACE_B) {
244 pcm_chunks[1] += 4;
245 }
227 } 246 }
228 247
229 /* At mode x4, no data chunks are supported in this part. */ 248 /* At mode x4, no data chunks are supported in this part. */
diff --git a/sound/firewire/motu/motu.c b/sound/firewire/motu/motu.c
index 513291ba0ab0..201539d4488c 100644
--- a/sound/firewire/motu/motu.c
+++ b/sound/firewire/motu/motu.c
@@ -203,6 +203,20 @@ const struct snd_motu_spec snd_motu_spec_traveler = {
203 .analog_out_ports = 8, 203 .analog_out_ports = 8,
204}; 204};
205 205
206const struct snd_motu_spec snd_motu_spec_8pre = {
207 .name = "8pre",
208 .protocol = &snd_motu_protocol_v2,
209 // In tx, use coax chunks for mix-return 1/2. In rx, use coax chunks for
210 // dummy 1/2.
211 .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 |
212 SND_MOTU_SPEC_HAS_OPT_IFACE_A |
213 SND_MOTU_SPEC_HAS_OPT_IFACE_B |
214 SND_MOTU_SPEC_RX_MIDI_2ND_Q |
215 SND_MOTU_SPEC_TX_MIDI_2ND_Q,
216 .analog_in_ports = 8,
217 .analog_out_ports = 2,
218};
219
206static const struct snd_motu_spec motu_828mk3 = { 220static const struct snd_motu_spec motu_828mk3 = {
207 .name = "828mk3", 221 .name = "828mk3",
208 .protocol = &snd_motu_protocol_v3, 222 .protocol = &snd_motu_protocol_v3,
@@ -248,6 +262,7 @@ static const struct snd_motu_spec motu_audio_express = {
248static const struct ieee1394_device_id motu_id_table[] = { 262static const struct ieee1394_device_id motu_id_table[] = {
249 SND_MOTU_DEV_ENTRY(0x000003, &motu_828mk2), 263 SND_MOTU_DEV_ENTRY(0x000003, &motu_828mk2),
250 SND_MOTU_DEV_ENTRY(0x000009, &snd_motu_spec_traveler), 264 SND_MOTU_DEV_ENTRY(0x000009, &snd_motu_spec_traveler),
265 SND_MOTU_DEV_ENTRY(0x00000f, &snd_motu_spec_8pre),
251 SND_MOTU_DEV_ENTRY(0x000015, &motu_828mk3), /* FireWire only. */ 266 SND_MOTU_DEV_ENTRY(0x000015, &motu_828mk3), /* FireWire only. */
252 SND_MOTU_DEV_ENTRY(0x000035, &motu_828mk3), /* Hybrid. */ 267 SND_MOTU_DEV_ENTRY(0x000035, &motu_828mk3), /* Hybrid. */
253 SND_MOTU_DEV_ENTRY(0x000033, &motu_audio_express), 268 SND_MOTU_DEV_ENTRY(0x000033, &motu_audio_express),
diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h
index fd5327d30ab1..1cd112be7dad 100644
--- a/sound/firewire/motu/motu.h
+++ b/sound/firewire/motu/motu.h
@@ -130,6 +130,7 @@ extern const struct snd_motu_protocol snd_motu_protocol_v2;
130extern const struct snd_motu_protocol snd_motu_protocol_v3; 130extern const struct snd_motu_protocol snd_motu_protocol_v3;
131 131
132extern const struct snd_motu_spec snd_motu_spec_traveler; 132extern const struct snd_motu_spec snd_motu_spec_traveler;
133extern const struct snd_motu_spec snd_motu_spec_8pre;
133 134
134int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, 135int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit,
135 enum amdtp_stream_direction dir, 136 enum amdtp_stream_direction dir,