Back to home page

OSCL-LXR

 
 

    


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