brintos

brintos / linux-shallow public Read only

0
0
Text · 19.2 KiB · efd59e9 Raw
734 lines · c
1// SPDX-License-Identifier: GPL-2.02// ff-protocol-former.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 FORMER_REG_SYNC_STATUS		0x0000801c0000ull11/* For block write request. */12#define FORMER_REG_FETCH_PCM_FRAMES	0x0000801c0000ull13#define FORMER_REG_CLOCK_CONFIG		0x0000801c0004ull14 15static 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 71static 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(ff->unit, TCODE_READ_QUADLET_REQUEST,79				 FORMER_REG_CLOCK_CONFIG, &reg, sizeof(reg), 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 87static 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 data105		 * blocks in reverse order. Precisely, quadlets for available106		 * data channels should be enabled. Here, I take second best107		 * to fetch PCM frames from all of data channels regardless of108		 * stf.109		 */110		for (i = 0; i < count; ++i)111			reg[i] = cpu_to_le32(0x00000001);112	}113 114	err = snd_fw_transaction(ff->unit, TCODE_WRITE_BLOCK_REQUEST,115				 FORMER_REG_FETCH_PCM_FRAMES, reg,116				 sizeof(__le32) * count, 0);117	kfree(reg);118	return err;119}120 121static 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(ff->unit, TCODE_READ_BLOCK_REQUEST,131				 FORMER_REG_CLOCK_CONFIG, &reg, sizeof(reg), 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		    (data & 0x00000040) ? "on" : "off");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		    (data & 0x00002000) ? "on" : "off");145 146	snd_iprintf(buffer, "S/PDIF input interface: %s\n",147		    (data & 0x00000200) ? "Optical" : "Coaxial");148 149	err = parse_clock_bits(data, &rate, &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 159static 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(ff->unit, TCODE_READ_BLOCK_REQUEST,201				 FORMER_REG_SYNC_STATUS, reg, sizeof(reg), 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			else217				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 257static 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 264static 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, 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		0x0000fc88f000286#define FF800_RX_PACKET_FORMAT	0x0000fc88f004287#define FF800_ALLOC_TX_STREAM	0x0000fc88f008288#define FF800_ISOC_COMM_START	0x0000fc88f00c289#define   FF800_TX_S800_FLAG	0x00000800290#define FF800_ISOC_COMM_STOP	0x0000fc88f010291 292#define FF800_TX_PACKET_ISOC_CH	0x0000801c0008293 294static 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(ff->unit, TCODE_WRITE_QUADLET_REQUEST,303				 FF800_ALLOC_TX_STREAM, &reg, sizeof(reg), 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(ff->unit, TCODE_READ_QUADLET_REQUEST,312				FF800_TX_PACKET_ISOC_CH, &reg, sizeof(reg), 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(50);323	}324	if (count >= 10)325		return -ETIMEDOUT;326 327	// NOTE: this is a makeshift to start OHCI 1394 IR context in the328	// channel. On the other hand, 'struct fw_iso_resources.allocated' is329	// not true and it's not deallocated at stop.330	ff->tx_resources.channel = tx_isoc_channel;331 332	return 0;333}334 335static 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(ff->unit, TCODE_WRITE_QUADLET_REQUEST,343				 FF800_STF, &reg, sizeof(reg), 0);344	if (err < 0)345		return err;346 347	// If starting isochronous communication immediately, change of STF has348	// no effect. In this case, the communication runs based on former STF.349	// Let's sleep for a bit.350	msleep(100);351 352	// Controllers should allocate isochronous resources for rx stream.353	err = fw_iso_resources_allocate(&ff->rx_resources,354				amdtp_stream_get_max_payload(&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 avoid361	// 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(ff->unit, TCODE_WRITE_QUADLET_REQUEST,366				 FF800_RX_PACKET_FORMAT, &reg, sizeof(reg), 0);367	if (err < 0)368		return err;369 370	return allocate_tx_resources(ff);371}372 373static 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(&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(ff->unit, TCODE_WRITE_QUADLET_REQUEST,389				 FF800_ISOC_COMM_START, &reg, sizeof(reg), 0);390}391 392static void ff800_finish_session(struct snd_ff *ff)393{394	__le32 reg;395 396	reg = cpu_to_le32(0x80000000);397	snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,398			   FF800_ISOC_COMM_STOP, &reg, sizeof(reg), 0);399}400 401// Fireface 800 doesn't allow drivers to register lower 4 bytes of destination402// address.403// A write transaction to clear registered higher 4 bytes of destination address404// has an effect to suppress asynchronous transaction from device.405static 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, &byte, 1);417	}418}419 420const 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		0x000080100500ull432#define FF400_RX_PACKET_FORMAT	0x000080100504ull433#define FF400_ISOC_COMM_START	0x000080100508ull434#define FF400_TX_PACKET_FORMAT	0x00008010050cull435#define FF400_ISOC_COMM_STOP	0x000080100510ull436 437// Fireface 400 manages isochronous channel number in 3 bit field. Therefore,438// we can allocate between 0 and 7 channel.439static 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(ff->unit, TCODE_WRITE_QUADLET_REQUEST,457				 FF400_STF, &reg, sizeof(reg), 0);458	if (err < 0)459		return err;460 461	msleep(100);462 463	err = snd_ff_stream_get_multiplier_mode(i, &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(&ff->tx_resources,470			amdtp_stream_get_max_payload(&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(&ff->rx_resources,478			amdtp_stream_get_max_payload(&ff->rx_stream),479			fw_parent_device(ff->unit)->max_speed);480	if (err < 0)481		fw_iso_resources_free(&ff->tx_resources);482 483	return err;484}485 486static 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(&ff->tx_resources);494		if (err < 0)495			return err;496 497		err = fw_iso_resources_update(&ff->rx_resources);498		if (err < 0)499			return err;500	}501 502	// Set isochronous channel and the number of quadlets of received503	// packets.504	reg = cpu_to_le32(((ff->rx_stream.data_block_quadlets << 3) << 8) |505			  ff->rx_resources.channel);506	err = snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,507				 FF400_RX_PACKET_FORMAT, &reg, sizeof(reg), 0);508	if (err < 0)509		return err;510 511	// Set isochronous channel and the number of quadlets of transmitted512	// 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(ff->unit, TCODE_WRITE_QUADLET_REQUEST,518				 FF400_TX_PACKET_FORMAT, &reg, sizeof(reg), 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(ff->unit, TCODE_WRITE_QUADLET_REQUEST,525				 FF400_ISOC_COMM_START, &reg, sizeof(reg), 0);526}527 528static void ff400_finish_session(struct snd_ff *ff)529{530	__le32 reg;531 532	reg = cpu_to_le32(0x80000000);533	snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,534			   FF400_ISOC_COMM_STOP, &reg, sizeof(reg), 0);535}536 537static 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, &byte, 1);545	}546}547 548#define FF400_QUEUE_SIZE	32549 550struct 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 559static 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 bit567// flag in quadlet register (little endian) at 0x'0000'801'0051c. Drivers can568// select one of 4 options:569//570// bit flags: offset of destination address571//  - 0x04000000: 0x'....'....'0000'0000572//  - 0x08000000: 0x'....'....'0000'0080573//  - 0x10000000: 0x'....'....'0000'0100574//  - 0x20000000: 0x'....'....'0000'0180575//576// Drivers can suppress the device to transfer asynchronous transactions by577// using below 2 bits.578//  - 0x01000000: suppress transmission579//  - 0x02000000: suppress transmission580//581// Actually, the register is write-only and includes the other options such as582// input attenuation. This driver allocates destination address with '0000'0000583// in its lower offset and expects userspace application to configure the584// register for it.585 586// When the message is for signal level operation, the upper 4 bits in MSB expresses the pair of587// stereo physical port.588// - 0: Microphone input 0/1589// - 1: Line input 0/1590// - [2-4]: Line output 0-5591// - 5: Headphone output 0/1592// - 6: S/PDIF output 0/1593// - [7-10]: ADAT output 0-7594//595// The value of signal level can be detected by mask of 0x00fffc00. For signal level of microphone596// input:597//598// - 0:    0.0 dB599// - 10: +10.0 dB600// - 11: +11.0 dB601// - 12: +12.0 dB602// - ...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 dB610// - 1: +0.5 dB611// - 2: +1.0 dB612// - 3: +1.5 dB613// - ...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: -infinite621// - 62: -58.0 dB622// - 61: -56.0 dB623// - 60: -54.0 dB624// - 59: -53.0 dB625// - 58: -52.0 dB626// - ...627// - 7: -1.0 dB628// - 6:  0.0 dB629// - 5: +1.0 dB630// - ...631// - 2: +4.0 dB632// - 1: +5.0 dB633// - 0: +6.0 dB634//635// When the message is not for signal level operation, it's for MIDI bytes. When matching to636// FF400_MSG_FLAG_IS_MIDI_PORT_0, one MIDI byte can be detected by mask of 0x000000ff. When637// 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		0x04000000639#define  FF400_MSG_FLAG_IS_RIGHT_CHANNEL	0x08000000640#define  FF400_MSG_FLAG_IS_STEREO_PAIRED	0x02000000641#define  FF400_MSG_MASK_STEREO_PAIR		0xf0000000642#define  FF400_MSG_MASK_SIGNAL_LEVEL		0x00fffc00643#define FF400_MSG_FLAG_IS_MIDI_PORT_0		0x00000100644#define  FF400_MSG_MASK_MIDI_PORT_0		0x000000ff645#define FF400_MSG_FLAG_IS_MIDI_PORT_1		0x01000000646#define  FF400_MSG_MASK_MIDI_PORT_1		0x00ff0000647 648static 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, 0);669		} else if (quad & FF400_MSG_FLAG_IS_MIDI_PORT_1) {670			parse_midi_msg(ff, quad, 1);671		}672	}673 674	if (need_hwdep_wake_up)675		wake_up(&ff->hwdep_wait);676}677 678static 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(&ff->lock);696		if (copy_to_user(buf + consumed, parser->msgs + parser->pull_pos,697				 sizeof(*parser->msgs)))698			ret = -EFAULT;699		spin_lock_irq(&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(&ff->lock);712	if (copy_to_user(buf, &ev, sizeof(ev)))713		ret = -EFAULT;714	spin_lock_irq(&ff->lock);715	if (ret)716		return ret;717 718	return consumed;719}720 721const 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