541 lines · c
1// SPDX-License-Identifier: GPL-2.02// ff-protocol-latter.c - a part of driver for RME Fireface series3//4// Copyright (c) 2019 Takashi Sakamoto5 6#include <linux/delay.h>7 8#include "ff.h"9 10#define LATTER_STF 0xffff00000004ULL11#define LATTER_ISOC_CHANNELS 0xffff00000008ULL12#define LATTER_ISOC_START 0xffff0000000cULL13#define LATTER_FETCH_MODE 0xffff00000010ULL14#define LATTER_SYNC_STATUS 0x0000801c0000ULL15 16// The content of sync status register differs between models.17//18// Fireface UCX:19// 0xf0000000: (unidentified)20// 0x0f000000: effective rate of sampling clock21// 0x00f00000: detected rate of word clock on BNC interface22// 0x000f0000: detected rate of ADAT or S/PDIF on optical interface23// 0x0000f000: detected rate of S/PDIF on coaxial interface24// 0x00000e00: effective source of sampling clock25// 0x00000e00: Internal26// 0x00000800: (unidentified)27// 0x00000600: Word clock on BNC interface28// 0x00000400: ADAT on optical interface29// 0x00000200: S/PDIF on coaxial or optical interface30// 0x00000100: Optical interface is used for ADAT signal31// 0x00000080: (unidentified)32// 0x00000040: Synchronized to word clock on BNC interface33// 0x00000020: Synchronized to ADAT or S/PDIF on optical interface34// 0x00000010: Synchronized to S/PDIF on coaxial interface35// 0x00000008: (unidentified)36// 0x00000004: Lock word clock on BNC interface37// 0x00000002: Lock ADAT or S/PDIF on optical interface38// 0x00000001: Lock S/PDIF on coaxial interface39//40// Fireface 802 (and perhaps UFX):41// 0xf0000000: effective rate of sampling clock42// 0x0f000000: detected rate of ADAT-B on 2nd optical interface43// 0x00f00000: detected rate of ADAT-A on 1st optical interface44// 0x000f0000: detected rate of AES/EBU on XLR or coaxial interface45// 0x0000f000: detected rate of word clock on BNC interface46// 0x00000e00: effective source of sampling clock47// 0x00000e00: internal48// 0x00000800: ADAT-B49// 0x00000600: ADAT-A50// 0x00000400: AES/EBU51// 0x00000200: Word clock52// 0x00000080: Synchronized to ADAT-B on 2nd optical interface53// 0x00000040: Synchronized to ADAT-A on 1st optical interface54// 0x00000020: Synchronized to AES/EBU on XLR or 2nd optical interface55// 0x00000010: Synchronized to word clock on BNC interface56// 0x00000008: Lock ADAT-B on 2nd optical interface57// 0x00000004: Lock ADAT-A on 1st optical interface58// 0x00000002: Lock AES/EBU on XLR or 2nd optical interface59// 0x00000001: Lock word clock on BNC interface60//61// The pattern for rate bits:62// 0x00: 32.0 kHz63// 0x01: 44.1 kHz64// 0x02: 48.0 kHz65// 0x04: 64.0 kHz66// 0x05: 88.2 kHz67// 0x06: 96.0 kHz68// 0x08: 128.0 kHz69// 0x09: 176.4 kHz70// 0x0a: 192.0 kHz71static int parse_clock_bits(u32 data, unsigned int *rate,72 enum snd_ff_clock_src *src,73 enum snd_ff_unit_version unit_version)74{75 static const struct {76 unsigned int rate;77 u32 flag;78 } *rate_entry, rate_entries[] = {79 { 32000, 0x00, },80 { 44100, 0x01, },81 { 48000, 0x02, },82 { 64000, 0x04, },83 { 88200, 0x05, },84 { 96000, 0x06, },85 { 128000, 0x08, },86 { 176400, 0x09, },87 { 192000, 0x0a, },88 };89 static const struct {90 enum snd_ff_clock_src src;91 u32 flag;92 } *clk_entry, *clk_entries, ucx_clk_entries[] = {93 { SND_FF_CLOCK_SRC_SPDIF, 0x00000200, },94 { SND_FF_CLOCK_SRC_ADAT1, 0x00000400, },95 { SND_FF_CLOCK_SRC_WORD, 0x00000600, },96 { SND_FF_CLOCK_SRC_INTERNAL, 0x00000e00, },97 }, ufx_ff802_clk_entries[] = {98 { SND_FF_CLOCK_SRC_WORD, 0x00000200, },99 { SND_FF_CLOCK_SRC_SPDIF, 0x00000400, },100 { SND_FF_CLOCK_SRC_ADAT1, 0x00000600, },101 { SND_FF_CLOCK_SRC_ADAT2, 0x00000800, },102 { SND_FF_CLOCK_SRC_INTERNAL, 0x00000e00, },103 };104 u32 rate_bits;105 unsigned int clk_entry_count;106 int i;107 108 if (unit_version == SND_FF_UNIT_VERSION_UCX) {109 rate_bits = (data & 0x0f000000) >> 24;110 clk_entries = ucx_clk_entries;111 clk_entry_count = ARRAY_SIZE(ucx_clk_entries);112 } else {113 rate_bits = (data & 0xf0000000) >> 28;114 clk_entries = ufx_ff802_clk_entries;115 clk_entry_count = ARRAY_SIZE(ufx_ff802_clk_entries);116 }117 118 for (i = 0; i < ARRAY_SIZE(rate_entries); ++i) {119 rate_entry = rate_entries + i;120 if (rate_bits == rate_entry->flag) {121 *rate = rate_entry->rate;122 break;123 }124 }125 if (i == ARRAY_SIZE(rate_entries))126 return -EIO;127 128 for (i = 0; i < clk_entry_count; ++i) {129 clk_entry = clk_entries + i;130 if ((data & 0x000e00) == clk_entry->flag) {131 *src = clk_entry->src;132 break;133 }134 }135 if (i == clk_entry_count)136 return -EIO;137 138 return 0;139}140 141static int latter_get_clock(struct snd_ff *ff, unsigned int *rate,142 enum snd_ff_clock_src *src)143{144 __le32 reg;145 u32 data;146 int err;147 148 err = snd_fw_transaction(ff->unit, TCODE_READ_QUADLET_REQUEST,149 LATTER_SYNC_STATUS, ®, sizeof(reg), 0);150 if (err < 0)151 return err;152 data = le32_to_cpu(reg);153 154 return parse_clock_bits(data, rate, src, ff->unit_version);155}156 157static int latter_switch_fetching_mode(struct snd_ff *ff, bool enable)158{159 u32 data;160 __le32 reg;161 162 if (enable)163 data = 0x00000000;164 else165 data = 0xffffffff;166 reg = cpu_to_le32(data);167 168 return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,169 LATTER_FETCH_MODE, ®, sizeof(reg), 0);170}171 172static int latter_allocate_resources(struct snd_ff *ff, unsigned int rate)173{174 enum snd_ff_stream_mode mode;175 unsigned int code;176 __le32 reg;177 unsigned int count;178 int i;179 int err;180 181 // Set the number of data blocks transferred in a second.182 if (rate % 48000 == 0)183 code = 0x04;184 else if (rate % 44100 == 0)185 code = 0x02;186 else if (rate % 32000 == 0)187 code = 0x00;188 else189 return -EINVAL;190 191 if (rate >= 64000 && rate < 128000)192 code |= 0x08;193 else if (rate >= 128000)194 code |= 0x10;195 196 reg = cpu_to_le32(code);197 err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,198 LATTER_STF, ®, sizeof(reg), 0);199 if (err < 0)200 return err;201 202 // Confirm to shift transmission clock.203 count = 0;204 while (count++ < 10) {205 unsigned int curr_rate;206 enum snd_ff_clock_src src;207 208 err = latter_get_clock(ff, &curr_rate, &src);209 if (err < 0)210 return err;211 212 if (curr_rate == rate)213 break;214 }215 if (count > 10)216 return -ETIMEDOUT;217 218 for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); ++i) {219 if (rate == amdtp_rate_table[i])220 break;221 }222 if (i == ARRAY_SIZE(amdtp_rate_table))223 return -EINVAL;224 225 err = snd_ff_stream_get_multiplier_mode(i, &mode);226 if (err < 0)227 return err;228 229 // Keep resources for in-stream.230 ff->tx_resources.channels_mask = 0x00000000000000ffuLL;231 err = fw_iso_resources_allocate(&ff->tx_resources,232 amdtp_stream_get_max_payload(&ff->tx_stream),233 fw_parent_device(ff->unit)->max_speed);234 if (err < 0)235 return err;236 237 // Keep resources for out-stream.238 ff->rx_resources.channels_mask = 0x00000000000000ffuLL;239 err = fw_iso_resources_allocate(&ff->rx_resources,240 amdtp_stream_get_max_payload(&ff->rx_stream),241 fw_parent_device(ff->unit)->max_speed);242 if (err < 0)243 fw_iso_resources_free(&ff->tx_resources);244 245 return err;246}247 248static int latter_begin_session(struct snd_ff *ff, unsigned int rate)249{250 unsigned int generation = ff->rx_resources.generation;251 unsigned int flag;252 u32 data;253 __le32 reg;254 int err;255 256 if (ff->unit_version == SND_FF_UNIT_VERSION_UCX) {257 // For Fireface UCX. Always use the maximum number of data258 // channels in data block of packet.259 if (rate >= 32000 && rate <= 48000)260 flag = 0x92;261 else if (rate >= 64000 && rate <= 96000)262 flag = 0x8e;263 else if (rate >= 128000 && rate <= 192000)264 flag = 0x8c;265 else266 return -EINVAL;267 } else {268 // For Fireface UFX and 802. Due to bandwidth limitation on269 // IEEE 1394a (400 Mbps), Analog 1-12 and AES are available270 // without any ADAT at quadruple speed.271 if (rate >= 32000 && rate <= 48000)272 flag = 0x9e;273 else if (rate >= 64000 && rate <= 96000)274 flag = 0x96;275 else if (rate >= 128000 && rate <= 192000)276 flag = 0x8e;277 else278 return -EINVAL;279 }280 281 if (generation != fw_parent_device(ff->unit)->card->generation) {282 err = fw_iso_resources_update(&ff->tx_resources);283 if (err < 0)284 return err;285 286 err = fw_iso_resources_update(&ff->rx_resources);287 if (err < 0)288 return err;289 }290 291 data = (ff->tx_resources.channel << 8) | ff->rx_resources.channel;292 reg = cpu_to_le32(data);293 err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,294 LATTER_ISOC_CHANNELS, ®, sizeof(reg), 0);295 if (err < 0)296 return err;297 298 reg = cpu_to_le32(flag);299 return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,300 LATTER_ISOC_START, ®, sizeof(reg), 0);301}302 303static void latter_finish_session(struct snd_ff *ff)304{305 __le32 reg;306 307 reg = cpu_to_le32(0x00000000);308 snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,309 LATTER_ISOC_START, ®, sizeof(reg), 0);310}311 312static void latter_dump_status(struct snd_ff *ff, struct snd_info_buffer *buffer)313{314 static const struct {315 char *const label;316 u32 locked_mask;317 u32 synced_mask;318 } *clk_entry, *clk_entries, ucx_clk_entries[] = {319 { "S/PDIF", 0x00000001, 0x00000010, },320 { "ADAT", 0x00000002, 0x00000020, },321 { "WDClk", 0x00000004, 0x00000040, },322 }, ufx_ff802_clk_entries[] = {323 { "WDClk", 0x00000001, 0x00000010, },324 { "AES/EBU", 0x00000002, 0x00000020, },325 { "ADAT-A", 0x00000004, 0x00000040, },326 { "ADAT-B", 0x00000008, 0x00000080, },327 };328 __le32 reg;329 u32 data;330 unsigned int rate;331 enum snd_ff_clock_src src;332 const char *label;333 unsigned int clk_entry_count;334 int i;335 int err;336 337 err = snd_fw_transaction(ff->unit, TCODE_READ_QUADLET_REQUEST,338 LATTER_SYNC_STATUS, ®, sizeof(reg), 0);339 if (err < 0)340 return;341 data = le32_to_cpu(reg);342 343 snd_iprintf(buffer, "External source detection:\n");344 345 if (ff->unit_version == SND_FF_UNIT_VERSION_UCX) {346 clk_entries = ucx_clk_entries;347 clk_entry_count = ARRAY_SIZE(ucx_clk_entries);348 } else {349 clk_entries = ufx_ff802_clk_entries;350 clk_entry_count = ARRAY_SIZE(ufx_ff802_clk_entries);351 }352 353 for (i = 0; i < clk_entry_count; ++i) {354 clk_entry = clk_entries + i;355 snd_iprintf(buffer, "%s: ", clk_entry->label);356 if (data & clk_entry->locked_mask) {357 if (data & clk_entry->synced_mask)358 snd_iprintf(buffer, "sync\n");359 else360 snd_iprintf(buffer, "lock\n");361 } else {362 snd_iprintf(buffer, "none\n");363 }364 }365 366 err = parse_clock_bits(data, &rate, &src, ff->unit_version);367 if (err < 0)368 return;369 label = snd_ff_proc_get_clk_label(src);370 if (!label)371 return;372 373 snd_iprintf(buffer, "Referred clock: %s %d\n", label, rate);374}375 376// NOTE: transactions are transferred within 0x00-0x7f in allocated range of377// address. This seems to be for check of discontinuity in receiver side.378//379// Like Fireface 400, drivers can select one of 4 options for lower 4 bytes of380// destination address by bit flags in quadlet register (little endian) at381// 0x'ffff'0000'0014:382//383// bit flags: offset of destination address384// - 0x00002000: 0x'....'....'0000'0000385// - 0x00004000: 0x'....'....'0000'0080386// - 0x00008000: 0x'....'....'0000'0100387// - 0x00010000: 0x'....'....'0000'0180388//389// Drivers can suppress the device to transfer asynchronous transactions by390// clear these bit flags.391//392// Actually, the register is write-only and includes the other settings such as393// input attenuation. This driver allocates for the first option394// (0x'....'....'0000'0000) and expects userspace application to configure the395// register for it.396static void latter_handle_midi_msg(struct snd_ff *ff, unsigned int offset, const __le32 *buf,397 size_t length, u32 tstamp)398{399 u32 data = le32_to_cpu(*buf);400 unsigned int index = (data & 0x000000f0) >> 4;401 u8 byte[3];402 struct snd_rawmidi_substream *substream;403 unsigned int len;404 405 if (index >= ff->spec->midi_in_ports)406 return;407 408 switch (data & 0x0000000f) {409 case 0x00000008:410 case 0x00000009:411 case 0x0000000a:412 case 0x0000000b:413 case 0x0000000e:414 len = 3;415 break;416 case 0x0000000c:417 case 0x0000000d:418 len = 2;419 break;420 default:421 len = data & 0x00000003;422 if (len == 0)423 len = 3;424 break;425 }426 427 byte[0] = (data & 0x0000ff00) >> 8;428 byte[1] = (data & 0x00ff0000) >> 16;429 byte[2] = (data & 0xff000000) >> 24;430 431 substream = READ_ONCE(ff->tx_midi_substreams[index]);432 if (substream)433 snd_rawmidi_receive(substream, byte, len);434}435 436/*437 * When return minus value, given argument is not MIDI status.438 * When return 0, given argument is a beginning of system exclusive.439 * When return the others, given argument is MIDI data.440 */441static inline int calculate_message_bytes(u8 status)442{443 switch (status) {444 case 0xf6: /* Tune request. */445 case 0xf8: /* Timing clock. */446 case 0xfa: /* Start. */447 case 0xfb: /* Continue. */448 case 0xfc: /* Stop. */449 case 0xfe: /* Active sensing. */450 case 0xff: /* System reset. */451 return 1;452 case 0xf1: /* MIDI time code quarter frame. */453 case 0xf3: /* Song select. */454 return 2;455 case 0xf2: /* Song position pointer. */456 return 3;457 case 0xf0: /* Exclusive. */458 return 0;459 case 0xf7: /* End of exclusive. */460 break;461 case 0xf4: /* Undefined. */462 case 0xf5: /* Undefined. */463 case 0xf9: /* Undefined. */464 case 0xfd: /* Undefined. */465 break;466 default:467 switch (status & 0xf0) {468 case 0x80: /* Note on. */469 case 0x90: /* Note off. */470 case 0xa0: /* Polyphonic key pressure. */471 case 0xb0: /* Control change and Mode change. */472 case 0xe0: /* Pitch bend change. */473 return 3;474 case 0xc0: /* Program change. */475 case 0xd0: /* Channel pressure. */476 return 2;477 default:478 break;479 }480 break;481 }482 483 return -EINVAL;484}485 486static int latter_fill_midi_msg(struct snd_ff *ff,487 struct snd_rawmidi_substream *substream,488 unsigned int port)489{490 u32 data = {0};491 u8 *buf = (u8 *)&data;492 int consumed;493 494 buf[0] = port << 4;495 consumed = snd_rawmidi_transmit_peek(substream, buf + 1, 3);496 if (consumed <= 0)497 return consumed;498 499 if (!ff->on_sysex[port]) {500 if (buf[1] != 0xf0) {501 if (consumed < calculate_message_bytes(buf[1]))502 return 0;503 } else {504 // The beginning of exclusives.505 ff->on_sysex[port] = true;506 }507 508 buf[0] |= consumed;509 } else {510 if (buf[1] != 0xf7) {511 if (buf[2] == 0xf7 || buf[3] == 0xf7) {512 // Transfer end code at next time.513 consumed -= 1;514 }515 516 buf[0] |= consumed;517 } else {518 // The end of exclusives.519 ff->on_sysex[port] = false;520 consumed = 1;521 buf[0] |= 0x0f;522 }523 }524 525 ff->msg_buf[port][0] = cpu_to_le32(data);526 ff->rx_bytes[port] = consumed;527 528 return 1;529}530 531const struct snd_ff_protocol snd_ff_protocol_latter = {532 .handle_msg = latter_handle_midi_msg,533 .fill_midi_msg = latter_fill_midi_msg,534 .get_clock = latter_get_clock,535 .switch_fetching_mode = latter_switch_fetching_mode,536 .allocate_resources = latter_allocate_resources,537 .begin_session = latter_begin_session,538 .finish_session = latter_finish_session,539 .dump_status = latter_dump_status,540};541