| 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | // ff-protocol-former.c - a part of driver for RME Fireface series |
| 3 | // |
| 4 | // Copyright (c) 2019 Takashi Sakamoto |
| 5 | |
| 6 | #include <linux/delay.h> |
| 7 | |
| 8 | #include "ff.h" |
| 9 | |
| 10 | #define FORMER_REG_SYNC_STATUS 0x0000801c0000ull |
| 11 | /* For block write request. */ |
| 12 | #define FORMER_REG_FETCH_PCM_FRAMES 0x0000801c0000ull |
| 13 | #define FORMER_REG_CLOCK_CONFIG 0x0000801c0004ull |
| 14 | |
| 15 | static int parse_clock_bits(u32 data, unsigned int *rate, |
| 16 | enum snd_ff_clock_src *src) |
| 17 | { |
| 18 | static const struct { |
| 19 | unsigned int rate; |
| 20 | u32 mask; |
| 21 | } *rate_entry, rate_entries[] = { |
| 22 | { 32000, 0x00000002, }, |
| 23 | { 44100, 0x00000000, }, |
| 24 | { 48000, 0x00000006, }, |
| 25 | { 64000, 0x0000000a, }, |
| 26 | { 88200, 0x00000008, }, |
| 27 | { 96000, 0x0000000e, }, |
| 28 | { 128000, 0x00000012, }, |
| 29 | { 176400, 0x00000010, }, |
| 30 | { 192000, 0x00000016, }, |
| 31 | }; |
| 32 | static const struct { |
| 33 | enum snd_ff_clock_src src; |
| 34 | u32 mask; |
| 35 | } *clk_entry, clk_entries[] = { |
| 36 | { SND_FF_CLOCK_SRC_ADAT1, 0x00000000, }, |
| 37 | { SND_FF_CLOCK_SRC_ADAT2, 0x00000400, }, |
| 38 | { SND_FF_CLOCK_SRC_SPDIF, 0x00000c00, }, |
| 39 | { SND_FF_CLOCK_SRC_WORD, 0x00001000, }, |
| 40 | { SND_FF_CLOCK_SRC_LTC, 0x00001800, }, |
| 41 | }; |
| 42 | int i; |
| 43 | |
| 44 | for (i = 0; i < ARRAY_SIZE(rate_entries); ++i) { |
| 45 | rate_entry = rate_entries + i; |
| 46 | if ((data & 0x0000001e) == rate_entry->mask) { |
| 47 | *rate = rate_entry->rate; |
| 48 | break; |
| 49 | } |
| 50 | } |
| 51 | if (i == ARRAY_SIZE(rate_entries)) |
| 52 | return -EIO; |
| 53 | |
| 54 | if (data & 0x00000001) { |
| 55 | *src = SND_FF_CLOCK_SRC_INTERNAL; |
| 56 | } else { |
| 57 | for (i = 0; i < ARRAY_SIZE(clk_entries); ++i) { |
| 58 | clk_entry = clk_entries + i; |
| 59 | if ((data & 0x00001c00) == clk_entry->mask) { |
| 60 | *src = clk_entry->src; |
| 61 | break; |
| 62 | } |
| 63 | } |
| 64 | if (i == ARRAY_SIZE(clk_entries)) |
| 65 | return -EIO; |
| 66 | } |
| 67 | |
| 68 | return 0; |
| 69 | } |
| 70 | |
| 71 | static int former_get_clock(struct snd_ff *ff, unsigned int *rate, |
| 72 | enum snd_ff_clock_src *src) |
| 73 | { |
| 74 | __le32 reg; |
| 75 | u32 data; |
| 76 | int err; |
| 77 | |
| 78 | err = snd_fw_transaction(unit: ff->unit, TCODE_READ_QUADLET_REQUEST, |
| 79 | FORMER_REG_CLOCK_CONFIG, buffer: ®, length: sizeof(reg), flags: 0); |
| 80 | if (err < 0) |
| 81 | return err; |
| 82 | data = le32_to_cpu(reg); |
| 83 | |
| 84 | return parse_clock_bits(data, rate, src); |
| 85 | } |
| 86 | |
| 87 | static int former_switch_fetching_mode(struct snd_ff *ff, bool enable) |
| 88 | { |
| 89 | unsigned int count; |
| 90 | __le32 *reg; |
| 91 | int i; |
| 92 | int err; |
| 93 | |
| 94 | count = 0; |
| 95 | for (i = 0; i < SND_FF_STREAM_MODE_COUNT; ++i) |
| 96 | count = max(count, ff->spec->pcm_playback_channels[i]); |
| 97 | |
| 98 | reg = kcalloc(count, sizeof(__le32), GFP_KERNEL); |
| 99 | if (!reg) |
| 100 | return -ENOMEM; |
| 101 | |
| 102 | if (!enable) { |
| 103 | /* |
| 104 | * Each quadlet is corresponding to data channels in a data |
| 105 | * blocks in reverse order. Precisely, quadlets for available |
| 106 | * data channels should be enabled. Here, I take second best |
| 107 | * to fetch PCM frames from all of data channels regardless of |
| 108 | * stf. |
| 109 | */ |
| 110 | for (i = 0; i < count; ++i) |
| 111 | reg[i] = cpu_to_le32(0x00000001); |
| 112 | } |
| 113 | |
| 114 | err = snd_fw_transaction(unit: ff->unit, TCODE_WRITE_BLOCK_REQUEST, |
| 115 | FORMER_REG_FETCH_PCM_FRAMES, buffer: reg, |
| 116 | length: sizeof(__le32) * count, flags: 0); |
| 117 | kfree(objp: reg); |
| 118 | return err; |
| 119 | } |
| 120 | |
| 121 | static void dump_clock_config(struct snd_ff *ff, struct snd_info_buffer *buffer) |
| 122 | { |
| 123 | __le32 reg; |
| 124 | u32 data; |
| 125 | unsigned int rate; |
| 126 | enum snd_ff_clock_src src; |
| 127 | const char *label; |
| 128 | int err; |
| 129 | |
| 130 | err = snd_fw_transaction(unit: ff->unit, TCODE_READ_BLOCK_REQUEST, |
| 131 | FORMER_REG_CLOCK_CONFIG, buffer: ®, length: sizeof(reg), flags: 0); |
| 132 | if (err < 0) |
| 133 | return; |
| 134 | data = le32_to_cpu(reg); |
| 135 | |
| 136 | snd_iprintf(buffer, "Output S/PDIF format: %s (Emphasis: %s)\n" , |
| 137 | (data & 0x00000020) ? "Professional" : "Consumer" , |
| 138 | str_on_off(data & 0x00000040)); |
| 139 | |
| 140 | snd_iprintf(buffer, "Optical output interface format: %s\n" , |
| 141 | (data & 0x00000100) ? "S/PDIF" : "ADAT" ); |
| 142 | |
| 143 | snd_iprintf(buffer, "Word output single speed: %s\n" , |
| 144 | str_on_off(data & 0x00002000)); |
| 145 | |
| 146 | snd_iprintf(buffer, "S/PDIF input interface: %s\n" , |
| 147 | (data & 0x00000200) ? "Optical" : "Coaxial" ); |
| 148 | |
| 149 | err = parse_clock_bits(data, rate: &rate, src: &src); |
| 150 | if (err < 0) |
| 151 | return; |
| 152 | label = snd_ff_proc_get_clk_label(src); |
| 153 | if (!label) |
| 154 | return; |
| 155 | |
| 156 | snd_iprintf(buffer, "Clock configuration: %d %s\n" , rate, label); |
| 157 | } |
| 158 | |
| 159 | static void dump_sync_status(struct snd_ff *ff, struct snd_info_buffer *buffer) |
| 160 | { |
| 161 | static const struct { |
| 162 | char *const label; |
| 163 | u32 locked_mask; |
| 164 | u32 synced_mask; |
| 165 | } *clk_entry, clk_entries[] = { |
| 166 | { "WDClk" , 0x40000000, 0x20000000, }, |
| 167 | { "S/PDIF" , 0x00080000, 0x00040000, }, |
| 168 | { "ADAT1" , 0x00000400, 0x00001000, }, |
| 169 | { "ADAT2" , 0x00000800, 0x00002000, }, |
| 170 | }; |
| 171 | static const struct { |
| 172 | char *const label; |
| 173 | u32 mask; |
| 174 | } *referred_entry, referred_entries[] = { |
| 175 | { "ADAT1" , 0x00000000, }, |
| 176 | { "ADAT2" , 0x00400000, }, |
| 177 | { "S/PDIF" , 0x00c00000, }, |
| 178 | { "WDclk" , 0x01000000, }, |
| 179 | { "TCO" , 0x01400000, }, |
| 180 | }; |
| 181 | static const struct { |
| 182 | unsigned int rate; |
| 183 | u32 mask; |
| 184 | } *rate_entry, rate_entries[] = { |
| 185 | { 32000, 0x02000000, }, |
| 186 | { 44100, 0x04000000, }, |
| 187 | { 48000, 0x06000000, }, |
| 188 | { 64000, 0x08000000, }, |
| 189 | { 88200, 0x0a000000, }, |
| 190 | { 96000, 0x0c000000, }, |
| 191 | { 128000, 0x0e000000, }, |
| 192 | { 176400, 0x10000000, }, |
| 193 | { 192000, 0x12000000, }, |
| 194 | }; |
| 195 | __le32 reg[2]; |
| 196 | u32 data[2]; |
| 197 | int i; |
| 198 | int err; |
| 199 | |
| 200 | err = snd_fw_transaction(unit: ff->unit, TCODE_READ_BLOCK_REQUEST, |
| 201 | FORMER_REG_SYNC_STATUS, buffer: reg, length: sizeof(reg), flags: 0); |
| 202 | if (err < 0) |
| 203 | return; |
| 204 | data[0] = le32_to_cpu(reg[0]); |
| 205 | data[1] = le32_to_cpu(reg[1]); |
| 206 | |
| 207 | snd_iprintf(buffer, "External source detection:\n" ); |
| 208 | |
| 209 | for (i = 0; i < ARRAY_SIZE(clk_entries); ++i) { |
| 210 | const char *state; |
| 211 | |
| 212 | clk_entry = clk_entries + i; |
| 213 | if (data[0] & clk_entry->locked_mask) { |
| 214 | if (data[0] & clk_entry->synced_mask) |
| 215 | state = "sync" ; |
| 216 | else |
| 217 | state = "lock" ; |
| 218 | } else { |
| 219 | state = "none" ; |
| 220 | } |
| 221 | |
| 222 | snd_iprintf(buffer, "%s: %s\n" , clk_entry->label, state); |
| 223 | } |
| 224 | |
| 225 | snd_iprintf(buffer, "Referred clock:\n" ); |
| 226 | |
| 227 | if (data[1] & 0x00000001) { |
| 228 | snd_iprintf(buffer, "Internal\n" ); |
| 229 | } else { |
| 230 | unsigned int rate; |
| 231 | const char *label; |
| 232 | |
| 233 | for (i = 0; i < ARRAY_SIZE(referred_entries); ++i) { |
| 234 | referred_entry = referred_entries + i; |
| 235 | if ((data[0] & 0x1e0000) == referred_entry->mask) { |
| 236 | label = referred_entry->label; |
| 237 | break; |
| 238 | } |
| 239 | } |
| 240 | if (i == ARRAY_SIZE(referred_entries)) |
| 241 | label = "none" ; |
| 242 | |
| 243 | for (i = 0; i < ARRAY_SIZE(rate_entries); ++i) { |
| 244 | rate_entry = rate_entries + i; |
| 245 | if ((data[0] & 0x1e000000) == rate_entry->mask) { |
| 246 | rate = rate_entry->rate; |
| 247 | break; |
| 248 | } |
| 249 | } |
| 250 | if (i == ARRAY_SIZE(rate_entries)) |
| 251 | rate = 0; |
| 252 | |
| 253 | snd_iprintf(buffer, "%s %d\n" , label, rate); |
| 254 | } |
| 255 | } |
| 256 | |
| 257 | static void former_dump_status(struct snd_ff *ff, |
| 258 | struct snd_info_buffer *buffer) |
| 259 | { |
| 260 | dump_clock_config(ff, buffer); |
| 261 | dump_sync_status(ff, buffer); |
| 262 | } |
| 263 | |
| 264 | static int former_fill_midi_msg(struct snd_ff *ff, |
| 265 | struct snd_rawmidi_substream *substream, |
| 266 | unsigned int port) |
| 267 | { |
| 268 | u8 *buf = (u8 *)ff->msg_buf[port]; |
| 269 | int len; |
| 270 | int i; |
| 271 | |
| 272 | len = snd_rawmidi_transmit_peek(substream, buffer: buf, |
| 273 | SND_FF_MAXIMIM_MIDI_QUADS); |
| 274 | if (len <= 0) |
| 275 | return len; |
| 276 | |
| 277 | // One quadlet includes one byte. |
| 278 | for (i = len - 1; i >= 0; --i) |
| 279 | ff->msg_buf[port][i] = cpu_to_le32(buf[i]); |
| 280 | ff->rx_bytes[port] = len; |
| 281 | |
| 282 | return len; |
| 283 | } |
| 284 | |
| 285 | #define FF800_STF 0x0000fc88f000 |
| 286 | #define FF800_RX_PACKET_FORMAT 0x0000fc88f004 |
| 287 | #define FF800_ALLOC_TX_STREAM 0x0000fc88f008 |
| 288 | #define FF800_ISOC_COMM_START 0x0000fc88f00c |
| 289 | #define FF800_TX_S800_FLAG 0x00000800 |
| 290 | #define FF800_ISOC_COMM_STOP 0x0000fc88f010 |
| 291 | |
| 292 | #define FF800_TX_PACKET_ISOC_CH 0x0000801c0008 |
| 293 | |
| 294 | static int allocate_tx_resources(struct snd_ff *ff) |
| 295 | { |
| 296 | __le32 reg; |
| 297 | unsigned int count; |
| 298 | unsigned int tx_isoc_channel; |
| 299 | int err; |
| 300 | |
| 301 | reg = cpu_to_le32(ff->tx_stream.data_block_quadlets); |
| 302 | err = snd_fw_transaction(unit: ff->unit, TCODE_WRITE_QUADLET_REQUEST, |
| 303 | FF800_ALLOC_TX_STREAM, buffer: ®, length: sizeof(reg), flags: 0); |
| 304 | if (err < 0) |
| 305 | return err; |
| 306 | |
| 307 | // Wait till the format of tx packet is available. |
| 308 | count = 0; |
| 309 | while (count++ < 10) { |
| 310 | u32 data; |
| 311 | err = snd_fw_transaction(unit: ff->unit, TCODE_READ_QUADLET_REQUEST, |
| 312 | FF800_TX_PACKET_ISOC_CH, buffer: ®, length: sizeof(reg), flags: 0); |
| 313 | if (err < 0) |
| 314 | return err; |
| 315 | |
| 316 | data = le32_to_cpu(reg); |
| 317 | if (data != 0xffffffff) { |
| 318 | tx_isoc_channel = data; |
| 319 | break; |
| 320 | } |
| 321 | |
| 322 | msleep(msecs: 50); |
| 323 | } |
| 324 | if (count >= 10) |
| 325 | return -ETIMEDOUT; |
| 326 | |
| 327 | // NOTE: this is a makeshift to start OHCI 1394 IR context in the |
| 328 | // channel. On the other hand, 'struct fw_iso_resources.allocated' is |
| 329 | // not true and it's not deallocated at stop. |
| 330 | ff->tx_resources.channel = tx_isoc_channel; |
| 331 | |
| 332 | return 0; |
| 333 | } |
| 334 | |
| 335 | static int ff800_allocate_resources(struct snd_ff *ff, unsigned int rate) |
| 336 | { |
| 337 | u32 data; |
| 338 | __le32 reg; |
| 339 | int err; |
| 340 | |
| 341 | reg = cpu_to_le32(rate); |
| 342 | err = snd_fw_transaction(unit: ff->unit, TCODE_WRITE_QUADLET_REQUEST, |
| 343 | FF800_STF, buffer: ®, length: sizeof(reg), flags: 0); |
| 344 | if (err < 0) |
| 345 | return err; |
| 346 | |
| 347 | // If starting isochronous communication immediately, change of STF has |
| 348 | // no effect. In this case, the communication runs based on former STF. |
| 349 | // Let's sleep for a bit. |
| 350 | msleep(msecs: 100); |
| 351 | |
| 352 | // Controllers should allocate isochronous resources for rx stream. |
| 353 | err = fw_iso_resources_allocate(r: &ff->rx_resources, |
| 354 | max_payload_bytes: amdtp_stream_get_max_payload(s: &ff->rx_stream), |
| 355 | fw_parent_device(ff->unit)->max_speed); |
| 356 | if (err < 0) |
| 357 | return err; |
| 358 | |
| 359 | // Set isochronous channel and the number of quadlets of rx packets. |
| 360 | // This should be done before the allocation of tx resources to avoid |
| 361 | // periodical noise. |
| 362 | data = ff->rx_stream.data_block_quadlets << 3; |
| 363 | data = (data << 8) | ff->rx_resources.channel; |
| 364 | reg = cpu_to_le32(data); |
| 365 | err = snd_fw_transaction(unit: ff->unit, TCODE_WRITE_QUADLET_REQUEST, |
| 366 | FF800_RX_PACKET_FORMAT, buffer: ®, length: sizeof(reg), flags: 0); |
| 367 | if (err < 0) |
| 368 | return err; |
| 369 | |
| 370 | return allocate_tx_resources(ff); |
| 371 | } |
| 372 | |
| 373 | static int ff800_begin_session(struct snd_ff *ff, unsigned int rate) |
| 374 | { |
| 375 | unsigned int generation = ff->rx_resources.generation; |
| 376 | __le32 reg; |
| 377 | |
| 378 | if (generation != fw_parent_device(ff->unit)->card->generation) { |
| 379 | int err = fw_iso_resources_update(r: &ff->rx_resources); |
| 380 | if (err < 0) |
| 381 | return err; |
| 382 | } |
| 383 | |
| 384 | reg = cpu_to_le32(0x80000000); |
| 385 | reg |= cpu_to_le32(ff->tx_stream.data_block_quadlets); |
| 386 | if (fw_parent_device(ff->unit)->max_speed == SCODE_800) |
| 387 | reg |= cpu_to_le32(FF800_TX_S800_FLAG); |
| 388 | return snd_fw_transaction(unit: ff->unit, TCODE_WRITE_QUADLET_REQUEST, |
| 389 | FF800_ISOC_COMM_START, buffer: ®, length: sizeof(reg), flags: 0); |
| 390 | } |
| 391 | |
| 392 | static void ff800_finish_session(struct snd_ff *ff) |
| 393 | { |
| 394 | __le32 reg; |
| 395 | |
| 396 | reg = cpu_to_le32(0x80000000); |
| 397 | snd_fw_transaction(unit: ff->unit, TCODE_WRITE_QUADLET_REQUEST, |
| 398 | FF800_ISOC_COMM_STOP, buffer: ®, length: sizeof(reg), flags: 0); |
| 399 | } |
| 400 | |
| 401 | // Fireface 800 doesn't allow drivers to register lower 4 bytes of destination |
| 402 | // address. |
| 403 | // A write transaction to clear registered higher 4 bytes of destination address |
| 404 | // has an effect to suppress asynchronous transaction from device. |
| 405 | static void ff800_handle_midi_msg(struct snd_ff *ff, unsigned int offset, const __le32 *buf, |
| 406 | size_t length, u32 tstamp) |
| 407 | { |
| 408 | int i; |
| 409 | |
| 410 | for (i = 0; i < length / 4; i++) { |
| 411 | u8 byte = le32_to_cpu(buf[i]) & 0xff; |
| 412 | struct snd_rawmidi_substream *substream; |
| 413 | |
| 414 | substream = READ_ONCE(ff->tx_midi_substreams[0]); |
| 415 | if (substream) |
| 416 | snd_rawmidi_receive(substream, buffer: &byte, count: 1); |
| 417 | } |
| 418 | } |
| 419 | |
| 420 | const struct snd_ff_protocol snd_ff_protocol_ff800 = { |
| 421 | .handle_msg = ff800_handle_midi_msg, |
| 422 | .fill_midi_msg = former_fill_midi_msg, |
| 423 | .get_clock = former_get_clock, |
| 424 | .switch_fetching_mode = former_switch_fetching_mode, |
| 425 | .allocate_resources = ff800_allocate_resources, |
| 426 | .begin_session = ff800_begin_session, |
| 427 | .finish_session = ff800_finish_session, |
| 428 | .dump_status = former_dump_status, |
| 429 | }; |
| 430 | |
| 431 | #define FF400_STF 0x000080100500ull |
| 432 | #define FF400_RX_PACKET_FORMAT 0x000080100504ull |
| 433 | #define FF400_ISOC_COMM_START 0x000080100508ull |
| 434 | #define FF400_TX_PACKET_FORMAT 0x00008010050cull |
| 435 | #define FF400_ISOC_COMM_STOP 0x000080100510ull |
| 436 | |
| 437 | // Fireface 400 manages isochronous channel number in 3 bit field. Therefore, |
| 438 | // we can allocate between 0 and 7 channel. |
| 439 | static int ff400_allocate_resources(struct snd_ff *ff, unsigned int rate) |
| 440 | { |
| 441 | __le32 reg; |
| 442 | enum snd_ff_stream_mode mode; |
| 443 | int i; |
| 444 | int err; |
| 445 | |
| 446 | // Check whether the given value is supported or not. |
| 447 | for (i = 0; i < CIP_SFC_COUNT; i++) { |
| 448 | if (amdtp_rate_table[i] == rate) |
| 449 | break; |
| 450 | } |
| 451 | if (i >= CIP_SFC_COUNT) |
| 452 | return -EINVAL; |
| 453 | |
| 454 | // Set the number of data blocks transferred in a second. |
| 455 | reg = cpu_to_le32(rate); |
| 456 | err = snd_fw_transaction(unit: ff->unit, TCODE_WRITE_QUADLET_REQUEST, |
| 457 | FF400_STF, buffer: ®, length: sizeof(reg), flags: 0); |
| 458 | if (err < 0) |
| 459 | return err; |
| 460 | |
| 461 | msleep(msecs: 100); |
| 462 | |
| 463 | err = snd_ff_stream_get_multiplier_mode(sfc: i, mode: &mode); |
| 464 | if (err < 0) |
| 465 | return err; |
| 466 | |
| 467 | // Keep resources for in-stream. |
| 468 | ff->tx_resources.channels_mask = 0x00000000000000ffuLL; |
| 469 | err = fw_iso_resources_allocate(r: &ff->tx_resources, |
| 470 | max_payload_bytes: amdtp_stream_get_max_payload(s: &ff->tx_stream), |
| 471 | fw_parent_device(ff->unit)->max_speed); |
| 472 | if (err < 0) |
| 473 | return err; |
| 474 | |
| 475 | // Keep resources for out-stream. |
| 476 | ff->rx_resources.channels_mask = 0x00000000000000ffuLL; |
| 477 | err = fw_iso_resources_allocate(r: &ff->rx_resources, |
| 478 | max_payload_bytes: amdtp_stream_get_max_payload(s: &ff->rx_stream), |
| 479 | fw_parent_device(ff->unit)->max_speed); |
| 480 | if (err < 0) |
| 481 | fw_iso_resources_free(r: &ff->tx_resources); |
| 482 | |
| 483 | return err; |
| 484 | } |
| 485 | |
| 486 | static int ff400_begin_session(struct snd_ff *ff, unsigned int rate) |
| 487 | { |
| 488 | unsigned int generation = ff->rx_resources.generation; |
| 489 | __le32 reg; |
| 490 | int err; |
| 491 | |
| 492 | if (generation != fw_parent_device(ff->unit)->card->generation) { |
| 493 | err = fw_iso_resources_update(r: &ff->tx_resources); |
| 494 | if (err < 0) |
| 495 | return err; |
| 496 | |
| 497 | err = fw_iso_resources_update(r: &ff->rx_resources); |
| 498 | if (err < 0) |
| 499 | return err; |
| 500 | } |
| 501 | |
| 502 | // Set isochronous channel and the number of quadlets of received |
| 503 | // packets. |
| 504 | reg = cpu_to_le32(((ff->rx_stream.data_block_quadlets << 3) << 8) | |
| 505 | ff->rx_resources.channel); |
| 506 | err = snd_fw_transaction(unit: ff->unit, TCODE_WRITE_QUADLET_REQUEST, |
| 507 | FF400_RX_PACKET_FORMAT, buffer: ®, length: sizeof(reg), flags: 0); |
| 508 | if (err < 0) |
| 509 | return err; |
| 510 | |
| 511 | // Set isochronous channel and the number of quadlets of transmitted |
| 512 | // packet. |
| 513 | // TODO: investigate the purpose of this 0x80. |
| 514 | reg = cpu_to_le32((0x80 << 24) | |
| 515 | (ff->tx_resources.channel << 5) | |
| 516 | (ff->tx_stream.data_block_quadlets)); |
| 517 | err = snd_fw_transaction(unit: ff->unit, TCODE_WRITE_QUADLET_REQUEST, |
| 518 | FF400_TX_PACKET_FORMAT, buffer: ®, length: sizeof(reg), flags: 0); |
| 519 | if (err < 0) |
| 520 | return err; |
| 521 | |
| 522 | // Allow to transmit packets. |
| 523 | reg = cpu_to_le32(0x00000001); |
| 524 | return snd_fw_transaction(unit: ff->unit, TCODE_WRITE_QUADLET_REQUEST, |
| 525 | FF400_ISOC_COMM_START, buffer: ®, length: sizeof(reg), flags: 0); |
| 526 | } |
| 527 | |
| 528 | static void ff400_finish_session(struct snd_ff *ff) |
| 529 | { |
| 530 | __le32 reg; |
| 531 | |
| 532 | reg = cpu_to_le32(0x80000000); |
| 533 | snd_fw_transaction(unit: ff->unit, TCODE_WRITE_QUADLET_REQUEST, |
| 534 | FF400_ISOC_COMM_STOP, buffer: ®, length: sizeof(reg), flags: 0); |
| 535 | } |
| 536 | |
| 537 | static void parse_midi_msg(struct snd_ff *ff, u32 quad, unsigned int port) |
| 538 | { |
| 539 | struct snd_rawmidi_substream *substream = READ_ONCE(ff->tx_midi_substreams[port]); |
| 540 | |
| 541 | if (substream != NULL) { |
| 542 | u8 byte = (quad >> (16 * port)) & 0x000000ff; |
| 543 | |
| 544 | snd_rawmidi_receive(substream, buffer: &byte, count: 1); |
| 545 | } |
| 546 | } |
| 547 | |
| 548 | #define FF400_QUEUE_SIZE 32 |
| 549 | |
| 550 | struct ff400_msg_parser { |
| 551 | struct { |
| 552 | u32 msg; |
| 553 | u32 tstamp; |
| 554 | } msgs[FF400_QUEUE_SIZE]; |
| 555 | size_t push_pos; |
| 556 | size_t pull_pos; |
| 557 | }; |
| 558 | |
| 559 | static bool ff400_has_msg(struct snd_ff *ff) |
| 560 | { |
| 561 | struct ff400_msg_parser *parser = ff->msg_parser; |
| 562 | |
| 563 | return (parser->push_pos != parser->pull_pos); |
| 564 | } |
| 565 | |
| 566 | // For Fireface 400, lower 4 bytes of destination address is configured by bit |
| 567 | // flag in quadlet register (little endian) at 0x'0000'801'0051c. Drivers can |
| 568 | // select one of 4 options: |
| 569 | // |
| 570 | // bit flags: offset of destination address |
| 571 | // - 0x04000000: 0x'....'....'0000'0000 |
| 572 | // - 0x08000000: 0x'....'....'0000'0080 |
| 573 | // - 0x10000000: 0x'....'....'0000'0100 |
| 574 | // - 0x20000000: 0x'....'....'0000'0180 |
| 575 | // |
| 576 | // Drivers can suppress the device to transfer asynchronous transactions by |
| 577 | // using below 2 bits. |
| 578 | // - 0x01000000: suppress transmission |
| 579 | // - 0x02000000: suppress transmission |
| 580 | // |
| 581 | // Actually, the register is write-only and includes the other options such as |
| 582 | // input attenuation. This driver allocates destination address with '0000'0000 |
| 583 | // in its lower offset and expects userspace application to configure the |
| 584 | // register for it. |
| 585 | |
| 586 | // When the message is for signal level operation, the upper 4 bits in MSB expresses the pair of |
| 587 | // stereo physical port. |
| 588 | // - 0: Microphone input 0/1 |
| 589 | // - 1: Line input 0/1 |
| 590 | // - [2-4]: Line output 0-5 |
| 591 | // - 5: Headphone output 0/1 |
| 592 | // - 6: S/PDIF output 0/1 |
| 593 | // - [7-10]: ADAT output 0-7 |
| 594 | // |
| 595 | // The value of signal level can be detected by mask of 0x00fffc00. For signal level of microphone |
| 596 | // input: |
| 597 | // |
| 598 | // - 0: 0.0 dB |
| 599 | // - 10: +10.0 dB |
| 600 | // - 11: +11.0 dB |
| 601 | // - 12: +12.0 dB |
| 602 | // - ... |
| 603 | // - 63: +63.0 dB: |
| 604 | // - 64: +64.0 dB: |
| 605 | // - 65: +65.0 dB: |
| 606 | // |
| 607 | // For signal level of line input: |
| 608 | // |
| 609 | // - 0: 0.0 dB |
| 610 | // - 1: +0.5 dB |
| 611 | // - 2: +1.0 dB |
| 612 | // - 3: +1.5 dB |
| 613 | // - ... |
| 614 | // - 34: +17.0 dB: |
| 615 | // - 35: +17.5 dB: |
| 616 | // - 36: +18.0 dB: |
| 617 | // |
| 618 | // For signal level of any type of output: |
| 619 | // |
| 620 | // - 63: -infinite |
| 621 | // - 62: -58.0 dB |
| 622 | // - 61: -56.0 dB |
| 623 | // - 60: -54.0 dB |
| 624 | // - 59: -53.0 dB |
| 625 | // - 58: -52.0 dB |
| 626 | // - ... |
| 627 | // - 7: -1.0 dB |
| 628 | // - 6: 0.0 dB |
| 629 | // - 5: +1.0 dB |
| 630 | // - ... |
| 631 | // - 2: +4.0 dB |
| 632 | // - 1: +5.0 dB |
| 633 | // - 0: +6.0 dB |
| 634 | // |
| 635 | // When the message is not for signal level operation, it's for MIDI bytes. When matching to |
| 636 | // FF400_MSG_FLAG_IS_MIDI_PORT_0, one MIDI byte can be detected by mask of 0x000000ff. When |
| 637 | // matching to FF400_MSG_FLAG_IS_MIDI_PORT_1, one MIDI byte can be detected by mask of 0x00ff0000. |
| 638 | #define FF400_MSG_FLAG_IS_SIGNAL_LEVEL 0x04000000 |
| 639 | #define FF400_MSG_FLAG_IS_RIGHT_CHANNEL 0x08000000 |
| 640 | #define FF400_MSG_FLAG_IS_STEREO_PAIRED 0x02000000 |
| 641 | #define FF400_MSG_MASK_STEREO_PAIR 0xf0000000 |
| 642 | #define FF400_MSG_MASK_SIGNAL_LEVEL 0x00fffc00 |
| 643 | #define FF400_MSG_FLAG_IS_MIDI_PORT_0 0x00000100 |
| 644 | #define FF400_MSG_MASK_MIDI_PORT_0 0x000000ff |
| 645 | #define FF400_MSG_FLAG_IS_MIDI_PORT_1 0x01000000 |
| 646 | #define FF400_MSG_MASK_MIDI_PORT_1 0x00ff0000 |
| 647 | |
| 648 | static void ff400_handle_msg(struct snd_ff *ff, unsigned int offset, const __le32 *buf, |
| 649 | size_t length, u32 tstamp) |
| 650 | { |
| 651 | bool need_hwdep_wake_up = false; |
| 652 | int i; |
| 653 | |
| 654 | for (i = 0; i < length / 4; i++) { |
| 655 | u32 quad = le32_to_cpu(buf[i]); |
| 656 | |
| 657 | if (quad & FF400_MSG_FLAG_IS_SIGNAL_LEVEL) { |
| 658 | struct ff400_msg_parser *parser = ff->msg_parser; |
| 659 | |
| 660 | parser->msgs[parser->push_pos].msg = quad; |
| 661 | parser->msgs[parser->push_pos].tstamp = tstamp; |
| 662 | ++parser->push_pos; |
| 663 | if (parser->push_pos >= FF400_QUEUE_SIZE) |
| 664 | parser->push_pos = 0; |
| 665 | |
| 666 | need_hwdep_wake_up = true; |
| 667 | } else if (quad & FF400_MSG_FLAG_IS_MIDI_PORT_0) { |
| 668 | parse_midi_msg(ff, quad, port: 0); |
| 669 | } else if (quad & FF400_MSG_FLAG_IS_MIDI_PORT_1) { |
| 670 | parse_midi_msg(ff, quad, port: 1); |
| 671 | } |
| 672 | } |
| 673 | |
| 674 | if (need_hwdep_wake_up) |
| 675 | wake_up(&ff->hwdep_wait); |
| 676 | } |
| 677 | |
| 678 | static long ff400_copy_msg_to_user(struct snd_ff *ff, char __user *buf, long count) |
| 679 | { |
| 680 | struct snd_firewire_event_ff400_message ev = { |
| 681 | .type = SNDRV_FIREWIRE_EVENT_FF400_MESSAGE, |
| 682 | .message_count = 0, |
| 683 | }; |
| 684 | struct ff400_msg_parser *parser = ff->msg_parser; |
| 685 | long consumed = 0; |
| 686 | long ret = 0; |
| 687 | |
| 688 | if (count < sizeof(ev) || parser->pull_pos == parser->push_pos) |
| 689 | return 0; |
| 690 | |
| 691 | count -= sizeof(ev); |
| 692 | consumed += sizeof(ev); |
| 693 | |
| 694 | while (count >= sizeof(*parser->msgs) && parser->pull_pos != parser->push_pos) { |
| 695 | spin_unlock_irq(lock: &ff->lock); |
| 696 | if (copy_to_user(to: buf + consumed, from: parser->msgs + parser->pull_pos, |
| 697 | n: sizeof(*parser->msgs))) |
| 698 | ret = -EFAULT; |
| 699 | spin_lock_irq(lock: &ff->lock); |
| 700 | if (ret) |
| 701 | return ret; |
| 702 | |
| 703 | ++parser->pull_pos; |
| 704 | if (parser->pull_pos >= FF400_QUEUE_SIZE) |
| 705 | parser->pull_pos = 0; |
| 706 | ++ev.message_count; |
| 707 | count -= sizeof(*parser->msgs); |
| 708 | consumed += sizeof(*parser->msgs); |
| 709 | } |
| 710 | |
| 711 | spin_unlock_irq(lock: &ff->lock); |
| 712 | if (copy_to_user(to: buf, from: &ev, n: sizeof(ev))) |
| 713 | ret = -EFAULT; |
| 714 | spin_lock_irq(lock: &ff->lock); |
| 715 | if (ret) |
| 716 | return ret; |
| 717 | |
| 718 | return consumed; |
| 719 | } |
| 720 | |
| 721 | const struct snd_ff_protocol snd_ff_protocol_ff400 = { |
| 722 | .msg_parser_size = sizeof(struct ff400_msg_parser), |
| 723 | .has_msg = ff400_has_msg, |
| 724 | .copy_msg_to_user = ff400_copy_msg_to_user, |
| 725 | .handle_msg = ff400_handle_msg, |
| 726 | .fill_midi_msg = former_fill_midi_msg, |
| 727 | .get_clock = former_get_clock, |
| 728 | .switch_fetching_mode = former_switch_fetching_mode, |
| 729 | .allocate_resources = ff400_allocate_resources, |
| 730 | .begin_session = ff400_begin_session, |
| 731 | .finish_session = ff400_finish_session, |
| 732 | .dump_status = former_dump_status, |
| 733 | }; |
| 734 | |