linux/sound/firewire/fireface/ff-protocol-former.c

// SPDX-License-Identifier: GPL-2.0
// ff-protocol-former.c - a part of driver for RME Fireface series
//
// Copyright (c) 2019 Takashi Sakamoto

#include <linux/delay.h>

#include "ff.h"

#define FORMER_REG_SYNC_STATUS
/* For block write request. */
#define FORMER_REG_FETCH_PCM_FRAMES
#define FORMER_REG_CLOCK_CONFIG

static int parse_clock_bits(u32 data, unsigned int *rate,
			    enum snd_ff_clock_src *src)
{}

static int former_get_clock(struct snd_ff *ff, unsigned int *rate,
			    enum snd_ff_clock_src *src)
{}

static int former_switch_fetching_mode(struct snd_ff *ff, bool enable)
{}

static void dump_clock_config(struct snd_ff *ff, struct snd_info_buffer *buffer)
{}

static void dump_sync_status(struct snd_ff *ff, struct snd_info_buffer *buffer)
{}

static void former_dump_status(struct snd_ff *ff,
			       struct snd_info_buffer *buffer)
{}

static int former_fill_midi_msg(struct snd_ff *ff,
				struct snd_rawmidi_substream *substream,
				unsigned int port)
{}

#define FF800_STF
#define FF800_RX_PACKET_FORMAT
#define FF800_ALLOC_TX_STREAM
#define FF800_ISOC_COMM_START
#define FF800_TX_S800_FLAG
#define FF800_ISOC_COMM_STOP

#define FF800_TX_PACKET_ISOC_CH

static int allocate_tx_resources(struct snd_ff *ff)
{}

static int ff800_allocate_resources(struct snd_ff *ff, unsigned int rate)
{}

static int ff800_begin_session(struct snd_ff *ff, unsigned int rate)
{}

static void ff800_finish_session(struct snd_ff *ff)
{}

// Fireface 800 doesn't allow drivers to register lower 4 bytes of destination
// address.
// A write transaction to clear registered higher 4 bytes of destination address
// has an effect to suppress asynchronous transaction from device.
static void ff800_handle_midi_msg(struct snd_ff *ff, unsigned int offset, const __le32 *buf,
				  size_t length, u32 tstamp)
{}

const struct snd_ff_protocol snd_ff_protocol_ff800 =;

#define FF400_STF
#define FF400_RX_PACKET_FORMAT
#define FF400_ISOC_COMM_START
#define FF400_TX_PACKET_FORMAT
#define FF400_ISOC_COMM_STOP

// Fireface 400 manages isochronous channel number in 3 bit field. Therefore,
// we can allocate between 0 and 7 channel.
static int ff400_allocate_resources(struct snd_ff *ff, unsigned int rate)
{}

static int ff400_begin_session(struct snd_ff *ff, unsigned int rate)
{}

static void ff400_finish_session(struct snd_ff *ff)
{}

static void parse_midi_msg(struct snd_ff *ff, u32 quad, unsigned int port)
{}

#define FF400_QUEUE_SIZE

struct ff400_msg_parser {};

static bool ff400_has_msg(struct snd_ff *ff)
{}

// For Fireface 400, lower 4 bytes of destination address is configured by bit
// flag in quadlet register (little endian) at 0x'0000'801'0051c. Drivers can
// select one of 4 options:
//
// bit flags: offset of destination address
//  - 0x04000000: 0x'....'....'0000'0000
//  - 0x08000000: 0x'....'....'0000'0080
//  - 0x10000000: 0x'....'....'0000'0100
//  - 0x20000000: 0x'....'....'0000'0180
//
// Drivers can suppress the device to transfer asynchronous transactions by
// using below 2 bits.
//  - 0x01000000: suppress transmission
//  - 0x02000000: suppress transmission
//
// Actually, the register is write-only and includes the other options such as
// input attenuation. This driver allocates destination address with '0000'0000
// in its lower offset and expects userspace application to configure the
// register for it.

// When the message is for signal level operation, the upper 4 bits in MSB expresses the pair of
// stereo physical port.
// - 0: Microphone input 0/1
// - 1: Line input 0/1
// - [2-4]: Line output 0-5
// - 5: Headphone output 0/1
// - 6: S/PDIF output 0/1
// - [7-10]: ADAT output 0-7
//
// The value of signal level can be detected by mask of 0x00fffc00. For signal level of microphone
// input:
//
// - 0:    0.0 dB
// - 10: +10.0 dB
// - 11: +11.0 dB
// - 12: +12.0 dB
// - ...
// - 63: +63.0 dB:
// - 64: +64.0 dB:
// - 65: +65.0 dB:
//
// For signal level of line input:
//
// - 0:  0.0 dB
// - 1: +0.5 dB
// - 2: +1.0 dB
// - 3: +1.5 dB
// - ...
// - 34: +17.0 dB:
// - 35: +17.5 dB:
// - 36: +18.0 dB:
//
// For signal level of any type of output:
//
// - 63: -infinite
// - 62: -58.0 dB
// - 61: -56.0 dB
// - 60: -54.0 dB
// - 59: -53.0 dB
// - 58: -52.0 dB
// - ...
// - 7: -1.0 dB
// - 6:  0.0 dB
// - 5: +1.0 dB
// - ...
// - 2: +4.0 dB
// - 1: +5.0 dB
// - 0: +6.0 dB
//
// When the message is not for signal level operation, it's for MIDI bytes. When matching to
// FF400_MSG_FLAG_IS_MIDI_PORT_0, one MIDI byte can be detected by mask of 0x000000ff. When
// matching to FF400_MSG_FLAG_IS_MIDI_PORT_1, one MIDI byte can be detected by mask of 0x00ff0000.
#define FF400_MSG_FLAG_IS_SIGNAL_LEVEL
#define FF400_MSG_FLAG_IS_RIGHT_CHANNEL
#define FF400_MSG_FLAG_IS_STEREO_PAIRED
#define FF400_MSG_MASK_STEREO_PAIR
#define FF400_MSG_MASK_SIGNAL_LEVEL
#define FF400_MSG_FLAG_IS_MIDI_PORT_0
#define FF400_MSG_MASK_MIDI_PORT_0
#define FF400_MSG_FLAG_IS_MIDI_PORT_1
#define FF400_MSG_MASK_MIDI_PORT_1

static void ff400_handle_msg(struct snd_ff *ff, unsigned int offset, const __le32 *buf,
			     size_t length, u32 tstamp)
{}

static long ff400_copy_msg_to_user(struct snd_ff *ff, char __user *buf, long count)
{}

const struct snd_ff_protocol snd_ff_protocol_ff400 =;