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 // Licensed under the terms of the GNU General Public License, version 2. 7 8 #include <linux/delay.h> 9 10 #include "ff.h" 11 12 #define FF800_STF 0x0000fc88f000 13 #define FF800_RX_PACKET_FORMAT 0x0000fc88f004 14 #define FF800_ALLOC_TX_STREAM 0x0000fc88f008 15 #define FF800_ISOC_COMM_START 0x0000fc88f00c 16 #define FF800_TX_S800_FLAG 0x00000800 17 #define FF800_ISOC_COMM_STOP 0x0000fc88f010 18 19 #define FF800_TX_PACKET_ISOC_CH 0x0000801c0008 20 21 static int allocate_rx_resources(struct snd_ff *ff) 22 { 23 u32 data; 24 __le32 reg; 25 int err; 26 27 // Controllers should allocate isochronous resources for rx stream. 28 err = fw_iso_resources_allocate(&ff->rx_resources, 29 amdtp_stream_get_max_payload(&ff->rx_stream), 30 fw_parent_device(ff->unit)->max_speed); 31 if (err < 0) 32 return err; 33 34 // Set isochronous channel and the number of quadlets of rx packets. 35 data = ff->rx_stream.data_block_quadlets << 3; 36 data = (data << 8) | ff->rx_resources.channel; 37 reg = cpu_to_le32(data); 38 return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST, 39 FF800_RX_PACKET_FORMAT, ®, sizeof(reg), 0); 40 } 41 42 static int allocate_tx_resources(struct snd_ff *ff) 43 { 44 __le32 reg; 45 unsigned int count; 46 unsigned int tx_isoc_channel; 47 int err; 48 49 reg = cpu_to_le32(ff->tx_stream.data_block_quadlets); 50 err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST, 51 FF800_ALLOC_TX_STREAM, ®, sizeof(reg), 0); 52 if (err < 0) 53 return err; 54 55 // Wait till the format of tx packet is available. 56 count = 0; 57 while (count++ < 10) { 58 u32 data; 59 err = snd_fw_transaction(ff->unit, TCODE_READ_QUADLET_REQUEST, 60 FF800_TX_PACKET_ISOC_CH, ®, sizeof(reg), 0); 61 if (err < 0) 62 return err; 63 64 data = le32_to_cpu(reg); 65 if (data != 0xffffffff) { 66 tx_isoc_channel = data; 67 break; 68 } 69 70 msleep(50); 71 } 72 if (count >= 10) 73 return -ETIMEDOUT; 74 75 // NOTE: this is a makeshift to start OHCI 1394 IR context in the 76 // channel. On the other hand, 'struct fw_iso_resources.allocated' is 77 // not true and it's not deallocated at stop. 78 ff->tx_resources.channel = tx_isoc_channel; 79 80 return 0; 81 } 82 83 static int ff800_begin_session(struct snd_ff *ff, unsigned int rate) 84 { 85 __le32 reg; 86 int err; 87 88 reg = cpu_to_le32(rate); 89 err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST, 90 FF800_STF, ®, sizeof(reg), 0); 91 if (err < 0) 92 return err; 93 94 // If starting isochronous communication immediately, change of STF has 95 // no effect. In this case, the communication runs based on former STF. 96 // Let's sleep for a bit. 97 msleep(100); 98 99 err = allocate_rx_resources(ff); 100 if (err < 0) 101 return err; 102 103 err = allocate_tx_resources(ff); 104 if (err < 0) 105 return err; 106 107 reg = cpu_to_le32(0x80000000); 108 reg |= cpu_to_le32(ff->tx_stream.data_block_quadlets); 109 if (fw_parent_device(ff->unit)->max_speed == SCODE_800) 110 reg |= cpu_to_le32(FF800_TX_S800_FLAG); 111 return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST, 112 FF800_ISOC_COMM_START, ®, sizeof(reg), 0); 113 } 114 115 static void ff800_finish_session(struct snd_ff *ff) 116 { 117 __le32 reg; 118 119 reg = cpu_to_le32(0x80000000); 120 snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST, 121 FF800_ISOC_COMM_STOP, ®, sizeof(reg), 0); 122 } 123 124 static void ff800_handle_midi_msg(struct snd_ff *ff, __le32 *buf, size_t length) 125 { 126 int i; 127 128 for (i = 0; i < length / 4; i++) { 129 u8 byte = le32_to_cpu(buf[i]) & 0xff; 130 struct snd_rawmidi_substream *substream; 131 132 substream = READ_ONCE(ff->tx_midi_substreams[0]); 133 if (substream) 134 snd_rawmidi_receive(substream, &byte, 1); 135 } 136 } 137 138 const struct snd_ff_protocol snd_ff_protocol_ff800 = { 139 .handle_midi_msg = ff800_handle_midi_msg, 140 .begin_session = ff800_begin_session, 141 .finish_session = ff800_finish_session, 142 }; 143