Path: blob/master/sound/firewire/fireworks/fireworks_midi.c
26424 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* fireworks_midi.c - a part of driver for Fireworks based devices3*4* Copyright (c) 2009-2010 Clemens Ladisch5* Copyright (c) 2013-2014 Takashi Sakamoto6*/7#include "fireworks.h"89static int midi_open(struct snd_rawmidi_substream *substream)10{11struct snd_efw *efw = substream->rmidi->private_data;12int err;1314err = snd_efw_stream_lock_try(efw);15if (err < 0)16goto end;1718mutex_lock(&efw->mutex);19err = snd_efw_stream_reserve_duplex(efw, 0, 0, 0);20if (err >= 0) {21++efw->substreams_counter;22err = snd_efw_stream_start_duplex(efw);23if (err < 0)24--efw->substreams_counter;25}26mutex_unlock(&efw->mutex);27if (err < 0)28snd_efw_stream_lock_release(efw);29end:30return err;31}3233static int midi_close(struct snd_rawmidi_substream *substream)34{35struct snd_efw *efw = substream->rmidi->private_data;3637mutex_lock(&efw->mutex);38--efw->substreams_counter;39snd_efw_stream_stop_duplex(efw);40mutex_unlock(&efw->mutex);4142snd_efw_stream_lock_release(efw);43return 0;44}4546static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)47{48struct snd_efw *efw = substrm->rmidi->private_data;49unsigned long flags;5051spin_lock_irqsave(&efw->lock, flags);5253if (up)54amdtp_am824_midi_trigger(&efw->tx_stream,55substrm->number, substrm);56else57amdtp_am824_midi_trigger(&efw->tx_stream,58substrm->number, NULL);5960spin_unlock_irqrestore(&efw->lock, flags);61}6263static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)64{65struct snd_efw *efw = substrm->rmidi->private_data;66unsigned long flags;6768spin_lock_irqsave(&efw->lock, flags);6970if (up)71amdtp_am824_midi_trigger(&efw->rx_stream,72substrm->number, substrm);73else74amdtp_am824_midi_trigger(&efw->rx_stream,75substrm->number, NULL);7677spin_unlock_irqrestore(&efw->lock, flags);78}7980static void set_midi_substream_names(struct snd_efw *efw,81struct snd_rawmidi_str *str)82{83struct snd_rawmidi_substream *subs;8485list_for_each_entry(subs, &str->substreams, list) {86scnprintf(subs->name, sizeof(subs->name),87"%s MIDI %d", efw->card->shortname, subs->number + 1);88}89}9091int snd_efw_create_midi_devices(struct snd_efw *efw)92{93static const struct snd_rawmidi_ops capture_ops = {94.open = midi_open,95.close = midi_close,96.trigger = midi_capture_trigger,97};98static const struct snd_rawmidi_ops playback_ops = {99.open = midi_open,100.close = midi_close,101.trigger = midi_playback_trigger,102};103struct snd_rawmidi *rmidi;104struct snd_rawmidi_str *str;105int err;106107/* create midi ports */108err = snd_rawmidi_new(efw->card, efw->card->driver, 0,109efw->midi_out_ports, efw->midi_in_ports,110&rmidi);111if (err < 0)112return err;113114snprintf(rmidi->name, sizeof(rmidi->name),115"%s MIDI", efw->card->shortname);116rmidi->private_data = efw;117118if (efw->midi_in_ports > 0) {119rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;120121snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,122&capture_ops);123124str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];125126set_midi_substream_names(efw, str);127}128129if (efw->midi_out_ports > 0) {130rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;131132snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,133&playback_ops);134135str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];136137set_midi_substream_names(efw, str);138}139140if ((efw->midi_out_ports > 0) && (efw->midi_in_ports > 0))141rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;142143return 0;144}145146147