[alsa-devel] [PATCH 1/8] add main file of driver module

o-takashi at sakamocchi.jp o-takashi at sakamocchi.jp
Sat Jun 1 17:55:51 CEST 2013


From: Takashi Sakamoto <o-takashi at sakamocchi.jp>

This driver module is an application of Firewire stack (Juju) and ALSA.
This file includes prove() function to be a device driver for firewire bus.

Signed-off-by: Takashi Sakamoto <o-takashi at sakamocchi.jp>
---
 sound/firewire/fireworks/fireworks.c |  488 ++++++++++++++++++++++++++++++++++
 sound/firewire/fireworks/fireworks.h |  241 +++++++++++++++++
 2 files changed, 729 insertions(+)
 create mode 100644 sound/firewire/fireworks/fireworks.c
 create mode 100644 sound/firewire/fireworks/fireworks.h

diff --git a/sound/firewire/fireworks/fireworks.c b/sound/firewire/fireworks/fireworks.c
new file mode 100644
index 0000000..c4cd0c0
--- /dev/null
+++ b/sound/firewire/fireworks/fireworks.c
@@ -0,0 +1,488 @@
+/*
+ * fireworks.c - driver for Firewire devices from Echo Digital Audio
+ *
+ * Copyright (c) 2009-2010 Clemens Ladisch
+ * Copyright (c) 2013 Takashi Sakamoto
+ *
+ *
+ * This driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2.
+ *
+ * This driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this driver; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "fireworks.h"
+
+MODULE_DESCRIPTION("Echo Fireworks driver");
+MODULE_AUTHOR("Clemens Ladisch <clemens at ladisch.de>");
+MODULE_LICENSE("GPL v2");
+
+static int index[SNDRV_CARDS]	= SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS]	= SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS]	= SNDRV_DEFAULT_ENABLE_PNP;
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "card index");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "enable Fireworks sound card");
+
+static DEFINE_MUTEX(devices_mutex);
+static unsigned int devices_used;
+
+#define FLAG_DYNADDR_SUPPORTED			0
+#define FLAG_MIRRORING_SUPPORTED		1
+#define FLAG_SPDIF_COAX_SUPPORTED		2
+#define FLAG_SPDIF_AES_EBU_XLR_SUPPORTED	3
+#define FLAG_HAS_DSP_MIXER			4
+#define FLAG_HAS_FPGA				5
+#define FLAG_HAS_PHANTOM			6
+/* other flags exist but unknown... */
+
+static int
+get_hardware_info(struct snd_efw *efw)
+{
+	int err;
+
+	struct snd_efw_hwinfo *hwinfo;
+	char version[12];
+	int size;
+	int i;
+
+	hwinfo = kzalloc(sizeof(struct snd_efw_hwinfo), GFP_KERNEL);
+	if (hwinfo == NULL)
+		return -ENOMEM;
+
+	err = snd_efw_command_get_hwinfo(efw, hwinfo);
+	if (err < 0)
+		goto end;
+
+	/* capabilities */
+	if (hwinfo->flags & (1 << FLAG_DYNADDR_SUPPORTED))
+		efw->dynaddr_support = 1;
+	if (hwinfo->flags & (1 << FLAG_MIRRORING_SUPPORTED))
+		efw->mirroring_support = 1;
+	if (hwinfo->flags & (1 << FLAG_SPDIF_AES_EBU_XLR_SUPPORTED))
+		efw->aes_ebu_xlr_support = 1;
+	if (hwinfo->flags & (1 << FLAG_HAS_DSP_MIXER))
+		efw->has_dsp_mixer = 1;
+	if (hwinfo->flags & (1 << FLAG_HAS_FPGA))
+		efw->has_fpga = 1;
+	if (hwinfo->flags & (1 << FLAG_HAS_PHANTOM))
+		efw->has_phantom = 1;
+	if (hwinfo->flags & (1 << FLAG_SPDIF_COAX_SUPPORTED)) {
+		efw->supported_digital_interface = BIT(2) | BIT(3);
+		/* TODO: find better way... */
+		if (strcmp(hwinfo->model_name, "AudioFire8a")
+		 || strcmp(hwinfo->model_name, "AudioFirePre8"))
+			efw->supported_digital_interface |= BIT(0);
+	}
+
+	/* for input physical metering */
+	if (hwinfo->nb_out_groups > 0) {
+		size = sizeof(struct snd_efw_phys_group) *
+						hwinfo->nb_out_groups;
+		efw->output_groups = kzalloc(size, GFP_KERNEL);
+		if (efw->output_groups == NULL) {
+			err = -ENOMEM;
+			goto error;
+		}
+
+		efw->output_group_counts = hwinfo->nb_out_groups;
+		for (i = 0; i < efw->output_group_counts; i += 1) {
+			efw->output_groups[i].type  =
+						hwinfo->out_groups[i].type;
+			efw->output_groups[i].count =
+						hwinfo->out_groups[i].count;
+		}
+	}
+
+	/* for output physical metering */
+	if (hwinfo->nb_in_groups > 0) {
+		size = sizeof(struct snd_efw_phys_group) *
+						hwinfo->nb_in_groups;
+		efw->input_groups = kzalloc(size, GFP_KERNEL);
+		if (efw->input_groups == NULL) {
+			err = -ENOMEM;
+			goto error;
+		}
+
+		efw->input_group_counts = hwinfo->nb_out_groups;
+		for (i = 0; i < efw->input_group_counts; i += 1) {
+			efw->input_groups[i].type =
+						hwinfo->in_groups[i].type;
+			efw->input_groups[i].count =
+						hwinfo->in_groups[i].count;
+		}
+	}
+
+	/* for mixer channels */
+	efw->mixer_output_channels = hwinfo->mixer_playback_channels;
+	efw->mixer_input_channels = hwinfo->mixer_capture_channels;
+
+	/* fill channels sets */
+	efw->pcm_capture_channels[0] = hwinfo->nb_1394_capture_channels;
+	efw->pcm_capture_channels[1] = hwinfo->nb_1394_capture_channels_2x;
+	efw->pcm_capture_channels[2] = hwinfo->nb_1394_capture_channels_4x;
+	efw->pcm_playback_channels[0] = hwinfo->nb_1394_playback_channels;
+	efw->pcm_playback_channels[1] = hwinfo->nb_1394_playback_channels_2x;
+	efw->pcm_playback_channels[2] = hwinfo->nb_1394_playback_channels_4x;
+
+	/* firmware version */
+	err = sprintf(version, "%u.%u",
+			(hwinfo->arm_version >> 24) & 0xff,
+			(hwinfo->arm_version >> 16) & 0xff);
+
+	/* set names */
+	strcpy(efw->card->driver, "Fireworks");
+	strcpy(efw->card->shortname, hwinfo->model_name);
+	snprintf(efw->card->longname, sizeof(efw->card->longname),
+		"%s %s v%s, GUID %08x%08x at %s, S%d",
+		hwinfo->vendor_name, hwinfo->model_name, version,
+		hwinfo->guid_hi, hwinfo->guid_lo,
+		dev_name(&efw->unit->device), 100 << efw->device->max_speed);
+	strcpy(efw->card->mixername, hwinfo->model_name);
+
+	/* set flag for supported clock source */
+	efw->supported_clock_source = hwinfo->supported_clocks;
+
+	/* set flag for supported sampling rate */
+	efw->supported_sampling_rate = 0;
+	if ((hwinfo->min_sample_rate <= 22050)
+	 && (22050 <= hwinfo->max_sample_rate))
+		efw->supported_sampling_rate |= SNDRV_PCM_RATE_22050;
+	if ((hwinfo->min_sample_rate <= 32000)
+	 && (32000 <= hwinfo->max_sample_rate))
+		efw->supported_sampling_rate |= SNDRV_PCM_RATE_32000;
+	if ((hwinfo->min_sample_rate <= 44100)
+	 && (44100 <= hwinfo->max_sample_rate))
+		efw->supported_sampling_rate |= SNDRV_PCM_RATE_44100;
+	if ((hwinfo->min_sample_rate <= 48000)
+	 && (48000 <= hwinfo->max_sample_rate))
+		efw->supported_sampling_rate |= SNDRV_PCM_RATE_48000;
+	if ((hwinfo->min_sample_rate <= 88200)
+	 && (88200 <= hwinfo->max_sample_rate))
+		efw->supported_sampling_rate |= SNDRV_PCM_RATE_88200;
+	if ((hwinfo->min_sample_rate <= 96000)
+	 && (96000 <= hwinfo->max_sample_rate))
+		efw->supported_sampling_rate |= SNDRV_PCM_RATE_96000;
+	if ((hwinfo->min_sample_rate <= 176400)
+	 && (176400 <= hwinfo->max_sample_rate))
+		efw->supported_sampling_rate |= SNDRV_PCM_RATE_176400;
+	if ((hwinfo->min_sample_rate <= 192000)
+	 && (192000 <= hwinfo->max_sample_rate))
+		efw->supported_sampling_rate |= SNDRV_PCM_RATE_192000;
+
+	/* MIDI inputs and outputs */
+	efw->midi_output_ports = hwinfo->nb_midi_out;
+	efw->midi_input_ports = hwinfo->nb_midi_in;
+
+	err = 0;
+	goto end;
+
+error:
+	if (efw->input_group_counts > 0)
+		kfree(efw->input_groups);
+	if (efw->output_group_counts > 0)
+		kfree(efw->output_groups);
+end:
+	kfree(hwinfo);
+	return err;
+}
+
+static int
+get_hardware_meters_count(struct snd_efw *efw)
+{
+	int err;
+	struct snd_efw_phys_meters *meters;
+
+	meters = kzalloc(sizeof(struct snd_efw_phys_meters), GFP_KERNEL);
+	if (meters == NULL)
+		return -ENOMEM;
+
+	err = snd_efw_command_get_phys_meters(efw, meters,
+				sizeof(struct snd_efw_phys_meters));
+	if (err < 0)
+		goto end;
+
+	efw->input_meter_counts = meters->nb_input_meters;
+	efw->output_meter_counts = meters->nb_output_meters;
+
+	err = 0;
+end:
+	kfree(meters);
+	return err;
+}
+
+static void
+snd_efw_update(struct fw_unit *unit)
+{
+	struct snd_card *card = dev_get_drvdata(&unit->device);
+	struct snd_efw *efw = card->private_data;
+
+	fcp_bus_reset(efw->unit);
+
+	/* bus reset for isochronous transmit stream */
+	if (cmp_connection_update(&efw->output_connection) < 0) {
+		amdtp_stream_pcm_abort(&efw->receive_stream);
+		mutex_lock(&efw->mutex);
+		snd_efw_stream_stop(efw, &efw->receive_stream);
+		mutex_unlock(&efw->mutex);
+	}
+	amdtp_stream_update(&efw->receive_stream);
+
+	/* bus reset for isochronous receive stream */
+	if (cmp_connection_update(&efw->input_connection) < 0) {
+		amdtp_stream_pcm_abort(&efw->transmit_stream);
+		mutex_lock(&efw->mutex);
+		snd_efw_stream_stop(efw, &efw->transmit_stream);
+		mutex_unlock(&efw->mutex);
+	}
+	amdtp_stream_update(&efw->transmit_stream);
+
+	return;
+}
+
+static bool match_fireworks_device_name(struct fw_unit *unit)
+{
+	static const char *const models[] = {
+		/* Echo Digital Audio */
+		"AudioFire2",
+		"AudioFire4",
+		"AudioFire8",
+		"AudioFire8a",
+		"AudioFirePre8",
+		"AudioFire12",
+		"Fireworks8",
+		"Fireworks HDMI",
+		/* Mackie */
+		"Onyx 400F",
+		"Onyx 1200F",
+		/* Gibson */
+		"RIP",
+		"Audiopunk",
+		"Goldtop",
+	};
+	char name[16];
+	unsigned int i;
+
+	if (fw_csr_string(unit->directory, CSR_MODEL, name, sizeof(name)) < 0)
+		return false;
+	for (i = 0; i < ARRAY_SIZE(models); i++)
+		if (!strcasecmp(name, models[i]))
+			return true;
+	return false;
+}
+
+static void
+snd_efw_card_free(struct snd_card *card)
+{
+	struct snd_efw *efw = card->private_data;
+
+	if (efw->card_index >= 0) {
+		mutex_lock(&devices_mutex);
+		devices_used &= ~(1 << efw->card_index);
+		mutex_unlock(&devices_mutex);
+	}
+
+	if (efw->output_group_counts > 0)
+		kfree(efw->output_groups);
+	if (efw->input_group_counts > 0)
+		kfree(efw->input_groups);
+
+	mutex_destroy(&efw->mutex);
+
+	return;
+}
+
+static int
+snd_efw_probe(struct device *dev)
+{
+	struct fw_unit *unit = fw_unit(dev);
+	int card_index;
+	struct snd_card *card;
+	struct snd_efw *efw;
+	int err;
+
+	mutex_lock(&devices_mutex);
+
+	/* check device name */
+	if (!match_fireworks_device_name(unit))
+		return -ENODEV;
+
+	/* check registered cards */
+	for (card_index = 0; card_index < SNDRV_CARDS; ++card_index)
+		if (!(devices_used & (1 << card_index)) && enable[card_index])
+			break;
+	if (card_index >= SNDRV_CARDS) {
+		err = -ENOENT;
+		goto end;
+	}
+
+	/* create card */
+	err = snd_card_create(index[card_index], id[card_index],
+				THIS_MODULE, sizeof(struct snd_efw), &card);
+	if (err < 0)
+		goto end;
+	card->private_free = snd_efw_card_free;
+
+	/* initialize myself */
+	efw = card->private_data;
+	efw->card = card;
+	efw->device = fw_parent_device(unit);
+	efw->unit = unit;
+	efw->card_index = -1;
+	mutex_init(&efw->mutex);
+	spin_lock_init(&efw->lock);
+
+	/* identifing */
+	err = snd_efw_command_identify(efw);
+	if (err < 0)
+		goto error;
+
+	/* get hardware information */
+	err = get_hardware_info(efw);
+	if (err < 0)
+		goto error;
+
+	/* get the number of hardware meters */
+	err = get_hardware_meters_count(efw);
+	if (err < 0)
+		goto error;
+
+	/* create procfs interface */
+	snd_efw_proc_init(efw);
+
+	/* create control interface */
+	err = snd_efw_create_control_devices(efw);
+	if (err < 0)
+		goto error;
+
+	/* create PCM interface */
+	err = snd_efw_create_pcm_devices(efw);
+	if (err < 0)
+		goto error;
+
+	/* create midi interface */
+	if (efw->midi_output_ports || efw->midi_input_ports) {
+		err = snd_efw_create_midi_devices(efw);
+		if (err < 0)
+			goto error;
+	}
+
+	/* register card and device */
+	snd_card_set_dev(card, dev);
+	err = snd_card_register(card);
+	if (err < 0)
+		goto error;
+	dev_set_drvdata(dev, card);
+	devices_used |= 1 << card_index;
+	efw->card_index = card_index;
+
+	/* proved */
+	err = 0;
+	goto end;
+
+error:
+	snd_card_free(card);
+
+end:
+	mutex_unlock(&devices_mutex);
+	return err;
+}
+
+static int
+snd_efw_remove(struct device *dev)
+{
+	struct snd_card *card = dev_get_drvdata(dev);
+	struct snd_efw *efw = card->private_data;
+
+	snd_efw_destroy_pcm_devices(efw);
+
+	snd_card_disconnect(card);
+	snd_card_free_when_closed(card);
+
+	return 0;
+}
+
+#define VENDOR_GIBSON			0x00075b
+#define  MODEL_GIBSON_RIP		0x00afb2
+/* #define  MODEL_GIBSON_GOLDTOP	0x?????? */
+
+#define VENDOR_LOUD			0x000ff2
+#define  MODEL_MACKIE_400F		0x00400f
+#define  MODEL_MACKIE_1200F		0x01200f
+
+#define VENDOR_ECHO_DIGITAL_AUDIO	0x001486
+#define  MODEL_ECHO_AUDIOFIRE_2		0x000af2
+#define  MODEL_ECHO_AUDIOFIRE_4		0x000af4
+#define  MODEL_ECHO_AUDIOFIRE_8		0x000af8
+/* #define  MODEL_ECHO_AUDIOFIRE_8A	0x?????? */
+/* #define  MODEL_ECHO_AUDIOFIRE_PRE8	0x?????? */
+#define  MODEL_ECHO_AUDIOFIRE_12	0x00af12
+#define  MODEL_ECHO_FIREWORKS_8		0x0000f8
+#define  MODEL_ECHO_FIREWORKS_HDMI	0x00afd1
+
+#define SPECIFIER_1394TA		0x00a02d
+
+static const struct ieee1394_device_id snd_efw_id_table[] = {
+	{
+		.match_flags = IEEE1394_MATCH_VENDOR_ID |
+			       IEEE1394_MATCH_SPECIFIER_ID,
+		.vendor_id = VENDOR_ECHO_DIGITAL_AUDIO,
+		.specifier_id = SPECIFIER_1394TA,
+	},
+	{
+		.match_flags = IEEE1394_MATCH_VENDOR_ID |
+			       IEEE1394_MATCH_SPECIFIER_ID,
+		.vendor_id = VENDOR_GIBSON,
+		.specifier_id = SPECIFIER_1394TA,
+	},
+	{
+		.match_flags = IEEE1394_MATCH_VENDOR_ID |
+			       IEEE1394_MATCH_MODEL_ID,
+		.vendor_id = VENDOR_LOUD,
+		.model_id = MODEL_MACKIE_400F,
+	},
+	{
+		.match_flags = IEEE1394_MATCH_VENDOR_ID |
+			       IEEE1394_MATCH_MODEL_ID,
+		.vendor_id = VENDOR_LOUD,
+		.model_id = MODEL_MACKIE_1200F,
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(ieee1394, snd_efw_id_table);
+
+static struct fw_driver snd_efw_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "snd-fireworks",
+		.bus = &fw_bus_type,
+		.probe = snd_efw_probe,
+		.remove = snd_efw_remove,
+	},
+	.update = snd_efw_update,
+	.id_table = snd_efw_id_table,
+};
+
+static int __init snd_efw_init(void)
+{
+	return driver_register(&snd_efw_driver.driver);
+}
+
+static void __exit snd_efw_exit(void)
+{
+	driver_unregister(&snd_efw_driver.driver);
+	mutex_destroy(&devices_mutex);
+}
+
+module_init(snd_efw_init);
+module_exit(snd_efw_exit);
diff --git a/sound/firewire/fireworks/fireworks.h b/sound/firewire/fireworks/fireworks.h
new file mode 100644
index 0000000..ce117b4
--- /dev/null
+++ b/sound/firewire/fireworks/fireworks.h
@@ -0,0 +1,241 @@
+/*
+ * fireworks.h - driver for Firewire devices from Echo Digital Audio
+ *
+ * Copyright (c) 2009-2010 Clemens Ladisch
+ * Copyright (c) 2013 Takashi Sakamoto
+ *
+ *
+ * This driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2.
+ *
+ * This driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this driver; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * mostly based on FFADO's efc_cmd.h, which is
+ * Copyright (C) 2005-2008 by Pieter Palmers
+ *
+ */
+#ifndef SOUND_FIREWORKS_H_INCLUDED
+#define SOUND_FIREWORKS_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/delay.h>
+#include <linux/slab.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/control.h>
+#include <sound/rawmidi.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/info.h>
+#include <sound/tlv.h>
+
+#include "../packets-buffer.h"
+#include "../iso-resources.h"
+#include "../amdtp.h"
+#include "../cmp.h"
+#include "../fcp.h"
+
+#define MAX_MIDI_OUTPUTS 2
+#define MAX_MIDI_INPUTS 2
+
+#define SND_EFW_MUITIPLIER_MODES 3
+#define HWINFO_NAME_SIZE_BYTES 32
+#define HWINFO_MAX_CAPS_GROUPS 8
+
+/* for physical metering */
+enum snd_efw_channel_type {
+	SND_EFW_CHANNEL_TYPE_ANALOG		= 0,
+	SND_EFW_CHANNEL_TYPE_SPDIF		= 1,
+	SND_EFW_CHANNEL_TYPE_ADAT		= 2,
+	SND_EFW_CHANNEL_TYPE_SPDIF_OR_ADAT	= 3,
+	SND_EFW_CHANNEL_TYPE_ANALOG_MIRRORING	= 4,
+	SND_EFW_CHANNEL_TYPE_HEADPHONES		= 5,
+	SND_EFW_CHANNEL_TYPE_I2S		= 6
+};
+struct snd_efw_phys_group {
+	u8 type;	/* enum snd_efw_channel_type */
+	u8 count;
+} __packed;
+
+struct snd_efw {
+	struct snd_card *card;
+	struct fw_device *device;
+	struct fw_unit *unit;
+	int card_index;
+
+	struct mutex mutex;
+	spinlock_t lock;
+
+	/* for EFC */
+	u32 sequence_number;
+
+	/* capabilities */
+	unsigned int supported_sampling_rate;
+	unsigned int supported_clock_source;
+	unsigned int supported_digital_interface;
+	unsigned int has_phantom;
+	unsigned int has_dsp_mixer;
+	unsigned int has_fpga;
+	unsigned int aes_ebu_xlr_support;
+	unsigned int mirroring_support;
+	unsigned int dynaddr_support;
+
+	/* physical metering */
+	unsigned int input_group_counts;
+	struct snd_efw_phys_group *input_groups;
+	unsigned int output_group_counts;
+	struct snd_efw_phys_group *output_groups;
+
+	/* meter parameters */
+	unsigned int input_meter_counts;
+	unsigned int output_meter_counts;
+
+	/* mixer parameters */
+	unsigned int mixer_input_channels;
+	unsigned int mixer_output_channels;
+
+	/* MIDI parameters */
+	unsigned int midi_input_ports;
+	unsigned int midi_output_ports;
+
+	/* PCM parameters */
+	unsigned int pcm_capture_channels[SND_EFW_MUITIPLIER_MODES];
+	unsigned int pcm_playback_channels[SND_EFW_MUITIPLIER_MODES];
+
+	/* notification to control components */
+	struct snd_ctl_elem_id *control_id_sampling_rate;
+
+	/* for IEC 61883-1 and -6 streaming */
+	struct amdtp_stream receive_stream;
+	struct amdtp_stream transmit_stream;
+	/* Fireworks has only two plugs */
+	struct cmp_connection output_connection;
+	struct cmp_connection input_connection;
+};
+
+struct snd_efw_hwinfo {
+	u32 flags;
+	u32 guid_hi;
+	u32 guid_lo;
+	u32 type;
+	u32 version;
+	char vendor_name[HWINFO_NAME_SIZE_BYTES];
+	char model_name[HWINFO_NAME_SIZE_BYTES];
+	u32 supported_clocks;
+	u32 nb_1394_playback_channels;
+	u32 nb_1394_capture_channels;
+	u32 nb_phys_audio_out;
+	u32 nb_phys_audio_in;
+	u32 nb_out_groups;
+	struct snd_efw_phys_group out_groups[HWINFO_MAX_CAPS_GROUPS];
+	u32 nb_in_groups;
+	struct snd_efw_phys_group in_groups[HWINFO_MAX_CAPS_GROUPS];
+	u32 nb_midi_out;
+	u32 nb_midi_in;
+	u32 max_sample_rate;
+	u32 min_sample_rate;
+	u32 dsp_version;
+	u32 arm_version;
+	u32 mixer_playback_channels;
+	u32 mixer_capture_channels;
+	u32 fpga_version;
+	u32 nb_1394_playback_channels_2x;
+	u32 nb_1394_capture_channels_2x;
+	u32 nb_1394_playback_channels_4x;
+	u32 nb_1394_capture_channels_4x;
+	u32 reserved[16];
+} __packed;
+
+/* for hardware metering */
+struct snd_efw_phys_meters {
+	u32 status;
+	u32 detect_spdif;
+	u32 detect_adat;
+	u32 reserved0;
+	u32 reserved1;
+	u32 nb_output_meters;
+	u32 nb_input_meters;
+	u32 reserved2;
+	u32 reserved3;
+	u32 values[0];
+} __packed;
+
+/* clock source parameters */
+enum snd_efw_clock_source {
+	SND_EFW_CLOCK_SOURCE_INTERNAL	= 0,
+	SND_EFW_CLOCK_SOURCE_SYTMATCH	= 1,
+	SND_EFW_CLOCK_SOURCE_WORDCLOCK	= 2,
+	SND_EFW_CLOCK_SOURCE_SPDIF	= 3,
+	SND_EFW_CLOCK_SOURCE_ADAT_1	= 4,
+	SND_EFW_CLOCK_SOURCE_ADAT_2	= 5,
+};
+
+/* digital interface parameters */
+enum snd_efw_digital_interface {
+	SND_EFW_DIGITAL_INTERFACE_SPDIF_COAXIAL	= 0,
+	SND_EFW_DIGITAL_INTERFACE_ADAT_COAXIAL	= 1,
+	SND_EFW_DIGITAL_INTERFACE_SPDIF_OPTICAL	= 2,
+	SND_EFW_DIGITAL_INTERFACE_ADAT_OPTICAL	= 3
+};
+
+/* S/PDIF format parameters */
+enum snd_efw_iec60958_format {
+	SND_EFW_IEC60958_FORMAT_CONSUMER	= 0,
+	SND_EFW_IEC60958_FORMAT_PROFESSIONAL	= 1
+};
+
+/* Echo Fireworks Command functions */
+int snd_efw_command_identify(struct snd_efw *efw);
+int snd_efw_command_get_hwinfo(struct snd_efw *efw,
+			       struct snd_efw_hwinfo *hwinfo);
+int snd_efw_command_get_phys_meters(struct snd_efw *efw,
+				    struct snd_efw_phys_meters *meters,
+				    int len);
+int snd_efw_command_get_clock_source(struct snd_efw *efw,
+				     enum snd_efw_clock_source *source);
+int snd_efw_command_set_clock_source(struct snd_efw *efw,
+				     enum snd_efw_clock_source source);
+int snd_efw_command_get_sampling_rate(struct snd_efw *efw, int *sampling_rate);
+int snd_efw_command_set_sampling_rate(struct snd_efw *efw, int sampling_rate);
+int snd_efw_command_get_iec60958_format(struct snd_efw *efw,
+					enum snd_efw_iec60958_format *format);
+int snd_efw_command_set_iec60958_format(struct snd_efw *efw,
+					enum snd_efw_iec60958_format format);
+int snd_efw_command_get_digital_interface(struct snd_efw *efw,
+			enum snd_efw_digital_interface *digital_interface);
+int snd_efw_command_set_digital_interface(struct snd_efw *efw,
+			enum snd_efw_digital_interface digital_interface);
+
+/* for AMDTP stream and CMP */
+int snd_efw_stream_init(struct snd_efw *efw, struct amdtp_stream *stream);
+int snd_efw_stream_start(struct snd_efw *efw, struct amdtp_stream *stream);
+void snd_efw_stream_stop(struct snd_efw *efw, struct amdtp_stream *stream);
+void snd_efw_stream_destroy(struct snd_efw *efw, struct amdtp_stream *stream);
+
+/* for procfs subsystem */
+void snd_efw_proc_init(struct snd_efw *efw);
+
+/* for control component */
+int snd_efw_create_control_devices(struct snd_efw *efw);
+
+/* for midi component */
+int snd_efw_create_midi_devices(struct snd_efw *ef);
+
+/* for pcm component */
+int snd_efw_create_pcm_devices(struct snd_efw *efw);
+void snd_efw_destroy_pcm_devices(struct snd_efw *efw);
+int snd_efw_get_multiplier_mode(int sampling_rate);
+
+
+#endif
-- 
1.7.10.4



More information about the Alsa-devel mailing list