2019-05-30 02:57:59 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2015-10-11 06:30:16 +03:00
/*
* digi00x - midi . h - a part of driver for Digidesign Digi 002 / 003 family
*
* Copyright ( c ) 2014 - 2015 Takashi Sakamoto
*/
# include "digi00x.h"
2017-04-02 17:48:26 +03:00
static int midi_open ( struct snd_rawmidi_substream * substream )
2015-10-11 06:30:16 +03:00
{
struct snd_dg00x * dg00x = substream - > rmidi - > private_data ;
int err ;
err = snd_dg00x_stream_lock_try ( dg00x ) ;
if ( err < 0 )
return err ;
mutex_lock ( & dg00x - > mutex ) ;
2019-10-17 18:54:18 +03:00
err = snd_dg00x_stream_reserve_duplex ( dg00x , 0 , 0 , 0 ) ;
2019-06-11 16:21:11 +03:00
if ( err > = 0 ) {
+ + dg00x - > substreams_counter ;
err = snd_dg00x_stream_start_duplex ( dg00x ) ;
2019-07-07 08:20:10 +03:00
if ( err < 0 )
- - dg00x - > substreams_counter ;
2019-06-11 16:21:11 +03:00
}
2015-10-11 06:30:16 +03:00
mutex_unlock ( & dg00x - > mutex ) ;
if ( err < 0 )
snd_dg00x_stream_lock_release ( dg00x ) ;
return err ;
}
2017-04-02 17:48:26 +03:00
static int midi_close ( struct snd_rawmidi_substream * substream )
2015-10-11 06:30:16 +03:00
{
struct snd_dg00x * dg00x = substream - > rmidi - > private_data ;
mutex_lock ( & dg00x - > mutex ) ;
2019-06-11 16:21:11 +03:00
- - dg00x - > substreams_counter ;
2015-10-11 06:30:16 +03:00
snd_dg00x_stream_stop_duplex ( dg00x ) ;
mutex_unlock ( & dg00x - > mutex ) ;
snd_dg00x_stream_lock_release ( dg00x ) ;
return 0 ;
}
2017-04-02 17:48:26 +03:00
static void midi_capture_trigger ( struct snd_rawmidi_substream * substream ,
int up )
2015-10-11 06:30:16 +03:00
{
2015-10-30 20:43:14 +03:00
struct snd_dg00x * dg00x = substream - > rmidi - > private_data ;
2017-04-02 17:48:26 +03:00
unsigned int port ;
2015-10-11 06:30:16 +03:00
unsigned long flags ;
2017-04-02 17:48:26 +03:00
if ( substream - > rmidi - > device = = 0 )
port = substream - > number ;
2015-10-30 20:43:16 +03:00
else
2017-04-02 17:48:26 +03:00
port = 2 ;
2015-10-11 06:30:16 +03:00
spin_lock_irqsave ( & dg00x - > lock , flags ) ;
2015-10-30 20:43:16 +03:00
if ( up )
2017-04-02 17:48:26 +03:00
amdtp_dot_midi_trigger ( & dg00x - > tx_stream , port , substream ) ;
2015-10-30 20:43:16 +03:00
else
2017-04-02 17:48:26 +03:00
amdtp_dot_midi_trigger ( & dg00x - > tx_stream , port , NULL ) ;
2015-10-11 06:30:16 +03:00
spin_unlock_irqrestore ( & dg00x - > lock , flags ) ;
}
2017-04-02 17:48:26 +03:00
static void midi_playback_trigger ( struct snd_rawmidi_substream * substream ,
int up )
2015-10-30 20:43:15 +03:00
{
struct snd_dg00x * dg00x = substream - > rmidi - > private_data ;
2017-04-02 17:48:26 +03:00
unsigned int port ;
2015-10-30 20:43:15 +03:00
unsigned long flags ;
2017-04-02 17:48:26 +03:00
if ( substream - > rmidi - > device = = 0 )
port = substream - > number ;
2015-10-30 20:43:15 +03:00
else
2017-04-02 17:48:26 +03:00
port = 2 ;
2015-10-30 20:43:15 +03:00
spin_lock_irqsave ( & dg00x - > lock , flags ) ;
if ( up )
2017-04-02 17:48:26 +03:00
amdtp_dot_midi_trigger ( & dg00x - > rx_stream , port , substream ) ;
else
amdtp_dot_midi_trigger ( & dg00x - > rx_stream , port , NULL ) ;
2015-10-30 20:43:15 +03:00
spin_unlock_irqrestore ( & dg00x - > lock , flags ) ;
}
2017-04-02 17:48:26 +03:00
static void set_substream_names ( struct snd_dg00x * dg00x ,
struct snd_rawmidi * rmidi , bool is_console )
2015-10-11 06:30:16 +03:00
{
struct snd_rawmidi_substream * subs ;
2017-04-02 17:48:26 +03:00
struct snd_rawmidi_str * str ;
int i ;
for ( i = 0 ; i < 2 ; + + i ) {
str = & rmidi - > streams [ i ] ;
list_for_each_entry ( subs , & str - > substreams , list ) {
if ( ! is_console ) {
snprintf ( subs - > name , sizeof ( subs - > name ) ,
" %s MIDI %d " ,
dg00x - > card - > shortname ,
subs - > number + 1 ) ;
} else {
snprintf ( subs - > name , sizeof ( subs - > name ) ,
" %s control " ,
dg00x - > card - > shortname ) ;
}
}
2015-10-11 06:30:16 +03:00
}
}
2017-04-02 17:48:26 +03:00
static int add_substream_pair ( struct snd_dg00x * dg00x , unsigned int out_ports ,
unsigned int in_ports , bool is_console )
2015-10-11 06:30:16 +03:00
{
2017-04-02 17:48:26 +03:00
static const struct snd_rawmidi_ops capture_ops = {
. open = midi_open ,
. close = midi_close ,
. trigger = midi_capture_trigger ,
2017-01-05 15:48:11 +03:00
} ;
2017-04-02 17:48:26 +03:00
static const struct snd_rawmidi_ops playback_ops = {
. open = midi_open ,
. close = midi_close ,
. trigger = midi_playback_trigger ,
2017-01-05 15:48:11 +03:00
} ;
2017-04-02 17:48:26 +03:00
const char * label ;
struct snd_rawmidi * rmidi ;
2015-10-11 06:30:16 +03:00
int err ;
2015-10-30 20:43:16 +03:00
/* Add physical midi ports. */
2017-04-02 17:48:26 +03:00
err = snd_rawmidi_new ( dg00x - > card , dg00x - > card - > driver , is_console ,
out_ports , in_ports , & rmidi ) ;
2015-10-11 06:30:16 +03:00
if ( err < 0 )
return err ;
2017-04-02 17:48:26 +03:00
rmidi - > private_data = dg00x ;
2015-10-11 06:30:16 +03:00
2017-04-02 17:48:26 +03:00
if ( ! is_console )
label = " %s control " ;
else
label = " %s MIDI " ;
snprintf ( rmidi - > name , sizeof ( rmidi - > name ) , label ,
dg00x - > card - > shortname ) ;
2015-10-11 06:30:16 +03:00
2017-04-02 17:48:26 +03:00
snd_rawmidi_set_ops ( rmidi , SNDRV_RAWMIDI_STREAM_OUTPUT , & playback_ops ) ;
snd_rawmidi_set_ops ( rmidi , SNDRV_RAWMIDI_STREAM_INPUT , & capture_ops ) ;
2015-10-30 20:43:16 +03:00
2017-04-02 17:48:26 +03:00
rmidi - > info_flags | = SNDRV_RAWMIDI_INFO_INPUT |
SNDRV_RAWMIDI_INFO_OUTPUT |
SNDRV_RAWMIDI_INFO_DUPLEX ;
2015-10-30 20:43:16 +03:00
2017-04-02 17:48:26 +03:00
set_substream_names ( dg00x , rmidi , is_console ) ;
2015-10-30 20:43:16 +03:00
2017-04-02 17:48:26 +03:00
return 0 ;
}
2015-10-30 20:43:16 +03:00
2017-04-02 17:48:26 +03:00
int snd_dg00x_create_midi_devices ( struct snd_dg00x * dg00x )
{
int err ;
2015-10-30 20:43:16 +03:00
2017-04-02 17:48:26 +03:00
/* Add physical midi ports. */
err = add_substream_pair ( dg00x , DOT_MIDI_OUT_PORTS , DOT_MIDI_IN_PORTS ,
false ) ;
if ( err < 0 )
return err ;
2015-10-30 20:43:16 +03:00
2017-04-02 17:48:26 +03:00
if ( dg00x - > is_console )
err = add_substream_pair ( dg00x , 1 , 1 , true ) ;
2015-10-11 06:30:16 +03:00
2017-04-02 17:48:26 +03:00
return err ;
2015-10-11 06:30:16 +03:00
}