Commit 82b6297b authored by Takashi Sakamoto's avatar Takashi Sakamoto Committed by Takashi Iwai
Browse files

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: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 481e09ac
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -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,
+12 −19
Original line number Diff line number Diff line
@@ -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]);
}

+3 −0
Original line number Diff line number Diff line
@@ -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);