2019-05-29 16:57:59 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2017-03-22 21:30:23 +09:00
/*
* motu - midi . h - a part of driver for MOTU FireWire series
*
* Copyright ( c ) 2015 - 2017 Takashi Sakamoto < o - takashi @ sakamocchi . jp >
*/
# include "motu.h"
2019-06-17 17:15:02 +09:00
static int midi_open ( struct snd_rawmidi_substream * substream )
2017-03-22 21:30:23 +09:00
{
struct snd_motu * motu = substream - > rmidi - > private_data ;
int err ;
2017-03-22 21:30:24 +09:00
err = snd_motu_stream_lock_try ( motu ) ;
if ( err < 0 )
return err ;
2017-03-22 21:30:23 +09:00
mutex_lock ( & motu - > mutex ) ;
2019-10-18 00:54:20 +09:00
err = snd_motu_stream_reserve_duplex ( motu , 0 , 0 , 0 ) ;
2019-06-17 17:15:08 +09:00
if ( err > = 0 ) {
+ + motu - > substreams_counter ;
err = snd_motu_stream_start_duplex ( motu ) ;
2019-07-07 14:20:11 +09:00
if ( err < 0 )
- - motu - > substreams_counter ;
2019-06-17 17:15:08 +09:00
}
2017-03-22 21:30:23 +09:00
mutex_unlock ( & motu - > mutex ) ;
2017-03-22 21:30:24 +09:00
if ( err < 0 )
snd_motu_stream_lock_release ( motu ) ;
2017-03-22 21:30:23 +09:00
return err ;
}
2019-06-17 17:15:02 +09:00
static int midi_close ( struct snd_rawmidi_substream * substream )
2017-03-22 21:30:23 +09:00
{
struct snd_motu * motu = substream - > rmidi - > private_data ;
mutex_lock ( & motu - > mutex ) ;
2019-06-17 17:15:08 +09:00
- - motu - > substreams_counter ;
2017-03-22 21:30:23 +09:00
snd_motu_stream_stop_duplex ( motu ) ;
mutex_unlock ( & motu - > mutex ) ;
2017-03-22 21:30:24 +09:00
snd_motu_stream_lock_release ( motu ) ;
2017-03-22 21:30:23 +09:00
return 0 ;
}
static void midi_capture_trigger ( struct snd_rawmidi_substream * substrm , int up )
{
struct snd_motu * motu = substrm - > rmidi - > private_data ;
unsigned long flags ;
spin_lock_irqsave ( & motu - > lock , flags ) ;
if ( up )
amdtp_motu_midi_trigger ( & motu - > tx_stream , substrm - > number ,
substrm ) ;
else
amdtp_motu_midi_trigger ( & motu - > tx_stream , substrm - > number ,
NULL ) ;
spin_unlock_irqrestore ( & motu - > lock , flags ) ;
}
static void midi_playback_trigger ( struct snd_rawmidi_substream * substrm , int up )
{
struct snd_motu * motu = substrm - > rmidi - > private_data ;
unsigned long flags ;
spin_lock_irqsave ( & motu - > lock , flags ) ;
if ( up )
amdtp_motu_midi_trigger ( & motu - > rx_stream , substrm - > number ,
substrm ) ;
else
amdtp_motu_midi_trigger ( & motu - > rx_stream , substrm - > number ,
NULL ) ;
spin_unlock_irqrestore ( & motu - > lock , flags ) ;
}
static void set_midi_substream_names ( struct snd_motu * motu ,
struct snd_rawmidi_str * str )
{
struct snd_rawmidi_substream * subs ;
list_for_each_entry ( subs , & str - > substreams , list ) {
snprintf ( subs - > name , sizeof ( subs - > name ) ,
" %s MIDI %d " , motu - > card - > shortname , subs - > number + 1 ) ;
}
}
int snd_motu_create_midi_devices ( struct snd_motu * motu )
{
2017-08-15 10:09:54 +02:00
static const struct snd_rawmidi_ops capture_ops = {
2019-06-17 17:15:02 +09:00
. open = midi_open ,
. close = midi_close ,
2017-03-22 21:30:23 +09:00
. trigger = midi_capture_trigger ,
} ;
2017-08-15 10:09:54 +02:00
static const struct snd_rawmidi_ops playback_ops = {
2019-06-17 17:15:02 +09:00
. open = midi_open ,
. close = midi_close ,
2017-03-22 21:30:23 +09:00
. trigger = midi_playback_trigger ,
} ;
struct snd_rawmidi * rmidi ;
struct snd_rawmidi_str * str ;
int err ;
/* create midi ports */
err = snd_rawmidi_new ( motu - > card , motu - > card - > driver , 0 , 1 , 1 , & rmidi ) ;
if ( err < 0 )
return err ;
snprintf ( rmidi - > name , sizeof ( rmidi - > name ) ,
" %s MIDI " , motu - > card - > shortname ) ;
rmidi - > private_data = motu ;
rmidi - > info_flags | = SNDRV_RAWMIDI_INFO_INPUT |
SNDRV_RAWMIDI_INFO_OUTPUT |
SNDRV_RAWMIDI_INFO_DUPLEX ;
snd_rawmidi_set_ops ( rmidi , SNDRV_RAWMIDI_STREAM_INPUT ,
& capture_ops ) ;
str = & rmidi - > streams [ SNDRV_RAWMIDI_STREAM_INPUT ] ;
set_midi_substream_names ( motu , str ) ;
snd_rawmidi_set_ops ( rmidi , SNDRV_RAWMIDI_STREAM_OUTPUT ,
& playback_ops ) ;
str = & rmidi - > streams [ SNDRV_RAWMIDI_STREAM_OUTPUT ] ;
set_midi_substream_names ( motu , str ) ;
return 0 ;
}