From 82b6297b4434d1bc523f3470be4875ab185c6663 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 22 Jan 2019 22:17:04 +0900 Subject: [PATCH] ALSA: fireface: add protocol-specific operation to fill transaction buffer with MIDI messages Between former and latter models, content of asynchronous transaction for MIDI messages from driver to device is different. This commit is a preparation to support latter models. A protocol-specific operation is added to encode MIDI messages to the transaction. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/fireface/ff-protocol-former.c | 23 +++++++++++++++++++++ sound/firewire/fireface/ff-transaction.c | 31 +++++++++++----------------- sound/firewire/fireface/ff.h | 3 +++ 3 files changed, 38 insertions(+), 19 deletions(-) diff --git a/sound/firewire/fireface/ff-protocol-former.c b/sound/firewire/fireface/ff-protocol-former.c index 266e489..e0acf40 100644 --- a/sound/firewire/fireface/ff-protocol-former.c +++ b/sound/firewire/fireface/ff-protocol-former.c @@ -263,6 +263,27 @@ static void former_dump_status(struct snd_ff *ff, dump_sync_status(ff, buffer); } +static int former_fill_midi_msg(struct snd_ff *ff, + struct snd_rawmidi_substream *substream, + unsigned int port) +{ + u8 *buf = (u8 *)ff->msg_buf[port]; + int len; + int i; + + len = snd_rawmidi_transmit_peek(substream, buf, + SND_FF_MAXIMIM_MIDI_QUADS); + if (len <= 0) + return len; + + // One quadlet includes one byte. + for (i = len - 1; i >= 0; --i) + ff->msg_buf[port][i] = cpu_to_le32(buf[i]); + ff->rx_bytes[port] = len; + + return len; +} + #define FF800_STF 0x0000fc88f000 #define FF800_RX_PACKET_FORMAT 0x0000fc88f004 #define FF800_ALLOC_TX_STREAM 0x0000fc88f008 @@ -392,6 +413,7 @@ static void ff800_handle_midi_msg(struct snd_ff *ff, unsigned int offset, const struct snd_ff_protocol snd_ff_protocol_ff800 = { .handle_midi_msg = ff800_handle_midi_msg, + .fill_midi_msg = former_fill_midi_msg, .get_clock = former_get_clock, .switch_fetching_mode = former_switch_fetching_mode, .begin_session = ff800_begin_session, @@ -543,6 +565,7 @@ static void ff400_handle_midi_msg(struct snd_ff *ff, unsigned int offset, const struct snd_ff_protocol snd_ff_protocol_ff400 = { .handle_midi_msg = ff400_handle_midi_msg, + .fill_midi_msg = former_fill_midi_msg, .get_clock = former_get_clock, .switch_fetching_mode = former_switch_fetching_mode, .begin_session = ff400_begin_session, diff --git a/sound/firewire/fireface/ff-transaction.c b/sound/firewire/fireface/ff-transaction.c index 92ca76a..d8a8b01 100644 --- a/sound/firewire/fireface/ff-transaction.c +++ b/sound/firewire/fireface/ff-transaction.c @@ -51,23 +51,17 @@ static void finish_transmit_midi1_msg(struct fw_card *card, int rcode, finish_transmit_midi_msg(ff, 1, rcode); } -static inline void fill_midi_buf(struct snd_ff *ff, unsigned int port, - unsigned int index, u8 byte) -{ - ff->msg_buf[port][index] = cpu_to_le32(byte); -} - static void transmit_midi_msg(struct snd_ff *ff, unsigned int port) { struct snd_rawmidi_substream *substream = READ_ONCE(ff->rx_midi_substreams[port]); - u8 *buf = (u8 *)ff->msg_buf[port]; - int i, len; + int quad_count; struct fw_device *fw_dev = fw_parent_device(ff->unit); unsigned long long addr; int generation; fw_transaction_callback_t callback; + int tcode; if (substream == NULL || snd_rawmidi_transmit_empty(substream)) return; @@ -81,14 +75,10 @@ static void transmit_midi_msg(struct snd_ff *ff, unsigned int port) return; } - len = snd_rawmidi_transmit_peek(substream, buf, - SND_FF_MAXIMIM_MIDI_QUADS); - if (len <= 0) + quad_count = ff->spec->protocol->fill_midi_msg(ff, substream, port); + if (quad_count <= 0) return; - for (i = len - 1; i >= 0; i--) - fill_midi_buf(ff, port, i, buf[i]); - if (port == 0) { addr = ff->spec->midi_rx_addrs[0]; callback = finish_transmit_midi0_msg; @@ -99,8 +89,12 @@ static void transmit_midi_msg(struct snd_ff *ff, unsigned int port) /* Set interval to next transaction. */ ff->next_ktime[port] = ktime_add_ns(ktime_get(), - len * 8 * NSEC_PER_SEC / 31250); - ff->rx_bytes[port] = len; + ff->rx_bytes[port] * 8 * NSEC_PER_SEC / 31250); + + if (quad_count == 1) + tcode = TCODE_WRITE_QUADLET_REQUEST; + else + tcode = TCODE_WRITE_BLOCK_REQUEST; /* * In Linux FireWire core, when generation is updated with memory @@ -112,10 +106,9 @@ static void transmit_midi_msg(struct snd_ff *ff, unsigned int port) */ generation = fw_dev->generation; smp_rmb(); - fw_send_request(fw_dev->card, &ff->transactions[port], - TCODE_WRITE_BLOCK_REQUEST, + fw_send_request(fw_dev->card, &ff->transactions[port], tcode, fw_dev->node_id, generation, fw_dev->max_speed, - addr, &ff->msg_buf[port], len * 4, + addr, &ff->msg_buf[port], quad_count * 4, callback, &ff->transactions[port]); } diff --git a/sound/firewire/fireface/ff.h b/sound/firewire/fireface/ff.h index edad75a..e52ad11 100644 --- a/sound/firewire/fireface/ff.h +++ b/sound/firewire/fireface/ff.h @@ -107,6 +107,9 @@ enum snd_ff_clock_src { struct snd_ff_protocol { void (*handle_midi_msg)(struct snd_ff *ff, unsigned int offset, __le32 *buf, size_t length); + int (*fill_midi_msg)(struct snd_ff *ff, + struct snd_rawmidi_substream *substream, + unsigned int port); int (*get_clock)(struct snd_ff *ff, unsigned int *rate, enum snd_ff_clock_src *src); int (*switch_fetching_mode)(struct snd_ff *ff, bool enable); -- 2.7.4