Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * fireworks_midi.c - a part of driver for Fireworks based devices
0004  *
0005  * Copyright (c) 2009-2010 Clemens Ladisch
0006  * Copyright (c) 2013-2014 Takashi Sakamoto
0007  */
0008 #include "fireworks.h"
0009 
0010 static int midi_open(struct snd_rawmidi_substream *substream)
0011 {
0012     struct snd_efw *efw = substream->rmidi->private_data;
0013     int err;
0014 
0015     err = snd_efw_stream_lock_try(efw);
0016     if (err < 0)
0017         goto end;
0018 
0019     mutex_lock(&efw->mutex);
0020     err = snd_efw_stream_reserve_duplex(efw, 0, 0, 0);
0021     if (err >= 0) {
0022         ++efw->substreams_counter;
0023         err = snd_efw_stream_start_duplex(efw);
0024         if (err < 0)
0025             --efw->substreams_counter;
0026     }
0027     mutex_unlock(&efw->mutex);
0028     if (err < 0)
0029         snd_efw_stream_lock_release(efw);
0030 end:
0031     return err;
0032 }
0033 
0034 static int midi_close(struct snd_rawmidi_substream *substream)
0035 {
0036     struct snd_efw *efw = substream->rmidi->private_data;
0037 
0038     mutex_lock(&efw->mutex);
0039     --efw->substreams_counter;
0040     snd_efw_stream_stop_duplex(efw);
0041     mutex_unlock(&efw->mutex);
0042 
0043     snd_efw_stream_lock_release(efw);
0044     return 0;
0045 }
0046 
0047 static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
0048 {
0049     struct snd_efw *efw = substrm->rmidi->private_data;
0050     unsigned long flags;
0051 
0052     spin_lock_irqsave(&efw->lock, flags);
0053 
0054     if (up)
0055         amdtp_am824_midi_trigger(&efw->tx_stream,
0056                       substrm->number, substrm);
0057     else
0058         amdtp_am824_midi_trigger(&efw->tx_stream,
0059                       substrm->number, NULL);
0060 
0061     spin_unlock_irqrestore(&efw->lock, flags);
0062 }
0063 
0064 static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
0065 {
0066     struct snd_efw *efw = substrm->rmidi->private_data;
0067     unsigned long flags;
0068 
0069     spin_lock_irqsave(&efw->lock, flags);
0070 
0071     if (up)
0072         amdtp_am824_midi_trigger(&efw->rx_stream,
0073                      substrm->number, substrm);
0074     else
0075         amdtp_am824_midi_trigger(&efw->rx_stream,
0076                      substrm->number, NULL);
0077 
0078     spin_unlock_irqrestore(&efw->lock, flags);
0079 }
0080 
0081 static void set_midi_substream_names(struct snd_efw *efw,
0082                      struct snd_rawmidi_str *str)
0083 {
0084     struct snd_rawmidi_substream *subs;
0085 
0086     list_for_each_entry(subs, &str->substreams, list) {
0087         snprintf(subs->name, sizeof(subs->name),
0088              "%s MIDI %d", efw->card->shortname, subs->number + 1);
0089     }
0090 }
0091 
0092 int snd_efw_create_midi_devices(struct snd_efw *efw)
0093 {
0094     static const struct snd_rawmidi_ops capture_ops = {
0095         .open       = midi_open,
0096         .close      = midi_close,
0097         .trigger    = midi_capture_trigger,
0098     };
0099     static const struct snd_rawmidi_ops playback_ops = {
0100         .open       = midi_open,
0101         .close      = midi_close,
0102         .trigger    = midi_playback_trigger,
0103     };
0104     struct snd_rawmidi *rmidi;
0105     struct snd_rawmidi_str *str;
0106     int err;
0107 
0108     /* create midi ports */
0109     err = snd_rawmidi_new(efw->card, efw->card->driver, 0,
0110                   efw->midi_out_ports, efw->midi_in_ports,
0111                   &rmidi);
0112     if (err < 0)
0113         return err;
0114 
0115     snprintf(rmidi->name, sizeof(rmidi->name),
0116          "%s MIDI", efw->card->shortname);
0117     rmidi->private_data = efw;
0118 
0119     if (efw->midi_in_ports > 0) {
0120         rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
0121 
0122         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
0123                     &capture_ops);
0124 
0125         str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
0126 
0127         set_midi_substream_names(efw, str);
0128     }
0129 
0130     if (efw->midi_out_ports > 0) {
0131         rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
0132 
0133         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
0134                     &playback_ops);
0135 
0136         str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
0137 
0138         set_midi_substream_names(efw, str);
0139     }
0140 
0141     if ((efw->midi_out_ports > 0) && (efw->midi_in_ports > 0))
0142         rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
0143 
0144     return 0;
0145 }