Path: blob/master/sound/firewire/fireworks/fireworks_midi.c
29269 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)16return err;1718scoped_guard(mutex, &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}26}27if (err < 0)28snd_efw_stream_lock_release(efw);29return err;30}3132static int midi_close(struct snd_rawmidi_substream *substream)33{34struct snd_efw *efw = substream->rmidi->private_data;3536scoped_guard(mutex, &efw->mutex) {37--efw->substreams_counter;38snd_efw_stream_stop_duplex(efw);39}4041snd_efw_stream_lock_release(efw);42return 0;43}4445static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)46{47struct snd_efw *efw = substrm->rmidi->private_data;4849guard(spinlock_irqsave)(&efw->lock);5051if (up)52amdtp_am824_midi_trigger(&efw->tx_stream,53substrm->number, substrm);54else55amdtp_am824_midi_trigger(&efw->tx_stream,56substrm->number, NULL);57}5859static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)60{61struct snd_efw *efw = substrm->rmidi->private_data;6263guard(spinlock_irqsave)(&efw->lock);6465if (up)66amdtp_am824_midi_trigger(&efw->rx_stream,67substrm->number, substrm);68else69amdtp_am824_midi_trigger(&efw->rx_stream,70substrm->number, NULL);71}7273static void set_midi_substream_names(struct snd_efw *efw,74struct snd_rawmidi_str *str)75{76struct snd_rawmidi_substream *subs;7778list_for_each_entry(subs, &str->substreams, list) {79scnprintf(subs->name, sizeof(subs->name),80"%s MIDI %d", efw->card->shortname, subs->number + 1);81}82}8384int snd_efw_create_midi_devices(struct snd_efw *efw)85{86static const struct snd_rawmidi_ops capture_ops = {87.open = midi_open,88.close = midi_close,89.trigger = midi_capture_trigger,90};91static const struct snd_rawmidi_ops playback_ops = {92.open = midi_open,93.close = midi_close,94.trigger = midi_playback_trigger,95};96struct snd_rawmidi *rmidi;97struct snd_rawmidi_str *str;98int err;99100/* create midi ports */101err = snd_rawmidi_new(efw->card, efw->card->driver, 0,102efw->midi_out_ports, efw->midi_in_ports,103&rmidi);104if (err < 0)105return err;106107snprintf(rmidi->name, sizeof(rmidi->name),108"%s MIDI", efw->card->shortname);109rmidi->private_data = efw;110111if (efw->midi_in_ports > 0) {112rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;113114snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,115&capture_ops);116117str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];118119set_midi_substream_names(efw, str);120}121122if (efw->midi_out_ports > 0) {123rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;124125snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,126&playback_ops);127128str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];129130set_midi_substream_names(efw, str);131}132133if ((efw->midi_out_ports > 0) && (efw->midi_in_ports > 0))134rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;135136return 0;137}138139140