brintos

brintos / linux-shallow public Read only

0
0
Text · 3.4 KiB · 350bf4d Raw
146 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * fireworks_midi.c - a part of driver for Fireworks based devices4 *5 * Copyright (c) 2009-2010 Clemens Ladisch6 * Copyright (c) 2013-2014 Takashi Sakamoto7 */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		goto end;18 19	mutex_lock(&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	mutex_unlock(&efw->mutex);28	if (err < 0)29		snd_efw_stream_lock_release(efw);30end:31	return err;32}33 34static int midi_close(struct snd_rawmidi_substream *substream)35{36	struct snd_efw *efw = substream->rmidi->private_data;37 38	mutex_lock(&efw->mutex);39	--efw->substreams_counter;40	snd_efw_stream_stop_duplex(efw);41	mutex_unlock(&efw->mutex);42 43	snd_efw_stream_lock_release(efw);44	return 0;45}46 47static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)48{49	struct snd_efw *efw = substrm->rmidi->private_data;50	unsigned long flags;51 52	spin_lock_irqsave(&efw->lock, flags);53 54	if (up)55		amdtp_am824_midi_trigger(&efw->tx_stream,56					  substrm->number, substrm);57	else58		amdtp_am824_midi_trigger(&efw->tx_stream,59					  substrm->number, NULL);60 61	spin_unlock_irqrestore(&efw->lock, flags);62}63 64static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)65{66	struct snd_efw *efw = substrm->rmidi->private_data;67	unsigned long flags;68 69	spin_lock_irqsave(&efw->lock, flags);70 71	if (up)72		amdtp_am824_midi_trigger(&efw->rx_stream,73					 substrm->number, substrm);74	else75		amdtp_am824_midi_trigger(&efw->rx_stream,76					 substrm->number, NULL);77 78	spin_unlock_irqrestore(&efw->lock, flags);79}80 81static void set_midi_substream_names(struct snd_efw *efw,82				     struct snd_rawmidi_str *str)83{84	struct snd_rawmidi_substream *subs;85 86	list_for_each_entry(subs, &str->substreams, list) {87		scnprintf(subs->name, sizeof(subs->name),88			  "%s MIDI %d", efw->card->shortname, subs->number + 1);89	}90}91 92int snd_efw_create_midi_devices(struct snd_efw *efw)93{94	static const struct snd_rawmidi_ops capture_ops = {95		.open		= midi_open,96		.close		= midi_close,97		.trigger	= midi_capture_trigger,98	};99	static const struct snd_rawmidi_ops playback_ops = {100		.open		= midi_open,101		.close		= midi_close,102		.trigger	= midi_playback_trigger,103	};104	struct snd_rawmidi *rmidi;105	struct snd_rawmidi_str *str;106	int err;107 108	/* create midi ports */109	err = snd_rawmidi_new(efw->card, efw->card->driver, 0,110			      efw->midi_out_ports, efw->midi_in_ports,111			      &rmidi);112	if (err < 0)113		return err;114 115	snprintf(rmidi->name, sizeof(rmidi->name),116		 "%s MIDI", efw->card->shortname);117	rmidi->private_data = efw;118 119	if (efw->midi_in_ports > 0) {120		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;121 122		snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,123				    &capture_ops);124 125		str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];126 127		set_midi_substream_names(efw, str);128	}129 130	if (efw->midi_out_ports > 0) {131		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;132 133		snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,134				    &playback_ops);135 136		str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];137 138		set_midi_substream_names(efw, str);139	}140 141	if ((efw->midi_out_ports > 0) && (efw->midi_in_ports > 0))142		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;143 144	return 0;145}146