2011-03-15 09:53:21 +03:00
/*
* Audio and Music Data Transmission Protocol ( IEC 61883 - 6 ) streams
* with Common Isochronous Packet ( IEC 61883 - 1 ) headers
*
* Copyright ( c ) Clemens Ladisch < clemens @ ladisch . de >
* Licensed under the terms of the GNU General Public License , version 2.
*/
# include <linux/device.h>
# include <linux/err.h>
# include <linux/firewire.h>
# include <linux/module.h>
# include <linux/slab.h>
2014-04-25 17:44:49 +04:00
# include <linux/sched.h>
2011-03-15 09:53:21 +03:00
# include <sound/pcm.h>
2014-04-25 17:44:52 +04:00
# include <sound/pcm_params.h>
ALSA: firewire-lib: Add support for MIDI capture/playback
For capturing/playbacking MIDI messages, this commit adds one MIDI conformant
data channel. This data channel has multiplexed 8 MIDI data streams. So this
data channel can transfer messages from/to 8 MIDI ports.
And this commit allows to set PCM format even if AMDTP streams already start.
I suppose the case that PCM substreams are going to be joined into AMDTP
streams when AMDTP streams are already started for MIDI substreams. Each
driver must count how many PCM/MIDI substreams use AMDTP streams to stop
AMDTP streams.
There are differences between specifications about MIDI conformant data.
About the multiplexing, IEC 61883-6:2002, itself, has no information. It
describes labels and bytes for MIDI messages and refers to MMA/AMEI RP-027
for 'successfull implementation'. MMA/AMEI RP-027 describes 8 MPX-MIDI data
streams for one MIDI conformant data channel. IEC 61883-6:2005 adds
'sequence multiplexing' and apply this way and describe incompatibility
between 2002 and 2005.
So this commit applies IEC 61883-6:2005. When we find some devices compliant
to IEC 61883-6:2002, then this difference should be handles as device quirk
in additional work.
About the number of bytes in an MIDI conformant data, IEC 61883-6:2002 describe
0,1,2,3 bytes. MMA/AMEI RP-027 describes 'MIDI1.0-1x-SPEED', 'MIDI1.0-2x-SPEED',
'MIDI1.0-3x-SPEED' modes and the maximum bytes for each mode corresponds to 1,
2, 3 bytes. The 'MIDI1.0-2x/3x-SPEED' modes are accompanied with 'negotiation
procedure' and 'encapsulation details' but there is no specifications for them.
So this commit implements 'MIDI1.0-1x-SPEED' mode for playback, but allows
to pick up 1-3 bytes for capturing.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-04-25 17:44:47 +04:00
# include <sound/rawmidi.h>
2011-03-15 09:53:21 +03:00
# include "amdtp.h"
# define TICKS_PER_CYCLE 3072
# define CYCLES_PER_SECOND 8000
# define TICKS_PER_SECOND (TICKS_PER_CYCLE * CYCLES_PER_SECOND)
# define TRANSFER_DELAY_TICKS 0x2e00 /* 479.17 µs */
2014-04-25 17:44:43 +04:00
/* isochronous header parameters */
# define ISO_DATA_LENGTH_SHIFT 16
2011-03-15 09:53:21 +03:00
# define TAG_CIP 1
2014-04-25 17:44:43 +04:00
/* common isochronous packet header parameters */
2011-03-15 09:53:21 +03:00
# define CIP_EOH (1u << 31)
2014-04-25 17:44:43 +04:00
# define CIP_EOH_MASK 0x80000000
2011-03-15 09:53:21 +03:00
# define CIP_FMT_AM (0x10 << 24)
2014-04-25 17:44:43 +04:00
# define CIP_FMT_MASK 0x3f000000
# define CIP_SYT_MASK 0x0000ffff
# define CIP_SYT_NO_INFO 0xffff
# define CIP_FDF_MASK 0x00ff0000
# define CIP_FDF_SFC_SHIFT 16
/*
* Audio and Music transfer protocol specific parameters
* only " Clock-based rate control mode " is supported
*/
# define AMDTP_FDF_AM824 (0 << (CIP_FDF_SFC_SHIFT + 3))
2014-04-25 17:44:46 +04:00
# define AMDTP_FDF_NO_DATA 0xff
2014-04-25 17:44:43 +04:00
# define AMDTP_DBS_MASK 0x00ff0000
# define AMDTP_DBS_SHIFT 16
# define AMDTP_DBC_MASK 0x000000ff
2011-03-15 09:53:21 +03:00
/* TODO: make these configurable */
# define INTERRUPT_INTERVAL 16
# define QUEUE_LENGTH 48
2014-04-25 17:44:46 +04:00
# define IN_PACKET_HEADER_SIZE 4
2014-04-25 17:44:45 +04:00
# define OUT_PACKET_HEADER_SIZE 0
2012-05-14 00:03:09 +04:00
static void pcm_period_tasklet ( unsigned long data ) ;
2011-03-15 09:53:21 +03:00
/**
2014-04-25 17:44:42 +04:00
* amdtp_stream_init - initialize an AMDTP stream structure
* @ s : the AMDTP stream to initialize
2011-03-15 09:53:21 +03:00
* @ unit : the target of the stream
2014-04-25 17:44:44 +04:00
* @ dir : the direction of stream
2011-03-15 09:53:21 +03:00
* @ flags : the packet transmission method to use
*/
2014-04-25 17:44:42 +04:00
int amdtp_stream_init ( struct amdtp_stream * s , struct fw_unit * unit ,
2014-04-25 17:44:44 +04:00
enum amdtp_stream_direction dir , enum cip_flags flags )
2011-03-15 09:53:21 +03:00
{
s - > unit = fw_unit_get ( unit ) ;
2014-04-25 17:44:44 +04:00
s - > direction = dir ;
2011-03-15 09:53:21 +03:00
s - > flags = flags ;
s - > context = ERR_PTR ( - 1 ) ;
mutex_init ( & s - > mutex ) ;
2012-05-14 00:03:09 +04:00
tasklet_init ( & s - > period_tasklet , pcm_period_tasklet , ( unsigned long ) s ) ;
2011-03-15 09:57:24 +03:00
s - > packet_index = 0 ;
2011-03-15 09:53:21 +03:00
2014-04-25 17:44:49 +04:00
init_waitqueue_head ( & s - > callback_wait ) ;
s - > callbacked = false ;
s - > sync_slave = NULL ;
2014-04-25 17:45:10 +04:00
s - > rx_blocks_for_midi = UINT_MAX ;
2011-03-15 09:53:21 +03:00
return 0 ;
}
2014-04-25 17:44:42 +04:00
EXPORT_SYMBOL ( amdtp_stream_init ) ;
2011-03-15 09:53:21 +03:00
/**
2014-04-25 17:44:42 +04:00
* amdtp_stream_destroy - free stream resources
* @ s : the AMDTP stream to destroy
2011-03-15 09:53:21 +03:00
*/
2014-04-25 17:44:42 +04:00
void amdtp_stream_destroy ( struct amdtp_stream * s )
2011-03-15 09:53:21 +03:00
{
2014-04-25 17:44:42 +04:00
WARN_ON ( amdtp_stream_running ( s ) ) ;
2011-03-15 09:53:21 +03:00
mutex_destroy ( & s - > mutex ) ;
fw_unit_put ( s - > unit ) ;
}
2014-04-25 17:44:42 +04:00
EXPORT_SYMBOL ( amdtp_stream_destroy ) ;
2011-03-15 09:53:21 +03:00
2011-10-16 23:39:00 +04:00
const unsigned int amdtp_syt_intervals [ CIP_SFC_COUNT ] = {
2011-09-05 00:16:10 +04:00
[ CIP_SFC_32000 ] = 8 ,
[ CIP_SFC_44100 ] = 8 ,
[ CIP_SFC_48000 ] = 8 ,
[ CIP_SFC_88200 ] = 16 ,
[ CIP_SFC_96000 ] = 16 ,
[ CIP_SFC_176400 ] = 32 ,
[ CIP_SFC_192000 ] = 32 ,
} ;
EXPORT_SYMBOL ( amdtp_syt_intervals ) ;
2014-04-25 17:44:59 +04:00
const unsigned int amdtp_rate_table [ ] = {
[ CIP_SFC_32000 ] = 32000 ,
[ CIP_SFC_44100 ] = 44100 ,
[ CIP_SFC_48000 ] = 48000 ,
[ CIP_SFC_88200 ] = 88200 ,
[ CIP_SFC_96000 ] = 96000 ,
[ CIP_SFC_176400 ] = 176400 ,
[ CIP_SFC_192000 ] = 192000 ,
} ;
EXPORT_SYMBOL ( amdtp_rate_table ) ;
2014-04-25 17:44:52 +04:00
/**
* amdtp_stream_add_pcm_hw_constraints - add hw constraints for PCM substream
* @ s : the AMDTP stream , which must be initialized .
* @ runtime : the PCM substream runtime
*/
int amdtp_stream_add_pcm_hw_constraints ( struct amdtp_stream * s ,
struct snd_pcm_runtime * runtime )
{
int err ;
/* AM824 in IEC 61883-6 can deliver 24bit data */
err = snd_pcm_hw_constraint_msbits ( runtime , 0 , 32 , 24 ) ;
if ( err < 0 )
goto end ;
/*
* Currently firewire - lib processes 16 packets in one software
* interrupt callback . This equals to 2 msec but actually the
* interval of the interrupts has a jitter .
* Additionally , even if adding a constraint to fit period size to
* 2 msec , actual calculated frames per period doesn ' t equal to 2 msec ,
* depending on sampling rate .
* Anyway , the interval to call snd_pcm_period_elapsed ( ) cannot 2 msec .
* Here let us use 5 msec for safe period interrupt .
*/
err = snd_pcm_hw_constraint_minmax ( runtime ,
SNDRV_PCM_HW_PARAM_PERIOD_TIME ,
5000 , UINT_MAX ) ;
if ( err < 0 )
goto end ;
/* Non-Blocking stream has no more constraints */
if ( ! ( s - > flags & CIP_BLOCKING ) )
goto end ;
/*
* One AMDTP packet can include some frames . In blocking mode , the
* number equals to SYT_INTERVAL . So the number is 8 , 16 or 32 ,
* depending on its sampling rate . For accurate period interrupt , it ' s
* preferrable to aligh period / buffer sizes to current SYT_INTERVAL .
*
* TODO : These constraints can be improved with propper rules .
* Currently apply LCM of SYT_INTEVALs .
*/
err = snd_pcm_hw_constraint_step ( runtime , 0 ,
SNDRV_PCM_HW_PARAM_PERIOD_SIZE , 32 ) ;
if ( err < 0 )
goto end ;
err = snd_pcm_hw_constraint_step ( runtime , 0 ,
SNDRV_PCM_HW_PARAM_BUFFER_SIZE , 32 ) ;
end :
return err ;
}
EXPORT_SYMBOL ( amdtp_stream_add_pcm_hw_constraints ) ;
2011-03-15 09:53:21 +03:00
/**
2014-04-25 17:44:42 +04:00
* amdtp_stream_set_parameters - set stream parameters
* @ s : the AMDTP stream to configure
2011-03-15 09:53:21 +03:00
* @ rate : the sample rate
2011-09-05 00:16:10 +04:00
* @ pcm_channels : the number of PCM samples in each data block , to be encoded
* as AM824 multi - bit linear audio
* @ midi_ports : the number of MIDI ports ( i . e . , MPX - MIDI Data Channels )
2011-03-15 09:53:21 +03:00
*
2011-09-05 00:16:10 +04:00
* The parameters must be set before the stream is started , and must not be
2011-03-15 09:53:21 +03:00
* changed while the stream is running .
*/
2014-04-25 17:44:42 +04:00
void amdtp_stream_set_parameters ( struct amdtp_stream * s ,
unsigned int rate ,
unsigned int pcm_channels ,
unsigned int midi_ports )
2011-03-15 09:53:21 +03:00
{
2014-04-25 17:44:50 +04:00
unsigned int i , sfc , midi_channels ;
2011-03-15 09:53:21 +03:00
ALSA: firewire-lib: Add support for MIDI capture/playback
For capturing/playbacking MIDI messages, this commit adds one MIDI conformant
data channel. This data channel has multiplexed 8 MIDI data streams. So this
data channel can transfer messages from/to 8 MIDI ports.
And this commit allows to set PCM format even if AMDTP streams already start.
I suppose the case that PCM substreams are going to be joined into AMDTP
streams when AMDTP streams are already started for MIDI substreams. Each
driver must count how many PCM/MIDI substreams use AMDTP streams to stop
AMDTP streams.
There are differences between specifications about MIDI conformant data.
About the multiplexing, IEC 61883-6:2002, itself, has no information. It
describes labels and bytes for MIDI messages and refers to MMA/AMEI RP-027
for 'successfull implementation'. MMA/AMEI RP-027 describes 8 MPX-MIDI data
streams for one MIDI conformant data channel. IEC 61883-6:2005 adds
'sequence multiplexing' and apply this way and describe incompatibility
between 2002 and 2005.
So this commit applies IEC 61883-6:2005. When we find some devices compliant
to IEC 61883-6:2002, then this difference should be handles as device quirk
in additional work.
About the number of bytes in an MIDI conformant data, IEC 61883-6:2002 describe
0,1,2,3 bytes. MMA/AMEI RP-027 describes 'MIDI1.0-1x-SPEED', 'MIDI1.0-2x-SPEED',
'MIDI1.0-3x-SPEED' modes and the maximum bytes for each mode corresponds to 1,
2, 3 bytes. The 'MIDI1.0-2x/3x-SPEED' modes are accompanied with 'negotiation
procedure' and 'encapsulation details' but there is no specifications for them.
So this commit implements 'MIDI1.0-1x-SPEED' mode for playback, but allows
to pick up 1-3 bytes for capturing.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-04-25 17:44:47 +04:00
midi_channels = DIV_ROUND_UP ( midi_ports , 8 ) ;
2014-04-25 17:44:50 +04:00
if ( WARN_ON ( amdtp_stream_running ( s ) ) |
WARN_ON ( pcm_channels > AMDTP_MAX_CHANNELS_FOR_PCM ) |
ALSA: firewire-lib: Add support for MIDI capture/playback
For capturing/playbacking MIDI messages, this commit adds one MIDI conformant
data channel. This data channel has multiplexed 8 MIDI data streams. So this
data channel can transfer messages from/to 8 MIDI ports.
And this commit allows to set PCM format even if AMDTP streams already start.
I suppose the case that PCM substreams are going to be joined into AMDTP
streams when AMDTP streams are already started for MIDI substreams. Each
driver must count how many PCM/MIDI substreams use AMDTP streams to stop
AMDTP streams.
There are differences between specifications about MIDI conformant data.
About the multiplexing, IEC 61883-6:2002, itself, has no information. It
describes labels and bytes for MIDI messages and refers to MMA/AMEI RP-027
for 'successfull implementation'. MMA/AMEI RP-027 describes 8 MPX-MIDI data
streams for one MIDI conformant data channel. IEC 61883-6:2005 adds
'sequence multiplexing' and apply this way and describe incompatibility
between 2002 and 2005.
So this commit applies IEC 61883-6:2005. When we find some devices compliant
to IEC 61883-6:2002, then this difference should be handles as device quirk
in additional work.
About the number of bytes in an MIDI conformant data, IEC 61883-6:2002 describe
0,1,2,3 bytes. MMA/AMEI RP-027 describes 'MIDI1.0-1x-SPEED', 'MIDI1.0-2x-SPEED',
'MIDI1.0-3x-SPEED' modes and the maximum bytes for each mode corresponds to 1,
2, 3 bytes. The 'MIDI1.0-2x/3x-SPEED' modes are accompanied with 'negotiation
procedure' and 'encapsulation details' but there is no specifications for them.
So this commit implements 'MIDI1.0-1x-SPEED' mode for playback, but allows
to pick up 1-3 bytes for capturing.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-04-25 17:44:47 +04:00
WARN_ON ( midi_channels > AMDTP_MAX_CHANNELS_FOR_MIDI ) )
2011-03-15 09:53:21 +03:00
return ;
2014-04-25 17:44:59 +04:00
for ( sfc = 0 ; sfc < sizeof ( amdtp_rate_table ) ; + + sfc )
if ( amdtp_rate_table [ sfc ] = = rate )
2011-09-05 00:12:48 +04:00
goto sfc_found ;
2011-03-15 09:53:21 +03:00
WARN_ON ( 1 ) ;
2011-09-05 00:12:48 +04:00
return ;
sfc_found :
2014-04-25 17:44:51 +04:00
s - > pcm_channels = pcm_channels ;
2011-09-05 00:12:48 +04:00
s - > sfc = sfc ;
2014-04-25 17:44:50 +04:00
s - > data_block_quadlets = s - > pcm_channels + midi_channels ;
2011-09-05 00:16:10 +04:00
s - > midi_ports = midi_ports ;
s - > syt_interval = amdtp_syt_intervals [ sfc ] ;
2011-09-05 00:12:48 +04:00
/* default buffering in the device */
s - > transfer_delay = TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE ;
if ( s - > flags & CIP_BLOCKING )
/* additional buffering needed to adjust for no-data packets */
s - > transfer_delay + = TICKS_PER_SECOND * s - > syt_interval / rate ;
2014-04-25 17:44:50 +04:00
/* init the position map for PCM and MIDI channels */
for ( i = 0 ; i < pcm_channels ; i + + )
s - > pcm_positions [ i ] = i ;
s - > midi_position = s - > pcm_channels ;
2011-03-15 09:53:21 +03:00
}
2014-04-25 17:44:42 +04:00
EXPORT_SYMBOL ( amdtp_stream_set_parameters ) ;
2011-03-15 09:53:21 +03:00
/**
2014-04-25 17:44:42 +04:00
* amdtp_stream_get_max_payload - get the stream ' s packet size
* @ s : the AMDTP stream
2011-03-15 09:53:21 +03:00
*
* This function must not be called before the stream has been configured
2014-04-25 17:44:42 +04:00
* with amdtp_stream_set_parameters ( ) .
2011-03-15 09:53:21 +03:00
*/
2014-04-25 17:44:42 +04:00
unsigned int amdtp_stream_get_max_payload ( struct amdtp_stream * s )
2011-03-15 09:53:21 +03:00
{
2011-09-05 00:12:48 +04:00
return 8 + s - > syt_interval * s - > data_block_quadlets * 4 ;
2011-03-15 09:53:21 +03:00
}
2014-04-25 17:44:42 +04:00
EXPORT_SYMBOL ( amdtp_stream_get_max_payload ) ;
2011-03-15 09:53:21 +03:00
2014-04-25 17:44:42 +04:00
static void amdtp_write_s16 ( struct amdtp_stream * s ,
2011-03-15 09:53:21 +03:00
struct snd_pcm_substream * pcm ,
__be32 * buffer , unsigned int frames ) ;
2014-04-25 17:44:42 +04:00
static void amdtp_write_s32 ( struct amdtp_stream * s ,
2011-03-15 09:53:21 +03:00
struct snd_pcm_substream * pcm ,
__be32 * buffer , unsigned int frames ) ;
2014-04-25 17:44:46 +04:00
static void amdtp_read_s32 ( struct amdtp_stream * s ,
struct snd_pcm_substream * pcm ,
__be32 * buffer , unsigned int frames ) ;
2011-03-15 09:53:21 +03:00
/**
2014-04-25 17:44:42 +04:00
* amdtp_stream_set_pcm_format - set the PCM format
* @ s : the AMDTP stream to configure
2011-03-15 09:53:21 +03:00
* @ format : the format of the ALSA PCM device
*
2011-09-05 00:16:10 +04:00
* The sample format must be set after the other paramters ( rate / PCM channels /
* MIDI ) and before the stream is started , and must not be changed while the
* stream is running .
2011-03-15 09:53:21 +03:00
*/
2014-04-25 17:44:42 +04:00
void amdtp_stream_set_pcm_format ( struct amdtp_stream * s ,
snd_pcm_format_t format )
2011-03-15 09:53:21 +03:00
{
ALSA: firewire-lib: Add support for MIDI capture/playback
For capturing/playbacking MIDI messages, this commit adds one MIDI conformant
data channel. This data channel has multiplexed 8 MIDI data streams. So this
data channel can transfer messages from/to 8 MIDI ports.
And this commit allows to set PCM format even if AMDTP streams already start.
I suppose the case that PCM substreams are going to be joined into AMDTP
streams when AMDTP streams are already started for MIDI substreams. Each
driver must count how many PCM/MIDI substreams use AMDTP streams to stop
AMDTP streams.
There are differences between specifications about MIDI conformant data.
About the multiplexing, IEC 61883-6:2002, itself, has no information. It
describes labels and bytes for MIDI messages and refers to MMA/AMEI RP-027
for 'successfull implementation'. MMA/AMEI RP-027 describes 8 MPX-MIDI data
streams for one MIDI conformant data channel. IEC 61883-6:2005 adds
'sequence multiplexing' and apply this way and describe incompatibility
between 2002 and 2005.
So this commit applies IEC 61883-6:2005. When we find some devices compliant
to IEC 61883-6:2002, then this difference should be handles as device quirk
in additional work.
About the number of bytes in an MIDI conformant data, IEC 61883-6:2002 describe
0,1,2,3 bytes. MMA/AMEI RP-027 describes 'MIDI1.0-1x-SPEED', 'MIDI1.0-2x-SPEED',
'MIDI1.0-3x-SPEED' modes and the maximum bytes for each mode corresponds to 1,
2, 3 bytes. The 'MIDI1.0-2x/3x-SPEED' modes are accompanied with 'negotiation
procedure' and 'encapsulation details' but there is no specifications for them.
So this commit implements 'MIDI1.0-1x-SPEED' mode for playback, but allows
to pick up 1-3 bytes for capturing.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-04-25 17:44:47 +04:00
if ( WARN_ON ( amdtp_stream_pcm_running ( s ) ) )
2011-03-15 09:53:21 +03:00
return ;
switch ( format ) {
default :
WARN_ON ( 1 ) ;
/* fall through */
case SNDRV_PCM_FORMAT_S16 :
2014-04-25 17:44:46 +04:00
if ( s - > direction = = AMDTP_OUT_STREAM ) {
2014-04-25 17:44:51 +04:00
s - > transfer_samples = amdtp_write_s16 ;
2014-04-25 17:44:46 +04:00
break ;
}
WARN_ON ( 1 ) ;
/* fall through */
2011-03-15 09:53:21 +03:00
case SNDRV_PCM_FORMAT_S32 :
2014-04-25 17:44:51 +04:00
if ( s - > direction = = AMDTP_OUT_STREAM )
s - > transfer_samples = amdtp_write_s32 ;
else
s - > transfer_samples = amdtp_read_s32 ;
2011-03-15 09:53:21 +03:00
break ;
}
}
2014-04-25 17:44:42 +04:00
EXPORT_SYMBOL ( amdtp_stream_set_pcm_format ) ;
2011-03-15 09:53:21 +03:00
2012-05-14 00:03:09 +04:00
/**
2014-04-25 17:44:42 +04:00
* amdtp_stream_pcm_prepare - prepare PCM device for running
* @ s : the AMDTP stream
2012-05-14 00:03:09 +04:00
*
* This function should be called from the PCM device ' s . prepare callback .
*/
2014-04-25 17:44:42 +04:00
void amdtp_stream_pcm_prepare ( struct amdtp_stream * s )
2012-05-14 00:03:09 +04:00
{
tasklet_kill ( & s - > period_tasklet ) ;
s - > pcm_buffer_pointer = 0 ;
s - > pcm_period_pointer = 0 ;
2012-05-13 21:07:22 +04:00
s - > pointer_flush = true ;
2012-05-14 00:03:09 +04:00
}
2014-04-25 17:44:42 +04:00
EXPORT_SYMBOL ( amdtp_stream_pcm_prepare ) ;
2012-05-14 00:03:09 +04:00
2014-04-25 17:44:42 +04:00
static unsigned int calculate_data_blocks ( struct amdtp_stream * s )
2011-03-15 09:53:21 +03:00
{
unsigned int phase , data_blocks ;
2014-04-25 17:44:48 +04:00
if ( s - > flags & CIP_BLOCKING )
data_blocks = s - > syt_interval ;
else if ( ! cip_sfc_is_base_44100 ( s - > sfc ) ) {
2011-03-15 09:53:21 +03:00
/* Sample_rate / 8000 is an integer, and precomputed. */
data_blocks = s - > data_block_state ;
} else {
phase = s - > data_block_state ;
/*
* This calculates the number of data blocks per packet so that
* 1 ) the overall rate is correct and exactly synchronized to
* the bus clock , and
* 2 ) packets with a rounded - up number of blocks occur as early
* as possible in the sequence ( to prevent underruns of the
* device ' s buffer ) .
*/
if ( s - > sfc = = CIP_SFC_44100 )
/* 6 6 5 6 5 6 5 ... */
data_blocks = 5 + ( ( phase & 1 ) ^
( phase = = 0 | | phase > = 40 ) ) ;
else
/* 12 11 11 11 11 ... or 23 22 22 22 22 ... */
data_blocks = 11 * ( s - > sfc > > 1 ) + ( phase = = 0 ) ;
if ( + + phase > = ( 80 > > ( s - > sfc > > 1 ) ) )
phase = 0 ;
s - > data_block_state = phase ;
}
return data_blocks ;
}
2014-04-25 17:44:42 +04:00
static unsigned int calculate_syt ( struct amdtp_stream * s ,
2011-03-15 09:53:21 +03:00
unsigned int cycle )
{
unsigned int syt_offset , phase , index , syt ;
if ( s - > last_syt_offset < TICKS_PER_CYCLE ) {
if ( ! cip_sfc_is_base_44100 ( s - > sfc ) )
syt_offset = s - > last_syt_offset + s - > syt_offset_state ;
else {
/*
* The time , in ticks , of the n ' th SYT_INTERVAL sample is :
* n * SYT_INTERVAL * 24576000 / sample_rate
* Modulo TICKS_PER_CYCLE , the difference between successive
* elements is about 1386.23 . Rounding the results of this
* formula to the SYT precision results in a sequence of
* differences that begins with :
* 1386 1386 1387 1386 1386 1386 1387 1386 1386 1386 1387 . . .
* This code generates _exactly_ the same sequence .
*/
phase = s - > syt_offset_state ;
index = phase % 13 ;
syt_offset = s - > last_syt_offset ;
syt_offset + = 1386 + ( ( index & & ! ( index & 3 ) ) | |
phase = = 146 ) ;
if ( + + phase > = 147 )
phase = 0 ;
s - > syt_offset_state = phase ;
}
} else
syt_offset = s - > last_syt_offset - TICKS_PER_CYCLE ;
s - > last_syt_offset = syt_offset ;
2011-03-15 09:55:02 +03:00
if ( syt_offset < TICKS_PER_CYCLE ) {
2011-09-05 00:12:48 +04:00
syt_offset + = s - > transfer_delay ;
2011-03-15 09:55:02 +03:00
syt = ( cycle + syt_offset / TICKS_PER_CYCLE ) < < 12 ;
syt + = syt_offset % TICKS_PER_CYCLE ;
2011-03-15 09:53:21 +03:00
2014-04-25 17:44:43 +04:00
return syt & CIP_SYT_MASK ;
2011-03-15 09:55:02 +03:00
} else {
2014-04-25 17:44:43 +04:00
return CIP_SYT_NO_INFO ;
2011-03-15 09:55:02 +03:00
}
2011-03-15 09:53:21 +03:00
}
2014-04-25 17:44:42 +04:00
static void amdtp_write_s32 ( struct amdtp_stream * s ,
2011-03-15 09:53:21 +03:00
struct snd_pcm_substream * pcm ,
__be32 * buffer , unsigned int frames )
{
struct snd_pcm_runtime * runtime = pcm - > runtime ;
2014-04-25 17:44:50 +04:00
unsigned int channels , remaining_frames , i , c ;
2011-03-15 09:53:21 +03:00
const u32 * src ;
channels = s - > pcm_channels ;
src = ( void * ) runtime - > dma_area +
2013-09-13 19:35:47 +04:00
frames_to_bytes ( runtime , s - > pcm_buffer_pointer ) ;
2011-03-15 09:53:21 +03:00
remaining_frames = runtime - > buffer_size - s - > pcm_buffer_pointer ;
for ( i = 0 ; i < frames ; + + i ) {
for ( c = 0 ; c < channels ; + + c ) {
2014-04-25 17:44:50 +04:00
buffer [ s - > pcm_positions [ c ] ] =
cpu_to_be32 ( ( * src > > 8 ) | 0x40000000 ) ;
2011-03-15 09:53:21 +03:00
src + + ;
}
2014-04-25 17:44:50 +04:00
buffer + = s - > data_block_quadlets ;
2011-03-15 09:53:21 +03:00
if ( - - remaining_frames = = 0 )
src = ( void * ) runtime - > dma_area ;
}
}
2014-04-25 17:44:42 +04:00
static void amdtp_write_s16 ( struct amdtp_stream * s ,
2011-03-15 09:53:21 +03:00
struct snd_pcm_substream * pcm ,
__be32 * buffer , unsigned int frames )
{
struct snd_pcm_runtime * runtime = pcm - > runtime ;
2014-04-25 17:44:50 +04:00
unsigned int channels , remaining_frames , i , c ;
2011-03-15 09:53:21 +03:00
const u16 * src ;
channels = s - > pcm_channels ;
src = ( void * ) runtime - > dma_area +
2013-09-13 19:35:47 +04:00
frames_to_bytes ( runtime , s - > pcm_buffer_pointer ) ;
2011-03-15 09:53:21 +03:00
remaining_frames = runtime - > buffer_size - s - > pcm_buffer_pointer ;
for ( i = 0 ; i < frames ; + + i ) {
for ( c = 0 ; c < channels ; + + c ) {
2014-04-25 17:44:50 +04:00
buffer [ s - > pcm_positions [ c ] ] =
cpu_to_be32 ( ( * src < < 8 ) | 0x40000000 ) ;
2011-03-15 09:53:21 +03:00
src + + ;
}
2014-04-25 17:44:50 +04:00
buffer + = s - > data_block_quadlets ;
2011-03-15 09:53:21 +03:00
if ( - - remaining_frames = = 0 )
src = ( void * ) runtime - > dma_area ;
}
}
2014-04-25 17:44:46 +04:00
static void amdtp_read_s32 ( struct amdtp_stream * s ,
struct snd_pcm_substream * pcm ,
__be32 * buffer , unsigned int frames )
{
struct snd_pcm_runtime * runtime = pcm - > runtime ;
unsigned int channels , remaining_frames , i , c ;
u32 * dst ;
channels = s - > pcm_channels ;
dst = ( void * ) runtime - > dma_area +
frames_to_bytes ( runtime , s - > pcm_buffer_pointer ) ;
remaining_frames = runtime - > buffer_size - s - > pcm_buffer_pointer ;
for ( i = 0 ; i < frames ; + + i ) {
for ( c = 0 ; c < channels ; + + c ) {
2014-04-25 17:44:50 +04:00
* dst = be32_to_cpu ( buffer [ s - > pcm_positions [ c ] ] ) < < 8 ;
2014-04-25 17:44:46 +04:00
dst + + ;
}
buffer + = s - > data_block_quadlets ;
if ( - - remaining_frames = = 0 )
dst = ( void * ) runtime - > dma_area ;
}
}
2014-04-25 17:44:42 +04:00
static void amdtp_fill_pcm_silence ( struct amdtp_stream * s ,
2011-03-15 09:53:21 +03:00
__be32 * buffer , unsigned int frames )
{
unsigned int i , c ;
for ( i = 0 ; i < frames ; + + i ) {
for ( c = 0 ; c < s - > pcm_channels ; + + c )
2014-04-25 17:44:50 +04:00
buffer [ s - > pcm_positions [ c ] ] = cpu_to_be32 ( 0x40000000 ) ;
2011-03-15 09:53:21 +03:00
buffer + = s - > data_block_quadlets ;
}
}
2014-04-25 17:44:42 +04:00
static void amdtp_fill_midi ( struct amdtp_stream * s ,
2011-03-15 09:53:21 +03:00
__be32 * buffer , unsigned int frames )
{
ALSA: firewire-lib: Add support for MIDI capture/playback
For capturing/playbacking MIDI messages, this commit adds one MIDI conformant
data channel. This data channel has multiplexed 8 MIDI data streams. So this
data channel can transfer messages from/to 8 MIDI ports.
And this commit allows to set PCM format even if AMDTP streams already start.
I suppose the case that PCM substreams are going to be joined into AMDTP
streams when AMDTP streams are already started for MIDI substreams. Each
driver must count how many PCM/MIDI substreams use AMDTP streams to stop
AMDTP streams.
There are differences between specifications about MIDI conformant data.
About the multiplexing, IEC 61883-6:2002, itself, has no information. It
describes labels and bytes for MIDI messages and refers to MMA/AMEI RP-027
for 'successfull implementation'. MMA/AMEI RP-027 describes 8 MPX-MIDI data
streams for one MIDI conformant data channel. IEC 61883-6:2005 adds
'sequence multiplexing' and apply this way and describe incompatibility
between 2002 and 2005.
So this commit applies IEC 61883-6:2005. When we find some devices compliant
to IEC 61883-6:2002, then this difference should be handles as device quirk
in additional work.
About the number of bytes in an MIDI conformant data, IEC 61883-6:2002 describe
0,1,2,3 bytes. MMA/AMEI RP-027 describes 'MIDI1.0-1x-SPEED', 'MIDI1.0-2x-SPEED',
'MIDI1.0-3x-SPEED' modes and the maximum bytes for each mode corresponds to 1,
2, 3 bytes. The 'MIDI1.0-2x/3x-SPEED' modes are accompanied with 'negotiation
procedure' and 'encapsulation details' but there is no specifications for them.
So this commit implements 'MIDI1.0-1x-SPEED' mode for playback, but allows
to pick up 1-3 bytes for capturing.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-04-25 17:44:47 +04:00
unsigned int f , port ;
u8 * b ;
for ( f = 0 ; f < frames ; f + + ) {
2014-04-25 17:44:50 +04:00
buffer [ s - > midi_position ] = 0 ;
b = ( u8 * ) & buffer [ s - > midi_position ] ;
ALSA: firewire-lib: Add support for MIDI capture/playback
For capturing/playbacking MIDI messages, this commit adds one MIDI conformant
data channel. This data channel has multiplexed 8 MIDI data streams. So this
data channel can transfer messages from/to 8 MIDI ports.
And this commit allows to set PCM format even if AMDTP streams already start.
I suppose the case that PCM substreams are going to be joined into AMDTP
streams when AMDTP streams are already started for MIDI substreams. Each
driver must count how many PCM/MIDI substreams use AMDTP streams to stop
AMDTP streams.
There are differences between specifications about MIDI conformant data.
About the multiplexing, IEC 61883-6:2002, itself, has no information. It
describes labels and bytes for MIDI messages and refers to MMA/AMEI RP-027
for 'successfull implementation'. MMA/AMEI RP-027 describes 8 MPX-MIDI data
streams for one MIDI conformant data channel. IEC 61883-6:2005 adds
'sequence multiplexing' and apply this way and describe incompatibility
between 2002 and 2005.
So this commit applies IEC 61883-6:2005. When we find some devices compliant
to IEC 61883-6:2002, then this difference should be handles as device quirk
in additional work.
About the number of bytes in an MIDI conformant data, IEC 61883-6:2002 describe
0,1,2,3 bytes. MMA/AMEI RP-027 describes 'MIDI1.0-1x-SPEED', 'MIDI1.0-2x-SPEED',
'MIDI1.0-3x-SPEED' modes and the maximum bytes for each mode corresponds to 1,
2, 3 bytes. The 'MIDI1.0-2x/3x-SPEED' modes are accompanied with 'negotiation
procedure' and 'encapsulation details' but there is no specifications for them.
So this commit implements 'MIDI1.0-1x-SPEED' mode for playback, but allows
to pick up 1-3 bytes for capturing.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-04-25 17:44:47 +04:00
port = ( s - > data_block_counter + f ) % 8 ;
2014-04-25 17:45:10 +04:00
if ( ( f > = s - > rx_blocks_for_midi ) | |
( s - > midi [ port ] = = NULL ) | |
ALSA: firewire-lib: Add support for MIDI capture/playback
For capturing/playbacking MIDI messages, this commit adds one MIDI conformant
data channel. This data channel has multiplexed 8 MIDI data streams. So this
data channel can transfer messages from/to 8 MIDI ports.
And this commit allows to set PCM format even if AMDTP streams already start.
I suppose the case that PCM substreams are going to be joined into AMDTP
streams when AMDTP streams are already started for MIDI substreams. Each
driver must count how many PCM/MIDI substreams use AMDTP streams to stop
AMDTP streams.
There are differences between specifications about MIDI conformant data.
About the multiplexing, IEC 61883-6:2002, itself, has no information. It
describes labels and bytes for MIDI messages and refers to MMA/AMEI RP-027
for 'successfull implementation'. MMA/AMEI RP-027 describes 8 MPX-MIDI data
streams for one MIDI conformant data channel. IEC 61883-6:2005 adds
'sequence multiplexing' and apply this way and describe incompatibility
between 2002 and 2005.
So this commit applies IEC 61883-6:2005. When we find some devices compliant
to IEC 61883-6:2002, then this difference should be handles as device quirk
in additional work.
About the number of bytes in an MIDI conformant data, IEC 61883-6:2002 describe
0,1,2,3 bytes. MMA/AMEI RP-027 describes 'MIDI1.0-1x-SPEED', 'MIDI1.0-2x-SPEED',
'MIDI1.0-3x-SPEED' modes and the maximum bytes for each mode corresponds to 1,
2, 3 bytes. The 'MIDI1.0-2x/3x-SPEED' modes are accompanied with 'negotiation
procedure' and 'encapsulation details' but there is no specifications for them.
So this commit implements 'MIDI1.0-1x-SPEED' mode for playback, but allows
to pick up 1-3 bytes for capturing.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-04-25 17:44:47 +04:00
( snd_rawmidi_transmit ( s - > midi [ port ] , b + 1 , 1 ) < = 0 ) )
b [ 0 ] = 0x80 ;
else
b [ 0 ] = 0x81 ;
buffer + = s - > data_block_quadlets ;
}
}
static void amdtp_pull_midi ( struct amdtp_stream * s ,
__be32 * buffer , unsigned int frames )
{
unsigned int f , port ;
int len ;
u8 * b ;
for ( f = 0 ; f < frames ; f + + ) {
port = ( s - > data_block_counter + f ) % 8 ;
2014-04-25 17:44:50 +04:00
b = ( u8 * ) & buffer [ s - > midi_position ] ;
2011-03-15 09:53:21 +03:00
ALSA: firewire-lib: Add support for MIDI capture/playback
For capturing/playbacking MIDI messages, this commit adds one MIDI conformant
data channel. This data channel has multiplexed 8 MIDI data streams. So this
data channel can transfer messages from/to 8 MIDI ports.
And this commit allows to set PCM format even if AMDTP streams already start.
I suppose the case that PCM substreams are going to be joined into AMDTP
streams when AMDTP streams are already started for MIDI substreams. Each
driver must count how many PCM/MIDI substreams use AMDTP streams to stop
AMDTP streams.
There are differences between specifications about MIDI conformant data.
About the multiplexing, IEC 61883-6:2002, itself, has no information. It
describes labels and bytes for MIDI messages and refers to MMA/AMEI RP-027
for 'successfull implementation'. MMA/AMEI RP-027 describes 8 MPX-MIDI data
streams for one MIDI conformant data channel. IEC 61883-6:2005 adds
'sequence multiplexing' and apply this way and describe incompatibility
between 2002 and 2005.
So this commit applies IEC 61883-6:2005. When we find some devices compliant
to IEC 61883-6:2002, then this difference should be handles as device quirk
in additional work.
About the number of bytes in an MIDI conformant data, IEC 61883-6:2002 describe
0,1,2,3 bytes. MMA/AMEI RP-027 describes 'MIDI1.0-1x-SPEED', 'MIDI1.0-2x-SPEED',
'MIDI1.0-3x-SPEED' modes and the maximum bytes for each mode corresponds to 1,
2, 3 bytes. The 'MIDI1.0-2x/3x-SPEED' modes are accompanied with 'negotiation
procedure' and 'encapsulation details' but there is no specifications for them.
So this commit implements 'MIDI1.0-1x-SPEED' mode for playback, but allows
to pick up 1-3 bytes for capturing.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-04-25 17:44:47 +04:00
len = b [ 0 ] - 0x80 ;
if ( ( 1 < = len ) & & ( len < = 3 ) & & ( s - > midi [ port ] ) )
snd_rawmidi_receive ( s - > midi [ port ] , b + 1 , len ) ;
buffer + = s - > data_block_quadlets ;
}
2011-03-15 09:53:21 +03:00
}
2014-04-25 17:44:45 +04:00
static void update_pcm_pointers ( struct amdtp_stream * s ,
struct snd_pcm_substream * pcm ,
unsigned int frames )
{ unsigned int ptr ;
ptr = s - > pcm_buffer_pointer + frames ;
if ( ptr > = pcm - > runtime - > buffer_size )
ptr - = pcm - > runtime - > buffer_size ;
ACCESS_ONCE ( s - > pcm_buffer_pointer ) = ptr ;
s - > pcm_period_pointer + = frames ;
if ( s - > pcm_period_pointer > = pcm - > runtime - > period_size ) {
s - > pcm_period_pointer - = pcm - > runtime - > period_size ;
s - > pointer_flush = false ;
tasklet_hi_schedule ( & s - > period_tasklet ) ;
}
}
static void pcm_period_tasklet ( unsigned long data )
{
struct amdtp_stream * s = ( void * ) data ;
struct snd_pcm_substream * pcm = ACCESS_ONCE ( s - > pcm ) ;
if ( pcm )
snd_pcm_period_elapsed ( pcm ) ;
}
static int queue_packet ( struct amdtp_stream * s ,
unsigned int header_length ,
unsigned int payload_length , bool skip )
{
struct fw_iso_packet p = { 0 } ;
2014-04-25 17:44:49 +04:00
int err = 0 ;
if ( IS_ERR ( s - > context ) )
goto end ;
2014-04-25 17:44:45 +04:00
p . interrupt = IS_ALIGNED ( s - > packet_index + 1 , INTERRUPT_INTERVAL ) ;
p . tag = TAG_CIP ;
p . header_length = header_length ;
p . payload_length = ( ! skip ) ? payload_length : 0 ;
p . skip = skip ;
err = fw_iso_context_queue ( s - > context , & p , & s - > buffer . iso_buffer ,
s - > buffer . packets [ s - > packet_index ] . offset ) ;
if ( err < 0 ) {
dev_err ( & s - > unit - > device , " queueing error: %d \n " , err ) ;
goto end ;
}
if ( + + s - > packet_index > = QUEUE_LENGTH )
s - > packet_index = 0 ;
end :
return err ;
}
static inline int queue_out_packet ( struct amdtp_stream * s ,
unsigned int payload_length , bool skip )
{
return queue_packet ( s , OUT_PACKET_HEADER_SIZE ,
payload_length , skip ) ;
}
2014-04-25 17:44:46 +04:00
static inline int queue_in_packet ( struct amdtp_stream * s )
{
return queue_packet ( s , IN_PACKET_HEADER_SIZE ,
amdtp_stream_get_max_payload ( s ) , false ) ;
}
2014-04-25 17:44:48 +04:00
static void handle_out_packet ( struct amdtp_stream * s , unsigned int syt )
2011-03-15 09:53:21 +03:00
{
__be32 * buffer ;
2014-04-25 17:44:48 +04:00
unsigned int data_blocks , payload_length ;
2011-03-15 09:53:21 +03:00
struct snd_pcm_substream * pcm ;
2011-03-15 09:57:24 +03:00
if ( s - > packet_index < 0 )
return ;
2013-11-21 09:21:06 +04:00
/* this module generate empty packet for 'no data' */
2014-04-25 17:44:48 +04:00
if ( ! ( s - > flags & CIP_BLOCKING ) | | ( syt ! = CIP_SYT_NO_INFO ) )
2011-09-05 00:12:48 +04:00
data_blocks = calculate_data_blocks ( s ) ;
2013-11-21 09:21:06 +04:00
else
data_blocks = 0 ;
2011-03-15 09:53:21 +03:00
2014-04-25 17:44:48 +04:00
buffer = s - > buffer . packets [ s - > packet_index ] . buffer ;
2011-03-15 09:53:21 +03:00
buffer [ 0 ] = cpu_to_be32 ( ACCESS_ONCE ( s - > source_node_id_field ) |
2014-04-25 17:44:43 +04:00
( s - > data_block_quadlets < < AMDTP_DBS_SHIFT ) |
2011-03-15 09:53:21 +03:00
s - > data_block_counter ) ;
buffer [ 1 ] = cpu_to_be32 ( CIP_EOH | CIP_FMT_AM | AMDTP_FDF_AM824 |
2014-04-25 17:44:43 +04:00
( s - > sfc < < CIP_FDF_SFC_SHIFT ) | syt ) ;
2011-03-15 09:53:21 +03:00
buffer + = 2 ;
pcm = ACCESS_ONCE ( s - > pcm ) ;
if ( pcm )
s - > transfer_samples ( s , pcm , buffer , data_blocks ) ;
else
amdtp_fill_pcm_silence ( s , buffer , data_blocks ) ;
if ( s - > midi_ports )
amdtp_fill_midi ( s , buffer , data_blocks ) ;
s - > data_block_counter = ( s - > data_block_counter + data_blocks ) & 0xff ;
2014-04-25 17:44:45 +04:00
payload_length = 8 + data_blocks * 4 * s - > data_block_quadlets ;
if ( queue_out_packet ( s , payload_length , false ) < 0 ) {
2011-03-15 09:57:24 +03:00
s - > packet_index = - 1 ;
2014-04-25 17:44:42 +04:00
amdtp_stream_pcm_abort ( s ) ;
2011-03-15 09:57:24 +03:00
return ;
}
2011-03-15 09:53:21 +03:00
2012-05-14 00:03:09 +04:00
if ( pcm )
2014-04-25 17:44:45 +04:00
update_pcm_pointers ( s , pcm , data_blocks ) ;
2012-05-14 00:03:09 +04:00
}
2014-04-25 17:44:46 +04:00
static void handle_in_packet ( struct amdtp_stream * s ,
unsigned int payload_quadlets ,
__be32 * buffer )
{
u32 cip_header [ 2 ] ;
2014-04-25 17:45:06 +04:00
unsigned int data_blocks , data_block_quadlets , data_block_counter ,
dbc_interval ;
2014-04-25 17:44:46 +04:00
struct snd_pcm_substream * pcm = NULL ;
2014-04-25 17:45:04 +04:00
bool lost ;
2014-04-25 17:44:46 +04:00
cip_header [ 0 ] = be32_to_cpu ( buffer [ 0 ] ) ;
cip_header [ 1 ] = be32_to_cpu ( buffer [ 1 ] ) ;
/*
* This module supports ' Two - quadlet CIP header with SYT field ' .
2014-04-25 17:44:50 +04:00
* For convenience , also check FMT field is AM824 or not .
2014-04-25 17:44:46 +04:00
*/
if ( ( ( cip_header [ 0 ] & CIP_EOH_MASK ) = = CIP_EOH ) | |
( ( cip_header [ 1 ] & CIP_EOH_MASK ) ! = CIP_EOH ) | |
( ( cip_header [ 1 ] & CIP_FMT_MASK ) ! = CIP_FMT_AM ) ) {
dev_info_ratelimited ( & s - > unit - > device ,
" Invalid CIP header for AMDTP: %08X:%08X \n " ,
cip_header [ 0 ] , cip_header [ 1 ] ) ;
goto end ;
}
/* Calculate data blocks */
if ( payload_quadlets < 3 | |
( ( cip_header [ 1 ] & CIP_FDF_MASK ) = =
( AMDTP_FDF_NO_DATA < < CIP_FDF_SFC_SHIFT ) ) ) {
data_blocks = 0 ;
} else {
data_block_quadlets =
( cip_header [ 0 ] & AMDTP_DBS_MASK ) > > AMDTP_DBS_SHIFT ;
/* avoid division by zero */
if ( data_block_quadlets = = 0 ) {
dev_info_ratelimited ( & s - > unit - > device ,
" Detect invalid value in dbs field: %08X \n " ,
cip_header [ 0 ] ) ;
goto err ;
}
2014-04-25 17:45:05 +04:00
if ( s - > flags & CIP_WRONG_DBS )
data_block_quadlets = s - > data_block_quadlets ;
2014-04-25 17:44:46 +04:00
data_blocks = ( payload_quadlets - 2 ) / data_block_quadlets ;
}
/* Check data block counter continuity */
data_block_counter = cip_header [ 0 ] & AMDTP_DBC_MASK ;
2014-04-25 17:45:07 +04:00
if ( ( s - > flags & CIP_SKIP_DBC_ZERO_CHECK ) & & data_block_counter = = 0 ) {
lost = false ;
} else if ( ! ( s - > flags & CIP_DBC_IS_END_EVENT ) ) {
2014-04-25 17:45:04 +04:00
lost = data_block_counter ! = s - > data_block_counter ;
2014-04-25 17:45:06 +04:00
} else {
if ( ( data_blocks > 0 ) & & ( s - > tx_dbc_interval > 0 ) )
dbc_interval = s - > tx_dbc_interval ;
else
dbc_interval = data_blocks ;
2014-04-25 17:45:04 +04:00
lost = data_block_counter ! =
2014-04-25 17:45:06 +04:00
( ( s - > data_block_counter + dbc_interval ) & 0xff ) ;
}
2014-04-25 17:45:04 +04:00
if ( lost ) {
2014-04-25 17:44:46 +04:00
dev_info ( & s - > unit - > device ,
" Detect discontinuity of CIP: %02X %02X \n " ,
s - > data_block_counter , data_block_counter ) ;
goto err ;
}
if ( data_blocks > 0 ) {
buffer + = 2 ;
pcm = ACCESS_ONCE ( s - > pcm ) ;
if ( pcm )
s - > transfer_samples ( s , pcm , buffer , data_blocks ) ;
ALSA: firewire-lib: Add support for MIDI capture/playback
For capturing/playbacking MIDI messages, this commit adds one MIDI conformant
data channel. This data channel has multiplexed 8 MIDI data streams. So this
data channel can transfer messages from/to 8 MIDI ports.
And this commit allows to set PCM format even if AMDTP streams already start.
I suppose the case that PCM substreams are going to be joined into AMDTP
streams when AMDTP streams are already started for MIDI substreams. Each
driver must count how many PCM/MIDI substreams use AMDTP streams to stop
AMDTP streams.
There are differences between specifications about MIDI conformant data.
About the multiplexing, IEC 61883-6:2002, itself, has no information. It
describes labels and bytes for MIDI messages and refers to MMA/AMEI RP-027
for 'successfull implementation'. MMA/AMEI RP-027 describes 8 MPX-MIDI data
streams for one MIDI conformant data channel. IEC 61883-6:2005 adds
'sequence multiplexing' and apply this way and describe incompatibility
between 2002 and 2005.
So this commit applies IEC 61883-6:2005. When we find some devices compliant
to IEC 61883-6:2002, then this difference should be handles as device quirk
in additional work.
About the number of bytes in an MIDI conformant data, IEC 61883-6:2002 describe
0,1,2,3 bytes. MMA/AMEI RP-027 describes 'MIDI1.0-1x-SPEED', 'MIDI1.0-2x-SPEED',
'MIDI1.0-3x-SPEED' modes and the maximum bytes for each mode corresponds to 1,
2, 3 bytes. The 'MIDI1.0-2x/3x-SPEED' modes are accompanied with 'negotiation
procedure' and 'encapsulation details' but there is no specifications for them.
So this commit implements 'MIDI1.0-1x-SPEED' mode for playback, but allows
to pick up 1-3 bytes for capturing.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-04-25 17:44:47 +04:00
if ( s - > midi_ports )
amdtp_pull_midi ( s , buffer , data_blocks ) ;
2014-04-25 17:44:46 +04:00
}
2014-04-25 17:45:04 +04:00
if ( s - > flags & CIP_DBC_IS_END_EVENT )
s - > data_block_counter = data_block_counter ;
else
s - > data_block_counter =
( data_block_counter + data_blocks ) & 0xff ;
2014-04-25 17:44:46 +04:00
end :
if ( queue_in_packet ( s ) < 0 )
goto err ;
if ( pcm )
update_pcm_pointers ( s , pcm , data_blocks ) ;
return ;
err :
s - > packet_index = - 1 ;
amdtp_stream_pcm_abort ( s ) ;
}
2014-04-25 17:44:45 +04:00
static void out_stream_callback ( struct fw_iso_context * context , u32 cycle ,
size_t header_length , void * header ,
void * private_data )
2011-03-15 09:53:21 +03:00
{
2014-04-25 17:44:42 +04:00
struct amdtp_stream * s = private_data ;
2014-04-25 17:44:48 +04:00
unsigned int i , syt , packets = header_length / 4 ;
2011-03-15 09:53:21 +03:00
/*
* Compute the cycle of the last queued packet .
* ( We need only the four lowest bits for the SYT , so we can ignore
* that bits 0 - 11 must wrap around at 3072. )
*/
cycle + = QUEUE_LENGTH - packets ;
2014-04-25 17:44:48 +04:00
for ( i = 0 ; i < packets ; + + i ) {
syt = calculate_syt ( s , + + cycle ) ;
handle_out_packet ( s , syt ) ;
}
2011-05-02 11:33:56 +04:00
fw_iso_context_queue_flush ( s - > context ) ;
2011-03-15 09:53:21 +03:00
}
2014-04-25 17:44:46 +04:00
static void in_stream_callback ( struct fw_iso_context * context , u32 cycle ,
size_t header_length , void * header ,
void * private_data )
{
struct amdtp_stream * s = private_data ;
2014-04-25 17:44:49 +04:00
unsigned int p , syt , packets , payload_quadlets ;
2014-04-25 17:44:46 +04:00
__be32 * buffer , * headers = header ;
/* The number of packets in buffer */
packets = header_length / IN_PACKET_HEADER_SIZE ;
for ( p = 0 ; p < packets ; p + + ) {
if ( s - > packet_index < 0 )
2014-04-25 17:44:49 +04:00
break ;
2014-04-25 17:44:46 +04:00
buffer = s - > buffer . packets [ s - > packet_index ] . buffer ;
2014-04-25 17:44:49 +04:00
/* Process sync slave stream */
if ( s - > sync_slave & & s - > sync_slave - > callbacked ) {
syt = be32_to_cpu ( buffer [ 1 ] ) & CIP_SYT_MASK ;
handle_out_packet ( s - > sync_slave , syt ) ;
}
2014-04-25 17:44:46 +04:00
/* The number of quadlets in this packet */
payload_quadlets =
( be32_to_cpu ( headers [ p ] ) > > ISO_DATA_LENGTH_SHIFT ) / 4 ;
handle_in_packet ( s , payload_quadlets , buffer ) ;
}
2014-04-25 17:44:49 +04:00
/* Queueing error or detecting discontinuity */
if ( s - > packet_index < 0 ) {
/* Abort sync slave. */
if ( s - > sync_slave ) {
s - > sync_slave - > packet_index = - 1 ;
amdtp_stream_pcm_abort ( s - > sync_slave ) ;
}
return ;
}
/* when sync to device, flush the packets for slave stream */
if ( s - > sync_slave & & s - > sync_slave - > callbacked )
fw_iso_context_queue_flush ( s - > sync_slave - > context ) ;
2014-04-25 17:44:46 +04:00
fw_iso_context_queue_flush ( s - > context ) ;
}
2014-04-25 17:44:49 +04:00
/* processing is done by master callback */
static void slave_stream_callback ( struct fw_iso_context * context , u32 cycle ,
size_t header_length , void * header ,
void * private_data )
{
return ;
}
/* this is executed one time */
static void amdtp_stream_first_callback ( struct fw_iso_context * context ,
u32 cycle , size_t header_length ,
void * header , void * private_data )
{
struct amdtp_stream * s = private_data ;
/*
* For in - stream , first packet has come .
* For out - stream , prepared to transmit first packet
*/
s - > callbacked = true ;
wake_up ( & s - > callback_wait ) ;
if ( s - > direction = = AMDTP_IN_STREAM )
context - > callback . sc = in_stream_callback ;
else if ( ( s - > flags & CIP_BLOCKING ) & & ( s - > flags & CIP_SYNC_TO_DEVICE ) )
context - > callback . sc = slave_stream_callback ;
else
context - > callback . sc = out_stream_callback ;
context - > callback . sc ( context , cycle , header_length , header , s ) ;
}
2011-03-15 09:53:21 +03:00
/**
2014-04-25 17:44:42 +04:00
* amdtp_stream_start - start transferring packets
* @ s : the AMDTP stream to start
2011-03-15 09:53:21 +03:00
* @ channel : the isochronous channel on the bus
* @ speed : firewire speed code
*
* The stream cannot be started until it has been configured with
2014-04-25 17:44:42 +04:00
* amdtp_stream_set_parameters ( ) and it must be started before any PCM or MIDI
* device can be started .
2011-03-15 09:53:21 +03:00
*/
2014-04-25 17:44:42 +04:00
int amdtp_stream_start ( struct amdtp_stream * s , int channel , int speed )
2011-03-15 09:53:21 +03:00
{
static const struct {
unsigned int data_block ;
unsigned int syt_offset ;
} initial_state [ ] = {
[ CIP_SFC_32000 ] = { 4 , 3072 } ,
[ CIP_SFC_48000 ] = { 6 , 1024 } ,
[ CIP_SFC_96000 ] = { 12 , 1024 } ,
[ CIP_SFC_192000 ] = { 24 , 1024 } ,
[ CIP_SFC_44100 ] = { 0 , 67 } ,
[ CIP_SFC_88200 ] = { 0 , 67 } ,
[ CIP_SFC_176400 ] = { 0 , 67 } ,
} ;
2014-04-25 17:44:46 +04:00
unsigned int header_size ;
enum dma_data_direction dir ;
2014-04-25 17:45:03 +04:00
int type , tag , err ;
2011-03-15 09:53:21 +03:00
mutex_lock ( & s - > mutex ) ;
2014-04-25 17:44:42 +04:00
if ( WARN_ON ( amdtp_stream_running ( s ) | |
2014-04-25 17:44:45 +04:00
( s - > data_block_quadlets < 1 ) ) ) {
2011-03-15 09:53:21 +03:00
err = - EBADFD ;
goto err_unlock ;
}
2014-04-25 17:44:45 +04:00
s - > data_block_counter = 0 ;
2011-03-15 09:53:21 +03:00
s - > data_block_state = initial_state [ s - > sfc ] . data_block ;
s - > syt_offset_state = initial_state [ s - > sfc ] . syt_offset ;
s - > last_syt_offset = TICKS_PER_CYCLE ;
2014-04-25 17:44:46 +04:00
/* initialize packet buffer */
if ( s - > direction = = AMDTP_IN_STREAM ) {
dir = DMA_FROM_DEVICE ;
type = FW_ISO_CONTEXT_RECEIVE ;
header_size = IN_PACKET_HEADER_SIZE ;
} else {
dir = DMA_TO_DEVICE ;
type = FW_ISO_CONTEXT_TRANSMIT ;
header_size = OUT_PACKET_HEADER_SIZE ;
}
2011-03-15 09:53:21 +03:00
err = iso_packets_buffer_init ( & s - > buffer , s - > unit , QUEUE_LENGTH ,
2014-04-25 17:44:46 +04:00
amdtp_stream_get_max_payload ( s ) , dir ) ;
2011-03-15 09:53:21 +03:00
if ( err < 0 )
goto err_unlock ;
s - > context = fw_iso_context_create ( fw_parent_device ( s - > unit ) - > card ,
2014-04-25 17:44:46 +04:00
type , channel , speed , header_size ,
2014-04-25 17:44:49 +04:00
amdtp_stream_first_callback , s ) ;
2011-03-15 09:53:21 +03:00
if ( IS_ERR ( s - > context ) ) {
err = PTR_ERR ( s - > context ) ;
if ( err = = - EBUSY )
dev_err ( & s - > unit - > device ,
2014-04-25 17:44:42 +04:00
" no free stream on this controller \n " ) ;
2011-03-15 09:53:21 +03:00
goto err_buffer ;
}
2014-04-25 17:44:42 +04:00
amdtp_stream_update ( s ) ;
2011-03-15 09:53:21 +03:00
2011-03-15 09:57:24 +03:00
s - > packet_index = 0 ;
2014-04-25 17:44:45 +04:00
do {
2014-04-25 17:44:46 +04:00
if ( s - > direction = = AMDTP_IN_STREAM )
err = queue_in_packet ( s ) ;
else
err = queue_out_packet ( s , 0 , true ) ;
2014-04-25 17:44:45 +04:00
if ( err < 0 )
goto err_context ;
} while ( s - > packet_index > 0 ) ;
2011-03-15 09:53:21 +03:00
2014-04-25 17:44:46 +04:00
/* NOTE: TAG1 matches CIP. This just affects in stream. */
2014-04-25 17:45:03 +04:00
tag = FW_ISO_CONTEXT_MATCH_TAG1 ;
if ( s - > flags & CIP_EMPTY_WITH_TAG0 )
tag | = FW_ISO_CONTEXT_MATCH_TAG0 ;
2014-04-25 17:44:49 +04:00
s - > callbacked = false ;
2014-04-25 17:45:03 +04:00
err = fw_iso_context_start ( s - > context , - 1 , 0 , tag ) ;
2011-03-15 09:53:21 +03:00
if ( err < 0 )
goto err_context ;
mutex_unlock ( & s - > mutex ) ;
return 0 ;
err_context :
fw_iso_context_destroy ( s - > context ) ;
s - > context = ERR_PTR ( - 1 ) ;
err_buffer :
iso_packets_buffer_destroy ( & s - > buffer , s - > unit ) ;
err_unlock :
mutex_unlock ( & s - > mutex ) ;
return err ;
}
2014-04-25 17:44:42 +04:00
EXPORT_SYMBOL ( amdtp_stream_start ) ;
2011-03-15 09:53:21 +03:00
2012-05-13 20:49:14 +04:00
/**
2014-04-25 17:44:42 +04:00
* amdtp_stream_pcm_pointer - get the PCM buffer position
* @ s : the AMDTP stream that transports the PCM data
2012-05-13 20:49:14 +04:00
*
* Returns the current buffer position , in frames .
*/
2014-04-25 17:44:42 +04:00
unsigned long amdtp_stream_pcm_pointer ( struct amdtp_stream * s )
2012-05-13 20:49:14 +04:00
{
2012-05-13 21:07:22 +04:00
/* this optimization is allowed to be racy */
2014-04-25 17:44:53 +04:00
if ( s - > pointer_flush & & amdtp_stream_running ( s ) )
2012-05-13 21:07:22 +04:00
fw_iso_context_flush_completions ( s - > context ) ;
else
s - > pointer_flush = true ;
2012-05-13 20:49:14 +04:00
return ACCESS_ONCE ( s - > pcm_buffer_pointer ) ;
}
2014-04-25 17:44:42 +04:00
EXPORT_SYMBOL ( amdtp_stream_pcm_pointer ) ;
2012-05-13 20:49:14 +04:00
2011-03-15 09:53:21 +03:00
/**
2014-04-25 17:44:42 +04:00
* amdtp_stream_update - update the stream after a bus reset
* @ s : the AMDTP stream
2011-03-15 09:53:21 +03:00
*/
2014-04-25 17:44:42 +04:00
void amdtp_stream_update ( struct amdtp_stream * s )
2011-03-15 09:53:21 +03:00
{
ACCESS_ONCE ( s - > source_node_id_field ) =
( fw_parent_device ( s - > unit ) - > card - > node_id & 0x3f ) < < 24 ;
}
2014-04-25 17:44:42 +04:00
EXPORT_SYMBOL ( amdtp_stream_update ) ;
2011-03-15 09:53:21 +03:00
/**
2014-04-25 17:44:42 +04:00
* amdtp_stream_stop - stop sending packets
* @ s : the AMDTP stream to stop
2011-03-15 09:53:21 +03:00
*
* All PCM and MIDI devices of the stream must be stopped before the stream
* itself can be stopped .
*/
2014-04-25 17:44:42 +04:00
void amdtp_stream_stop ( struct amdtp_stream * s )
2011-03-15 09:53:21 +03:00
{
mutex_lock ( & s - > mutex ) ;
2014-04-25 17:44:42 +04:00
if ( ! amdtp_stream_running ( s ) ) {
2011-03-15 09:53:21 +03:00
mutex_unlock ( & s - > mutex ) ;
return ;
}
2012-05-14 00:03:09 +04:00
tasklet_kill ( & s - > period_tasklet ) ;
2011-03-15 09:53:21 +03:00
fw_iso_context_stop ( s - > context ) ;
fw_iso_context_destroy ( s - > context ) ;
s - > context = ERR_PTR ( - 1 ) ;
iso_packets_buffer_destroy ( & s - > buffer , s - > unit ) ;
2014-04-25 17:44:49 +04:00
s - > callbacked = false ;
2011-03-15 09:53:21 +03:00
mutex_unlock ( & s - > mutex ) ;
}
2014-04-25 17:44:42 +04:00
EXPORT_SYMBOL ( amdtp_stream_stop ) ;
2011-03-15 09:53:21 +03:00
/**
2014-04-25 17:44:42 +04:00
* amdtp_stream_pcm_abort - abort the running PCM device
2011-03-15 09:53:21 +03:00
* @ s : the AMDTP stream about to be stopped
*
* If the isochronous stream needs to be stopped asynchronously , call this
* function first to stop the PCM device .
*/
2014-04-25 17:44:42 +04:00
void amdtp_stream_pcm_abort ( struct amdtp_stream * s )
2011-03-15 09:53:21 +03:00
{
struct snd_pcm_substream * pcm ;
pcm = ACCESS_ONCE ( s - > pcm ) ;
if ( pcm ) {
snd_pcm_stream_lock_irq ( pcm ) ;
if ( snd_pcm_running ( pcm ) )
snd_pcm_stop ( pcm , SNDRV_PCM_STATE_XRUN ) ;
snd_pcm_stream_unlock_irq ( pcm ) ;
}
}
2014-04-25 17:44:42 +04:00
EXPORT_SYMBOL ( amdtp_stream_pcm_abort ) ;