File Index
Files and directories
Sign in
FILE

bebob_midi.c

File preview with syntax highlighting.

linux-6.19.14/sound/firewire/bebob/bebob_midi.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * bebob_midi.c - a part of driver for BeBoB based devices
  4 *
  5 * Copyright (c) 2013-2014 Takashi Sakamoto
  6 */
  7
  8#include "bebob.h"
  9
 10static int midi_open(struct snd_rawmidi_substream *substream)
 11{
 12	struct snd_bebob *bebob = substream->rmidi->private_data;
 13	int err;
 14
 15	err = snd_bebob_stream_lock_try(bebob);
 16	if (err < 0)
 17		return err;
 18
 19	scoped_guard(mutex, &bebob->mutex) {
 20		err = snd_bebob_stream_reserve_duplex(bebob, 0, 0, 0);
 21		if (err >= 0) {
 22			++bebob->substreams_counter;
 23			err = snd_bebob_stream_start_duplex(bebob);
 24			if (err < 0)
 25				--bebob->substreams_counter;
 26		}
 27	}
 28	if (err < 0)
 29		snd_bebob_stream_lock_release(bebob);
 30
 31	return err;
 32}
 33
 34static int midi_close(struct snd_rawmidi_substream *substream)
 35{
 36	struct snd_bebob *bebob = substream->rmidi->private_data;
 37
 38	scoped_guard(mutex, &bebob->mutex) {
 39		bebob->substreams_counter--;
 40		snd_bebob_stream_stop_duplex(bebob);
 41	}
 42
 43	snd_bebob_stream_lock_release(bebob);
 44	return 0;
 45}
 46
 47static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
 48{
 49	struct snd_bebob *bebob = substrm->rmidi->private_data;
 50
 51	guard(spinlock_irqsave)(&bebob->lock);
 52
 53	if (up)
 54		amdtp_am824_midi_trigger(&bebob->tx_stream,
 55					 substrm->number, substrm);
 56	else
 57		amdtp_am824_midi_trigger(&bebob->tx_stream,
 58					 substrm->number, NULL);
 59}
 60
 61static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
 62{
 63	struct snd_bebob *bebob = substrm->rmidi->private_data;
 64
 65	guard(spinlock_irqsave)(&bebob->lock);
 66
 67	if (up)
 68		amdtp_am824_midi_trigger(&bebob->rx_stream,
 69					 substrm->number, substrm);
 70	else
 71		amdtp_am824_midi_trigger(&bebob->rx_stream,
 72					 substrm->number, NULL);
 73}
 74
 75static void set_midi_substream_names(struct snd_bebob *bebob,
 76				     struct snd_rawmidi_str *str)
 77{
 78	struct snd_rawmidi_substream *subs;
 79
 80	list_for_each_entry(subs, &str->substreams, list) {
 81		scnprintf(subs->name, sizeof(subs->name),
 82			  "%s MIDI %d",
 83			  bebob->card->shortname, subs->number + 1);
 84	}
 85}
 86
 87int snd_bebob_create_midi_devices(struct snd_bebob *bebob)
 88{
 89	static const struct snd_rawmidi_ops capture_ops = {
 90		.open		= midi_open,
 91		.close		= midi_close,
 92		.trigger	= midi_capture_trigger,
 93	};
 94	static const struct snd_rawmidi_ops playback_ops = {
 95		.open		= midi_open,
 96		.close		= midi_close,
 97		.trigger	= midi_playback_trigger,
 98	};
 99	struct snd_rawmidi *rmidi;
100	struct snd_rawmidi_str *str;
101	int err;
102
103	/* create midi ports */
104	err = snd_rawmidi_new(bebob->card, bebob->card->driver, 0,
105			      bebob->midi_output_ports, bebob->midi_input_ports,
106			      &rmidi);
107	if (err < 0)
108		return err;
109
110	snprintf(rmidi->name, sizeof(rmidi->name),
111		 "%s MIDI", bebob->card->shortname);
112	rmidi->private_data = bebob;
113
114	if (bebob->midi_input_ports > 0) {
115		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
116
117		snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
118				    &capture_ops);
119
120		str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
121
122		set_midi_substream_names(bebob, str);
123	}
124
125	if (bebob->midi_output_ports > 0) {
126		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
127
128		snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
129				    &playback_ops);
130
131		str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
132
133		set_midi_substream_names(bebob, str);
134	}
135
136	if ((bebob->midi_output_ports > 0) && (bebob->midi_input_ports > 0))
137		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
138
139	return 0;
140}
~/ Read-only file preview.