brintos

brintos / linux-shallow public Read only

0
0
Text · 3.5 KiB · b1425bf Raw
147 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * bebob_midi.c - a part of driver for BeBoB based devices4 *5 * Copyright (c) 2013-2014 Takashi Sakamoto6 */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	mutex_lock(&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	mutex_unlock(&bebob->mutex);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	mutex_lock(&bebob->mutex);39	bebob->substreams_counter--;40	snd_bebob_stream_stop_duplex(bebob);41	mutex_unlock(&bebob->mutex);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	unsigned long flags;51 52	spin_lock_irqsave(&bebob->lock, flags);53 54	if (up)55		amdtp_am824_midi_trigger(&bebob->tx_stream,56					 substrm->number, substrm);57	else58		amdtp_am824_midi_trigger(&bebob->tx_stream,59					 substrm->number, NULL);60 61	spin_unlock_irqrestore(&bebob->lock, flags);62}63 64static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)65{66	struct snd_bebob *bebob = substrm->rmidi->private_data;67	unsigned long flags;68 69	spin_lock_irqsave(&bebob->lock, flags);70 71	if (up)72		amdtp_am824_midi_trigger(&bebob->rx_stream,73					 substrm->number, substrm);74	else75		amdtp_am824_midi_trigger(&bebob->rx_stream,76					 substrm->number, NULL);77 78	spin_unlock_irqrestore(&bebob->lock, flags);79}80 81static void set_midi_substream_names(struct snd_bebob *bebob,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",89			  bebob->card->shortname, subs->number + 1);90	}91}92 93int snd_bebob_create_midi_devices(struct snd_bebob *bebob)94{95	static const struct snd_rawmidi_ops capture_ops = {96		.open		= midi_open,97		.close		= midi_close,98		.trigger	= midi_capture_trigger,99	};100	static const struct snd_rawmidi_ops playback_ops = {101		.open		= midi_open,102		.close		= midi_close,103		.trigger	= midi_playback_trigger,104	};105	struct snd_rawmidi *rmidi;106	struct snd_rawmidi_str *str;107	int err;108 109	/* create midi ports */110	err = snd_rawmidi_new(bebob->card, bebob->card->driver, 0,111			      bebob->midi_output_ports, bebob->midi_input_ports,112			      &rmidi);113	if (err < 0)114		return err;115 116	snprintf(rmidi->name, sizeof(rmidi->name),117		 "%s MIDI", bebob->card->shortname);118	rmidi->private_data = bebob;119 120	if (bebob->midi_input_ports > 0) {121		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;122 123		snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,124				    &capture_ops);125 126		str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];127 128		set_midi_substream_names(bebob, str);129	}130 131	if (bebob->midi_output_ports > 0) {132		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;133 134		snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,135				    &playback_ops);136 137		str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];138 139		set_midi_substream_names(bebob, str);140	}141 142	if ((bebob->midi_output_ports > 0) && (bebob->midi_input_ports > 0))143		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;144 145	return 0;146}147