Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * oxfw_midi.c - a part of driver for OXFW970/971 based devices
0004  *
0005  * Copyright (c) 2014 Takashi Sakamoto
0006  */
0007 
0008 #include "oxfw.h"
0009 
0010 static int midi_capture_open(struct snd_rawmidi_substream *substream)
0011 {
0012     struct snd_oxfw *oxfw = substream->rmidi->private_data;
0013     int err;
0014 
0015     err = snd_oxfw_stream_lock_try(oxfw);
0016     if (err < 0)
0017         return err;
0018 
0019     mutex_lock(&oxfw->mutex);
0020 
0021     err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream, 0, 0, 0, 0);
0022     if (err >= 0) {
0023         ++oxfw->substreams_count;
0024         err = snd_oxfw_stream_start_duplex(oxfw);
0025         if (err < 0)
0026             --oxfw->substreams_count;
0027     }
0028 
0029     mutex_unlock(&oxfw->mutex);
0030 
0031     if (err < 0)
0032         snd_oxfw_stream_lock_release(oxfw);
0033 
0034     return err;
0035 }
0036 
0037 static int midi_playback_open(struct snd_rawmidi_substream *substream)
0038 {
0039     struct snd_oxfw *oxfw = substream->rmidi->private_data;
0040     int err;
0041 
0042     err = snd_oxfw_stream_lock_try(oxfw);
0043     if (err < 0)
0044         return err;
0045 
0046     mutex_lock(&oxfw->mutex);
0047 
0048     err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->rx_stream, 0, 0, 0, 0);
0049     if (err >= 0) {
0050         ++oxfw->substreams_count;
0051         err = snd_oxfw_stream_start_duplex(oxfw);
0052     }
0053 
0054     mutex_unlock(&oxfw->mutex);
0055 
0056     if (err < 0)
0057         snd_oxfw_stream_lock_release(oxfw);
0058 
0059     return err;
0060 }
0061 
0062 static int midi_capture_close(struct snd_rawmidi_substream *substream)
0063 {
0064     struct snd_oxfw *oxfw = substream->rmidi->private_data;
0065 
0066     mutex_lock(&oxfw->mutex);
0067 
0068     --oxfw->substreams_count;
0069     snd_oxfw_stream_stop_duplex(oxfw);
0070 
0071     mutex_unlock(&oxfw->mutex);
0072 
0073     snd_oxfw_stream_lock_release(oxfw);
0074     return 0;
0075 }
0076 
0077 static int midi_playback_close(struct snd_rawmidi_substream *substream)
0078 {
0079     struct snd_oxfw *oxfw = substream->rmidi->private_data;
0080 
0081     mutex_lock(&oxfw->mutex);
0082 
0083     --oxfw->substreams_count;
0084     snd_oxfw_stream_stop_duplex(oxfw);
0085 
0086     mutex_unlock(&oxfw->mutex);
0087 
0088     snd_oxfw_stream_lock_release(oxfw);
0089     return 0;
0090 }
0091 
0092 static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
0093 {
0094     struct snd_oxfw *oxfw = substrm->rmidi->private_data;
0095     unsigned long flags;
0096 
0097     spin_lock_irqsave(&oxfw->lock, flags);
0098 
0099     if (up)
0100         amdtp_am824_midi_trigger(&oxfw->tx_stream,
0101                      substrm->number, substrm);
0102     else
0103         amdtp_am824_midi_trigger(&oxfw->tx_stream,
0104                      substrm->number, NULL);
0105 
0106     spin_unlock_irqrestore(&oxfw->lock, flags);
0107 }
0108 
0109 static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
0110 {
0111     struct snd_oxfw *oxfw = substrm->rmidi->private_data;
0112     unsigned long flags;
0113 
0114     spin_lock_irqsave(&oxfw->lock, flags);
0115 
0116     if (up)
0117         amdtp_am824_midi_trigger(&oxfw->rx_stream,
0118                      substrm->number, substrm);
0119     else
0120         amdtp_am824_midi_trigger(&oxfw->rx_stream,
0121                      substrm->number, NULL);
0122 
0123     spin_unlock_irqrestore(&oxfw->lock, flags);
0124 }
0125 
0126 static void set_midi_substream_names(struct snd_oxfw *oxfw,
0127                      struct snd_rawmidi_str *str)
0128 {
0129     struct snd_rawmidi_substream *subs;
0130 
0131     list_for_each_entry(subs, &str->substreams, list) {
0132         snprintf(subs->name, sizeof(subs->name),
0133              "%s MIDI %d",
0134              oxfw->card->shortname, subs->number + 1);
0135     }
0136 }
0137 
0138 int snd_oxfw_create_midi(struct snd_oxfw *oxfw)
0139 {
0140     static const struct snd_rawmidi_ops capture_ops = {
0141         .open       = midi_capture_open,
0142         .close      = midi_capture_close,
0143         .trigger    = midi_capture_trigger,
0144     };
0145     static const struct snd_rawmidi_ops playback_ops = {
0146         .open       = midi_playback_open,
0147         .close      = midi_playback_close,
0148         .trigger    = midi_playback_trigger,
0149     };
0150     struct snd_rawmidi *rmidi;
0151     struct snd_rawmidi_str *str;
0152     int err;
0153 
0154     if (oxfw->midi_input_ports == 0 && oxfw->midi_output_ports == 0)
0155         return 0;
0156 
0157     /* create midi ports */
0158     err = snd_rawmidi_new(oxfw->card, oxfw->card->driver, 0,
0159                   oxfw->midi_output_ports, oxfw->midi_input_ports,
0160                   &rmidi);
0161     if (err < 0)
0162         return err;
0163 
0164     snprintf(rmidi->name, sizeof(rmidi->name),
0165          "%s MIDI", oxfw->card->shortname);
0166     rmidi->private_data = oxfw;
0167 
0168     if (oxfw->midi_input_ports > 0) {
0169         rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
0170 
0171         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
0172                     &capture_ops);
0173 
0174         str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
0175 
0176         set_midi_substream_names(oxfw, str);
0177     }
0178 
0179     if (oxfw->midi_output_ports > 0) {
0180         rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
0181 
0182         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
0183                     &playback_ops);
0184 
0185         str = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
0186 
0187         set_midi_substream_names(oxfw, str);
0188     }
0189 
0190     if ((oxfw->midi_output_ports > 0) && (oxfw->midi_input_ports > 0))
0191         rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
0192 
0193     return 0;
0194 }