ALSA: fireface: add support for Fireface 800 with MIDI functionality only
Fireface 800 is a flagship model of RME GmbH for audio and music units on IEEE 1394 bus, shipped 2004. This model consists of four chips: - TI TSB81BA3D for physical layer on cable environment of EEE 1394 bus - TI TSB82AA2 for link layer for 1394 OHCI bus bridge to PCI bus - Xilinx Spartan-3 FPGA XC3S400 - Xilinx High-Performance CPLD XC9572XL This commit adds support Fireface 800. In this time, the support is restricted to its MIDI functionality, thus this commit adds some condition statements to avoid touching streaming functionality. Unlike Fireface 400, Fireface 800 has no functionality to suppress asynchronous transactions for MIDI messages except for unregister of listen address in controller side, thus the feature is available as is. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
aef4ad2f5a
commit
a91f676074
|
@ -162,5 +162,6 @@ config SND_FIREFACE
|
|||
help
|
||||
Say Y here to include support for RME fireface series.
|
||||
* Fireface 400
|
||||
* Fireface 800
|
||||
|
||||
endif # SND_FIREWIRE
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
snd-fireface-objs := ff.o ff-transaction.o ff-midi.o ff-proc.o amdtp-ff.o \
|
||||
ff-stream.o ff-pcm.o ff-hwdep.o ff-protocol-ff400.o
|
||||
ff-stream.o ff-pcm.o ff-hwdep.o ff-protocol-ff400.o \
|
||||
ff-protocol-ff800.o
|
||||
obj-$(CONFIG_SND_FIREFACE) += snd-fireface.o
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* ff-protocol-ff800.c - a part of driver for RME Fireface series
|
||||
*
|
||||
* Copyright (c) 2018 Takashi Sakamoto
|
||||
*
|
||||
* Licensed under the terms of the GNU General Public License, version 2.
|
||||
*/
|
||||
|
||||
#include "ff.h"
|
||||
|
||||
static void ff800_handle_midi_msg(struct snd_ff *ff, __le32 *buf, size_t length)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < length / 4; i++) {
|
||||
u8 byte = le32_to_cpu(buf[i]) & 0xff;
|
||||
struct snd_rawmidi_substream *substream;
|
||||
|
||||
substream = READ_ONCE(ff->tx_midi_substreams[0]);
|
||||
if (substream)
|
||||
snd_rawmidi_receive(substream, &byte, 1);
|
||||
}
|
||||
}
|
||||
|
||||
const struct snd_ff_protocol snd_ff_protocol_ff800 = {
|
||||
.handle_midi_msg = ff800_handle_midi_msg,
|
||||
};
|
|
@ -31,7 +31,8 @@ static void ff_card_free(struct snd_card *card)
|
|||
{
|
||||
struct snd_ff *ff = card->private_data;
|
||||
|
||||
snd_ff_stream_destroy_duplex(ff);
|
||||
if (ff->spec->protocol->begin_session)
|
||||
snd_ff_stream_destroy_duplex(ff);
|
||||
snd_ff_transaction_unregister(ff);
|
||||
}
|
||||
|
||||
|
@ -56,9 +57,11 @@ static void do_registration(struct work_struct *work)
|
|||
|
||||
name_card(ff);
|
||||
|
||||
err = snd_ff_stream_init_duplex(ff);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
if (ff->spec->protocol->begin_session) {
|
||||
err = snd_ff_stream_init_duplex(ff);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
snd_ff_proc_init(ff);
|
||||
|
||||
|
@ -66,13 +69,15 @@ static void do_registration(struct work_struct *work)
|
|||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
err = snd_ff_create_pcm_devices(ff);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
if (ff->spec->protocol->begin_session) {
|
||||
err = snd_ff_create_pcm_devices(ff);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
err = snd_ff_create_hwdep_devices(ff);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
err = snd_ff_create_hwdep_devices(ff);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
err = snd_card_register(ff->card);
|
||||
if (err < 0)
|
||||
|
@ -121,7 +126,7 @@ static void snd_ff_update(struct fw_unit *unit)
|
|||
|
||||
snd_ff_transaction_reregister(ff);
|
||||
|
||||
if (ff->registered)
|
||||
if (ff->registered && ff->spec->protocol->begin_session)
|
||||
snd_ff_stream_update_duplex(ff);
|
||||
}
|
||||
|
||||
|
@ -145,6 +150,16 @@ static void snd_ff_remove(struct fw_unit *unit)
|
|||
fw_unit_put(ff->unit);
|
||||
}
|
||||
|
||||
static const struct snd_ff_spec spec_ff800 = {
|
||||
.name = "Fireface800",
|
||||
.midi_in_ports = 1,
|
||||
.midi_out_ports = 1,
|
||||
.protocol = &snd_ff_protocol_ff800,
|
||||
.regs = {
|
||||
[SND_FF_REG_TYPE_MIDI_HIGH_ADDR] = 0x000200000320ull,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct snd_ff_spec spec_ff400 = {
|
||||
.name = "Fireface400",
|
||||
.pcm_capture_channels = {18, 14, 10},
|
||||
|
@ -158,6 +173,18 @@ static const struct snd_ff_spec spec_ff400 = {
|
|||
};
|
||||
|
||||
static const struct ieee1394_device_id snd_ff_id_table[] = {
|
||||
/* Fireface 800 */
|
||||
{
|
||||
.match_flags = IEEE1394_MATCH_VENDOR_ID |
|
||||
IEEE1394_MATCH_SPECIFIER_ID |
|
||||
IEEE1394_MATCH_VERSION |
|
||||
IEEE1394_MATCH_MODEL_ID,
|
||||
.vendor_id = OUI_RME,
|
||||
.specifier_id = OUI_RME,
|
||||
.version = 0x000001,
|
||||
.model_id = 0x101800,
|
||||
.driver_data = (kernel_ulong_t)&spec_ff800,
|
||||
},
|
||||
/* Fireface 400 */
|
||||
{
|
||||
.match_flags = IEEE1394_MATCH_VENDOR_ID |
|
||||
|
@ -165,7 +192,7 @@ static const struct ieee1394_device_id snd_ff_id_table[] = {
|
|||
IEEE1394_MATCH_VERSION |
|
||||
IEEE1394_MATCH_MODEL_ID,
|
||||
.vendor_id = OUI_RME,
|
||||
.specifier_id = 0x000a35,
|
||||
.specifier_id = OUI_RME,
|
||||
.version = 0x000002,
|
||||
.model_id = 0x101800,
|
||||
.driver_data = (kernel_ulong_t)&spec_ff400,
|
||||
|
|
|
@ -114,6 +114,7 @@ struct snd_ff_protocol {
|
|||
int (*switch_fetching_mode)(struct snd_ff *ff, bool enable);
|
||||
};
|
||||
|
||||
extern const struct snd_ff_protocol snd_ff_protocol_ff800;
|
||||
extern const struct snd_ff_protocol snd_ff_protocol_ff400;
|
||||
|
||||
int snd_ff_transaction_get_clock(struct snd_ff *ff, unsigned int *rate,
|
||||
|
|
Loading…
Reference in New Issue