2015-10-01 22:02:11 +09:00
/*
* tascam . h - a part of driver for TASCAM FireWire series
*
* Copyright ( c ) 2015 Takashi Sakamoto
*
* Licensed under the terms of the GNU General Public License , version 2.
*/
# ifndef SOUND_TASCAM_H_INCLUDED
# define SOUND_TASCAM_H_INCLUDED
# include <linux/device.h>
# include <linux/firewire.h>
# include <linux/firewire-constants.h>
# include <linux/module.h>
# include <linux/mod_devicetable.h>
# include <linux/mutex.h>
# include <linux/slab.h>
# include <linux/compat.h>
2017-02-02 19:15:33 +01:00
# include <linux/sched/signal.h>
2015-10-01 22:02:11 +09:00
# include <sound/core.h>
# include <sound/initval.h>
2015-10-01 22:02:13 +09:00
# include <sound/info.h>
2015-10-01 22:02:14 +09:00
# include <sound/pcm.h>
# include <sound/pcm_params.h>
2015-10-01 22:02:17 +09:00
# include <sound/firewire.h>
# include <sound/hwdep.h>
2015-10-12 19:10:21 +09:00
# include <sound/rawmidi.h>
2015-10-01 22:02:11 +09:00
# include "../lib.h"
2015-10-01 22:02:14 +09:00
# include "../amdtp-stream.h"
2015-10-01 22:02:15 +09:00
# include "../iso-resources.h"
2015-10-01 22:02:11 +09:00
2015-10-01 22:02:12 +09:00
struct snd_tscm_spec {
const char * const name ;
bool has_adat ;
bool has_spdif ;
unsigned int pcm_capture_analog_channels ;
unsigned int pcm_playback_analog_channels ;
unsigned int midi_capture_ports ;
unsigned int midi_playback_ports ;
} ;
2015-10-12 19:10:21 +09:00
# define TSCM_MIDI_IN_PORT_MAX 4
# define TSCM_MIDI_OUT_PORT_MAX 4
2017-04-14 16:46:25 +09:00
struct snd_fw_async_midi_port {
struct fw_device * parent ;
struct work_struct work ;
bool idling ;
ktime_t next_ktime ;
bool error ;
struct fw_transaction transaction ;
2017-04-14 16:46:29 +09:00
u8 buf [ 4 ] ;
2017-04-14 16:46:31 +09:00
u8 running_status ;
bool on_sysex ;
2017-04-14 16:46:25 +09:00
struct snd_rawmidi_substream * substream ;
int consume_bytes ;
} ;
2018-11-23 13:13:05 +09:00
# define SND_TSCM_QUEUE_COUNT 16
2015-10-01 22:02:11 +09:00
struct snd_tscm {
struct snd_card * card ;
struct fw_unit * unit ;
struct mutex mutex ;
2015-10-01 22:02:17 +09:00
spinlock_t lock ;
2015-10-01 22:02:12 +09:00
2016-03-31 08:47:09 +09:00
bool registered ;
struct delayed_work dwork ;
2015-10-01 22:02:12 +09:00
const struct snd_tscm_spec * spec ;
2015-10-01 22:02:15 +09:00
struct fw_iso_resources tx_resources ;
struct fw_iso_resources rx_resources ;
struct amdtp_stream tx_stream ;
struct amdtp_stream rx_stream ;
unsigned int substreams_counter ;
2015-10-01 22:02:17 +09:00
int dev_lock_count ;
bool dev_lock_changed ;
wait_queue_head_t hwdep_wait ;
2015-10-12 19:10:21 +09:00
/* For MIDI message incoming transactions. */
struct fw_address_handler async_handler ;
struct snd_rawmidi_substream * tx_midi_substreams [ TSCM_MIDI_IN_PORT_MAX ] ;
2015-10-12 19:10:22 +09:00
/* For MIDI message outgoing transactions. */
struct snd_fw_async_midi_port out_ports [ TSCM_MIDI_OUT_PORT_MAX ] ;
2018-11-23 13:13:03 +09:00
// A cache of status information in tx isoc packets.
__be32 state [ SNDRV_FIREWIRE_TASCAM_STATE_COUNT ] ;
2018-11-23 13:13:05 +09:00
struct snd_hwdep * hwdep ;
struct snd_firewire_tascam_change queue [ SND_TSCM_QUEUE_COUNT ] ;
unsigned int pull_pos ;
unsigned int push_pos ;
2015-10-01 22:02:11 +09:00
} ;
2015-10-01 22:02:13 +09:00
# define TSCM_ADDR_BASE 0xffff00000000ull
# define TSCM_OFFSET_FIRMWARE_REGISTER 0x0000
# define TSCM_OFFSET_FIRMWARE_FPGA 0x0004
# define TSCM_OFFSET_FIRMWARE_ARM 0x0008
# define TSCM_OFFSET_FIRMWARE_HW 0x000c
2015-10-01 22:02:15 +09:00
# define TSCM_OFFSET_ISOC_TX_CH 0x0200
# define TSCM_OFFSET_UNKNOWN 0x0204
# define TSCM_OFFSET_START_STREAMING 0x0208
# define TSCM_OFFSET_ISOC_RX_CH 0x020c
# define TSCM_OFFSET_ISOC_RX_ON 0x0210 /* Little conviction. */
# define TSCM_OFFSET_TX_PCM_CHANNELS 0x0214
# define TSCM_OFFSET_RX_PCM_CHANNELS 0x0218
# define TSCM_OFFSET_MULTIPLEX_MODE 0x021c
# define TSCM_OFFSET_ISOC_TX_ON 0x0220
/* Unknown 0x0224 */
# define TSCM_OFFSET_CLOCK_STATUS 0x0228
# define TSCM_OFFSET_SET_OPTION 0x022c
2015-10-12 19:10:21 +09:00
# define TSCM_OFFSET_MIDI_TX_ON 0x0300
# define TSCM_OFFSET_MIDI_TX_ADDR_HI 0x0304
# define TSCM_OFFSET_MIDI_TX_ADDR_LO 0x0308
2015-10-12 19:10:24 +09:00
# define TSCM_OFFSET_LED_POWER 0x0404
2015-10-12 19:10:21 +09:00
# define TSCM_OFFSET_MIDI_RX_QUAD 0x4000
2015-10-01 22:02:15 +09:00
enum snd_tscm_clock {
SND_TSCM_CLOCK_INTERNAL = 0 ,
SND_TSCM_CLOCK_WORD = 1 ,
SND_TSCM_CLOCK_SPDIF = 2 ,
SND_TSCM_CLOCK_ADAT = 3 ,
} ;
2015-10-01 22:02:14 +09:00
int amdtp_tscm_init ( struct amdtp_stream * s , struct fw_unit * unit ,
enum amdtp_stream_direction dir , unsigned int pcm_channels ) ;
int amdtp_tscm_set_parameters ( struct amdtp_stream * s , unsigned int rate ) ;
int amdtp_tscm_add_pcm_hw_constraints ( struct amdtp_stream * s ,
struct snd_pcm_runtime * runtime ) ;
2015-10-01 22:02:15 +09:00
int snd_tscm_stream_get_rate ( struct snd_tscm * tscm , unsigned int * rate ) ;
int snd_tscm_stream_get_clock ( struct snd_tscm * tscm ,
enum snd_tscm_clock * clock ) ;
int snd_tscm_stream_init_duplex ( struct snd_tscm * tscm ) ;
void snd_tscm_stream_update_duplex ( struct snd_tscm * tscm ) ;
void snd_tscm_stream_destroy_duplex ( struct snd_tscm * tscm ) ;
int snd_tscm_stream_start_duplex ( struct snd_tscm * tscm , unsigned int rate ) ;
void snd_tscm_stream_stop_duplex ( struct snd_tscm * tscm ) ;
2015-10-01 22:02:17 +09:00
void snd_tscm_stream_lock_changed ( struct snd_tscm * tscm ) ;
int snd_tscm_stream_lock_try ( struct snd_tscm * tscm ) ;
void snd_tscm_stream_lock_release ( struct snd_tscm * tscm ) ;
2017-04-14 16:46:30 +09:00
void snd_fw_async_midi_port_init ( struct snd_fw_async_midi_port * port ) ;
2017-04-14 16:46:25 +09:00
static inline void
snd_fw_async_midi_port_run ( struct snd_fw_async_midi_port * port ,
struct snd_rawmidi_substream * substream )
{
if ( ! port - > error ) {
port - > substream = substream ;
schedule_work ( & port - > work ) ;
}
}
static inline void
snd_fw_async_midi_port_finish ( struct snd_fw_async_midi_port * port )
{
port - > substream = NULL ;
2017-04-14 16:46:29 +09:00
cancel_work_sync ( & port - > work ) ;
2017-04-14 16:46:25 +09:00
port - > error = false ;
}
2015-10-12 19:10:21 +09:00
int snd_tscm_transaction_register ( struct snd_tscm * tscm ) ;
int snd_tscm_transaction_reregister ( struct snd_tscm * tscm ) ;
void snd_tscm_transaction_unregister ( struct snd_tscm * tscm ) ;
2015-10-01 22:02:13 +09:00
void snd_tscm_proc_init ( struct snd_tscm * tscm ) ;
2015-10-01 22:02:16 +09:00
int snd_tscm_create_pcm_devices ( struct snd_tscm * tscm ) ;
2015-10-12 19:10:23 +09:00
int snd_tscm_create_midi_devices ( struct snd_tscm * tscm ) ;
2015-10-01 22:02:17 +09:00
int snd_tscm_create_hwdep_device ( struct snd_tscm * tscm ) ;
2015-10-01 22:02:11 +09:00
# endif