Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * tascam-midi.c - a part of driver for TASCAM FireWire series
0004  *
0005  * Copyright (c) 2015 Takashi Sakamoto
0006  */
0007 
0008 #include "tascam.h"
0009 
0010 static int midi_capture_open(struct snd_rawmidi_substream *substream)
0011 {
0012     /* Do nothing. */
0013     return 0;
0014 }
0015 
0016 static int midi_playback_open(struct snd_rawmidi_substream *substream)
0017 {
0018     struct snd_tscm *tscm = substream->rmidi->private_data;
0019 
0020     snd_fw_async_midi_port_init(&tscm->out_ports[substream->number]);
0021 
0022     return 0;
0023 }
0024 
0025 static int midi_capture_close(struct snd_rawmidi_substream *substream)
0026 {
0027     /* Do nothing. */
0028     return 0;
0029 }
0030 
0031 static int midi_playback_close(struct snd_rawmidi_substream *substream)
0032 {
0033     return 0;
0034 }
0035 
0036 static void midi_playback_drain(struct snd_rawmidi_substream *substream)
0037 {
0038     struct snd_tscm *tscm = substream->rmidi->private_data;
0039 
0040     snd_fw_async_midi_port_finish(&tscm->out_ports[substream->number]);
0041 }
0042 
0043 static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
0044 {
0045     struct snd_tscm *tscm = substrm->rmidi->private_data;
0046     unsigned long flags;
0047 
0048     spin_lock_irqsave(&tscm->lock, flags);
0049 
0050     if (up)
0051         tscm->tx_midi_substreams[substrm->number] = substrm;
0052     else
0053         tscm->tx_midi_substreams[substrm->number] = NULL;
0054 
0055     spin_unlock_irqrestore(&tscm->lock, flags);
0056 }
0057 
0058 static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
0059 {
0060     struct snd_tscm *tscm = substrm->rmidi->private_data;
0061     unsigned long flags;
0062 
0063     spin_lock_irqsave(&tscm->lock, flags);
0064 
0065     if (up)
0066         snd_fw_async_midi_port_run(&tscm->out_ports[substrm->number],
0067                        substrm);
0068 
0069     spin_unlock_irqrestore(&tscm->lock, flags);
0070 }
0071 
0072 int snd_tscm_create_midi_devices(struct snd_tscm *tscm)
0073 {
0074     static const struct snd_rawmidi_ops capture_ops = {
0075         .open       = midi_capture_open,
0076         .close      = midi_capture_close,
0077         .trigger    = midi_capture_trigger,
0078     };
0079     static const struct snd_rawmidi_ops playback_ops = {
0080         .open       = midi_playback_open,
0081         .close      = midi_playback_close,
0082         .drain      = midi_playback_drain,
0083         .trigger    = midi_playback_trigger,
0084     };
0085     struct snd_rawmidi *rmidi;
0086     struct snd_rawmidi_str *stream;
0087     struct snd_rawmidi_substream *subs;
0088     int err;
0089 
0090     err = snd_rawmidi_new(tscm->card, tscm->card->driver, 0,
0091                   tscm->spec->midi_playback_ports,
0092                   tscm->spec->midi_capture_ports,
0093                   &rmidi);
0094     if (err < 0)
0095         return err;
0096 
0097     snprintf(rmidi->name, sizeof(rmidi->name),
0098          "%s MIDI", tscm->card->shortname);
0099     rmidi->private_data = tscm;
0100 
0101     rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
0102     snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
0103                 &capture_ops);
0104     stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
0105 
0106     /* Set port names for MIDI input. */
0107     list_for_each_entry(subs, &stream->substreams, list) {
0108         /* TODO: support virtual MIDI ports. */
0109         if (subs->number < tscm->spec->midi_capture_ports) {
0110             /* Hardware MIDI ports. */
0111             snprintf(subs->name, sizeof(subs->name),
0112                  "%s MIDI %d",
0113                  tscm->card->shortname, subs->number + 1);
0114         }
0115     }
0116 
0117     rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
0118     snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
0119                 &playback_ops);
0120     stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
0121 
0122     /* Set port names for MIDI ourput. */
0123     list_for_each_entry(subs, &stream->substreams, list) {
0124         if (subs->number < tscm->spec->midi_playback_ports) {
0125             /* Hardware MIDI ports only. */
0126             snprintf(subs->name, sizeof(subs->name),
0127                  "%s MIDI %d",
0128                  tscm->card->shortname, subs->number + 1);
0129         }
0130     }
0131 
0132     rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
0133 
0134     return 0;
0135 }