File Index
Files and directories
Sign in
FILE

fireworks_midi.c

File preview with syntax highlighting.

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