2019-05-29 16:57:59 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2014-04-25 22:45:09 +09:00
/*
* fireworks_midi . c - a part of driver for Fireworks based devices
*
* Copyright ( c ) 2009 - 2010 Clemens Ladisch
* Copyright ( c ) 2013 - 2014 Takashi Sakamoto
*/
# include "fireworks.h"
2019-06-12 17:44:09 +09:00
static int midi_open ( struct snd_rawmidi_substream * substream )
2014-04-25 22:45:09 +09:00
{
struct snd_efw * efw = substream - > rmidi - > private_data ;
2014-04-25 22:45:12 +09:00
int err ;
err = snd_efw_stream_lock_try ( efw ) ;
if ( err < 0 )
goto end ;
2014-04-25 22:45:09 +09:00
2015-11-14 16:54:50 +09:00
mutex_lock ( & efw - > mutex ) ;
2019-10-18 00:54:15 +09:00
err = snd_efw_stream_reserve_duplex ( efw , 0 , 0 , 0 ) ;
2019-06-12 17:44:11 +09:00
if ( err > = 0 ) {
+ + efw - > substreams_counter ;
err = snd_efw_stream_start_duplex ( efw ) ;
2019-07-07 14:20:07 +09:00
if ( err < 0 )
- - efw - > substreams_counter ;
2019-06-12 17:44:11 +09:00
}
2015-11-14 16:54:50 +09:00
mutex_unlock ( & efw - > mutex ) ;
2014-04-25 22:45:12 +09:00
if ( err < 0 )
snd_efw_stream_lock_release ( efw ) ;
end :
return err ;
2014-04-25 22:45:09 +09:00
}
2019-06-12 17:44:09 +09:00
static int midi_close ( struct snd_rawmidi_substream * substream )
2014-04-25 22:45:09 +09:00
{
struct snd_efw * efw = substream - > rmidi - > private_data ;
2015-11-14 16:54:50 +09:00
mutex_lock ( & efw - > mutex ) ;
2019-06-12 17:44:08 +09:00
- - efw - > substreams_counter ;
2014-04-25 22:45:09 +09:00
snd_efw_stream_stop_duplex ( efw ) ;
2015-11-14 16:54:50 +09:00
mutex_unlock ( & efw - > mutex ) ;
2014-04-25 22:45:09 +09:00
2014-04-25 22:45:12 +09:00
snd_efw_stream_lock_release ( efw ) ;
2014-04-25 22:45:09 +09:00
return 0 ;
}
static void midi_capture_trigger ( struct snd_rawmidi_substream * substrm , int up )
{
struct snd_efw * efw = substrm - > rmidi - > private_data ;
unsigned long flags ;
spin_lock_irqsave ( & efw - > lock , flags ) ;
if ( up )
2015-09-19 11:21:59 +09:00
amdtp_am824_midi_trigger ( & efw - > tx_stream ,
2014-04-25 22:45:09 +09:00
substrm - > number , substrm ) ;
else
2015-09-19 11:21:59 +09:00
amdtp_am824_midi_trigger ( & efw - > tx_stream ,
2014-04-25 22:45:09 +09:00
substrm - > number , NULL ) ;
spin_unlock_irqrestore ( & efw - > lock , flags ) ;
}
static void midi_playback_trigger ( struct snd_rawmidi_substream * substrm , int up )
{
struct snd_efw * efw = substrm - > rmidi - > private_data ;
unsigned long flags ;
spin_lock_irqsave ( & efw - > lock , flags ) ;
if ( up )
2015-09-19 11:21:59 +09:00
amdtp_am824_midi_trigger ( & efw - > rx_stream ,
substrm - > number , substrm ) ;
2014-04-25 22:45:09 +09:00
else
2015-09-19 11:21:59 +09:00
amdtp_am824_midi_trigger ( & efw - > rx_stream ,
substrm - > number , NULL ) ;
2014-04-25 22:45:09 +09:00
spin_unlock_irqrestore ( & efw - > lock , flags ) ;
}
static void set_midi_substream_names ( struct snd_efw * efw ,
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 " , efw - > card - > shortname , subs - > number + 1 ) ;
}
}
int snd_efw_create_midi_devices ( struct snd_efw * efw )
{
2017-01-05 17:29:54 +01:00
static const struct snd_rawmidi_ops capture_ops = {
2019-06-12 17:44:09 +09:00
. open = midi_open ,
. close = midi_close ,
2017-01-05 21:48:08 +09:00
. trigger = midi_capture_trigger ,
} ;
2017-01-05 17:29:54 +01:00
static const struct snd_rawmidi_ops playback_ops = {
2019-06-12 17:44:09 +09:00
. open = midi_open ,
. close = midi_close ,
2017-01-05 21:48:08 +09:00
. trigger = midi_playback_trigger ,
} ;
2014-04-25 22:45:09 +09:00
struct snd_rawmidi * rmidi ;
struct snd_rawmidi_str * str ;
int err ;
/* create midi ports */
err = snd_rawmidi_new ( efw - > card , efw - > card - > driver , 0 ,
efw - > midi_out_ports , efw - > midi_in_ports ,
& rmidi ) ;
if ( err < 0 )
return err ;
snprintf ( rmidi - > name , sizeof ( rmidi - > name ) ,
" %s MIDI " , efw - > card - > shortname ) ;
rmidi - > private_data = efw ;
if ( efw - > midi_in_ports > 0 ) {
rmidi - > info_flags | = SNDRV_RAWMIDI_INFO_INPUT ;
snd_rawmidi_set_ops ( rmidi , SNDRV_RAWMIDI_STREAM_INPUT ,
2017-01-05 21:48:08 +09:00
& capture_ops ) ;
2014-04-25 22:45:09 +09:00
str = & rmidi - > streams [ SNDRV_RAWMIDI_STREAM_INPUT ] ;
set_midi_substream_names ( efw , str ) ;
}
if ( efw - > midi_out_ports > 0 ) {
rmidi - > info_flags | = SNDRV_RAWMIDI_INFO_OUTPUT ;
snd_rawmidi_set_ops ( rmidi , SNDRV_RAWMIDI_STREAM_OUTPUT ,
2017-01-05 21:48:08 +09:00
& playback_ops ) ;
2014-04-25 22:45:09 +09:00
str = & rmidi - > streams [ SNDRV_RAWMIDI_STREAM_OUTPUT ] ;
set_midi_substream_names ( efw , str ) ;
}
if ( ( efw - > midi_out_ports > 0 ) & & ( efw - > midi_in_ports > 0 ) )
rmidi - > info_flags | = SNDRV_RAWMIDI_INFO_DUPLEX ;
return 0 ;
}