brintos

brintos / linux-shallow public Read only

0
0
Text · 3.2 KiB · da3054f Raw
129 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * ff-midi.c - a part of driver for RME Fireface series4 *5 * Copyright (c) 2015-2017 Takashi Sakamoto6 */7 8#include "ff.h"9 10static int midi_capture_open(struct snd_rawmidi_substream *substream)11{12	/* Do nothing. */13	return 0;14}15 16static int midi_playback_open(struct snd_rawmidi_substream *substream)17{18	struct snd_ff *ff = substream->rmidi->private_data;19 20	/* Initialize internal status. */21	ff->on_sysex[substream->number] = 0;22	ff->rx_midi_error[substream->number] = false;23 24	WRITE_ONCE(ff->rx_midi_substreams[substream->number], substream);25 26	return 0;27}28 29static int midi_capture_close(struct snd_rawmidi_substream *substream)30{31	/* Do nothing. */32	return 0;33}34 35static int midi_playback_close(struct snd_rawmidi_substream *substream)36{37	struct snd_ff *ff = substream->rmidi->private_data;38 39	cancel_work_sync(&ff->rx_midi_work[substream->number]);40	WRITE_ONCE(ff->rx_midi_substreams[substream->number], NULL);41 42	return 0;43}44 45static void midi_capture_trigger(struct snd_rawmidi_substream *substream,46				 int up)47{48	struct snd_ff *ff = substream->rmidi->private_data;49	unsigned long flags;50 51	spin_lock_irqsave(&ff->lock, flags);52 53	if (up)54		WRITE_ONCE(ff->tx_midi_substreams[substream->number],55			   substream);56	else57		WRITE_ONCE(ff->tx_midi_substreams[substream->number], NULL);58 59	spin_unlock_irqrestore(&ff->lock, flags);60}61 62static void midi_playback_trigger(struct snd_rawmidi_substream *substream,63				  int up)64{65	struct snd_ff *ff = substream->rmidi->private_data;66	unsigned long flags;67 68	spin_lock_irqsave(&ff->lock, flags);69 70	if (up || !ff->rx_midi_error[substream->number])71		schedule_work(&ff->rx_midi_work[substream->number]);72 73	spin_unlock_irqrestore(&ff->lock, flags);74}75 76static void set_midi_substream_names(struct snd_rawmidi_str *stream,77				     const char *const name)78{79	struct snd_rawmidi_substream *substream;80 81	list_for_each_entry(substream, &stream->substreams, list) {82		scnprintf(substream->name, sizeof(substream->name),83			  "%s MIDI %d", name, substream->number + 1);84	}85}86 87int snd_ff_create_midi_devices(struct snd_ff *ff)88{89	static const struct snd_rawmidi_ops midi_capture_ops = {90		.open		= midi_capture_open,91		.close		= midi_capture_close,92		.trigger	= midi_capture_trigger,93	};94	static const struct snd_rawmidi_ops midi_playback_ops = {95		.open		= midi_playback_open,96		.close		= midi_playback_close,97		.trigger	= midi_playback_trigger,98	};99	struct snd_rawmidi *rmidi;100	struct snd_rawmidi_str *stream;101	int err;102 103	err = snd_rawmidi_new(ff->card, ff->card->driver, 0,104			      ff->spec->midi_out_ports, ff->spec->midi_in_ports,105			      &rmidi);106	if (err < 0)107		return err;108 109	snprintf(rmidi->name, sizeof(rmidi->name),110		 "%s MIDI", ff->card->shortname);111	rmidi->private_data = ff;112 113	rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;114	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,115			    &midi_capture_ops);116	stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];117	set_midi_substream_names(stream, ff->card->shortname);118 119	rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;120	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,121			    &midi_playback_ops);122	stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];123	set_midi_substream_names(stream, ff->card->shortname);124 125	rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;126 127	return 0;128}129