Alsa-Devel Archive on lore.kernel.org
 help / color / Atom feed
From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
To: clemens@ladisch.de, tiwai@suse.de, perex@perex.cz
Cc: alsa-devel@alsa-project.org, ffado-devel@lists.sf.net
Subject: [PATCH 31/39] bebob: Add PCM interface
Date: Fri, 28 Feb 2014 12:27:44 +0900
Message-ID: <1393558072-25926-32-git-send-email-o-takashi@sakamocchi.jp> (raw)
In-Reply-To: <1393558072-25926-1-git-send-email-o-takashi@sakamocchi.jp>

This commit adds a functionality to capture/playback PCM samples.

When AMDTP stream is already running for PCM or the source of clock is not
internal, available sampling rate is limited at current one.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 sound/firewire/Kconfig           |   1 +
 sound/firewire/bebob/Makefile    |   1 +
 sound/firewire/bebob/bebob.c     |   4 +
 sound/firewire/bebob/bebob.h     |   4 +
 sound/firewire/bebob/bebob_pcm.c | 442 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 452 insertions(+)
 create mode 100644 sound/firewire/bebob/bebob_pcm.c

diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig
index 8081ca1..022fee0 100644
--- a/sound/firewire/Kconfig
+++ b/sound/firewire/Kconfig
@@ -83,6 +83,7 @@ config SND_BEBOB
 	tristate "BridgeCo DM1000/1500 with BeBoB firmware"
 	select SND_FIREWIRE_LIB
 	select SND_RAWMIDI
+	select SND_PCM
         help
 	 Say Y here to include support for FireWire devices based
 	 on BridgeCo DM1000/1500 with BeBoB firmware:
diff --git a/sound/firewire/bebob/Makefile b/sound/firewire/bebob/Makefile
index 1e39e59..533718a 100644
--- a/sound/firewire/bebob/Makefile
+++ b/sound/firewire/bebob/Makefile
@@ -1,3 +1,4 @@
 snd-bebob-objs := bebob_command.o bebob_stream.o bebob_proc.o bebob_midi.o \
+		  bebob_pcm.o \
 		  bebob.o
 obj-m += snd-bebob.o
diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c
index dbfbe89..777ccfc 100644
--- a/sound/firewire/bebob/bebob.c
+++ b/sound/firewire/bebob/bebob.c
@@ -174,6 +174,10 @@ bebob_probe(struct fw_unit *unit,
 			goto error;
 	}
 
+	err = snd_bebob_create_pcm_devices(bebob);
+	if (err < 0)
+		goto error;
+
 	err = snd_card_register(card);
 	if (err < 0) {
 		snd_card_free(card);
diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h
index 1e1db6c..b310c85 100644
--- a/sound/firewire/bebob/bebob.h
+++ b/sound/firewire/bebob/bebob.h
@@ -22,6 +22,8 @@
 #include <sound/initval.h>
 #include <sound/info.h>
 #include <sound/rawmidi.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
 
 #include "../lib.h"
 #include "../fcp.h"
@@ -181,6 +183,8 @@ void snd_bebob_proc_init(struct snd_bebob *bebob);
 
 int snd_bebob_create_midi_devices(struct snd_bebob *bebob);
 
+int snd_bebob_create_pcm_devices(struct snd_bebob *bebob);
+
 #define SND_BEBOB_DEV_ENTRY(vendor, model) \
 { \
 	.match_flags	= IEEE1394_MATCH_VENDOR_ID | \
diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c
new file mode 100644
index 0000000..db9c87f
--- /dev/null
+++ b/sound/firewire/bebob/bebob_pcm.c
@@ -0,0 +1,442 @@
+/*
+ * bebob_pcm.c - a part of driver for BeBoB based devices
+ *
+ * Copyright (c) 2013 Takashi Sakamoto
+ *
+ * Licensed under the terms of the GNU General Public License, version 2.
+ */
+
+#include "./bebob.h"
+
+static int
+hw_rule_rate(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule,
+	     struct snd_bebob *bebob,
+	     struct snd_bebob_stream_formation *formations)
+{
+	struct snd_interval *r =
+		hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+	const struct snd_interval *c =
+		hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+	struct snd_interval t = {
+		.min = UINT_MAX, .max = 0, .integer = 1
+	};
+	unsigned int i;
+
+	for (i = 0; i < SND_BEBOB_STRM_FMT_ENTRIES; i++) {
+		/* entry is invalid */
+		if (formations[i].pcm == 0)
+			continue;
+
+		if (!snd_interval_test(c, formations[i].pcm))
+			continue;
+
+		t.min = min(t.min, snd_bebob_rate_table[i]);
+		t.max = max(t.max, snd_bebob_rate_table[i]);
+
+	}
+	return snd_interval_refine(r, &t);
+}
+
+static int
+hw_rule_channels(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule,
+		 struct snd_bebob *bebob,
+		 struct snd_bebob_stream_formation *formations)
+{
+	struct snd_interval *c =
+		hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+	const struct snd_interval *r =
+		hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
+	struct snd_interval t = {
+		.min = UINT_MAX, .max = 0, .integer = 1
+	};
+
+	unsigned int i;
+
+	for (i = 0; i < SND_BEBOB_STRM_FMT_ENTRIES; i++) {
+		/* entry is invalid */
+		if (formations[i].pcm == 0)
+			continue;
+
+		if (!snd_interval_test(r, snd_bebob_rate_table[i]))
+			continue;
+
+		t.min = min(t.min, formations[i].pcm);
+		t.max = max(t.max, formations[i].pcm);
+	}
+
+	return snd_interval_refine(c, &t);
+}
+
+static inline int
+hw_rule_capture_rate(struct snd_pcm_hw_params *params,
+				struct snd_pcm_hw_rule *rule)
+{
+	struct snd_bebob *bebob = rule->private;
+	return hw_rule_rate(params, rule, bebob,
+				bebob->tx_stream_formations);
+}
+
+static inline int
+hw_rule_playback_rate(struct snd_pcm_hw_params *params,
+				struct snd_pcm_hw_rule *rule)
+{
+	struct snd_bebob *bebob = rule->private;
+	return hw_rule_rate(params, rule, bebob,
+				bebob->rx_stream_formations);
+}
+
+static inline int
+hw_rule_capture_channels(struct snd_pcm_hw_params *params,
+				struct snd_pcm_hw_rule *rule)
+{
+	struct snd_bebob *bebob = rule->private;
+	return hw_rule_channels(params, rule, bebob,
+				bebob->tx_stream_formations);
+}
+
+static inline int
+hw_rule_playback_channels(struct snd_pcm_hw_params *params,
+				struct snd_pcm_hw_rule *rule)
+{
+	struct snd_bebob *bebob = rule->private;
+	return hw_rule_channels(params, rule, bebob,
+				bebob->rx_stream_formations);
+}
+
+static void
+prepare_channels(struct snd_pcm_hardware *hw,
+	  struct snd_bebob_stream_formation *formations)
+{
+	unsigned int i;
+
+	for (i = 0; i < SND_BEBOB_STRM_FMT_ENTRIES; i++) {
+		/* entry has no PCM channels */
+		if (formations[i].pcm == 0)
+			continue;
+
+		hw->channels_min = min(hw->channels_min, formations[i].pcm);
+		hw->channels_max = max(hw->channels_max, formations[i].pcm);
+	}
+}
+
+static void
+prepare_rates(struct snd_pcm_hardware *hw,
+	  struct snd_bebob_stream_formation *formations)
+{
+	unsigned int i;
+
+	for (i = 0; i < SND_BEBOB_STRM_FMT_ENTRIES; i++) {
+		/* entry has no PCM channels */
+		if (formations[i].pcm == 0)
+			continue;
+
+		hw->rate_min = min(hw->rate_min, snd_bebob_rate_table[i]);
+		hw->rate_max = max(hw->rate_max, snd_bebob_rate_table[i]);
+		hw->rates |= snd_pcm_rate_to_rate_bit(snd_bebob_rate_table[i]);
+	}
+}
+
+static int
+pcm_init_hw_params(struct snd_bebob *bebob,
+			struct snd_pcm_substream *substream)
+{
+	int err;
+
+	static const struct snd_pcm_hardware hw = {
+		.info = SNDRV_PCM_INFO_BATCH |
+			SNDRV_PCM_INFO_BLOCK_TRANSFER |
+			SNDRV_PCM_INFO_INTERLEAVED |
+			SNDRV_PCM_INFO_JOINT_DUPLEX |
+			SNDRV_PCM_INFO_MMAP |
+			SNDRV_PCM_INFO_MMAP_VALID,
+		/* set up later */
+		.rates = 0,
+		.rate_min = UINT_MAX,
+		.rate_max = 0,
+		/* set up later */
+		.channels_min = UINT_MAX,
+		.channels_max = 0,
+		.buffer_bytes_max = 4 * 16 * 2048 * 2,
+		.period_bytes_min = 1,
+		.period_bytes_max = 4 * 16 * 2048,
+		.periods_min = 2,
+		.periods_max = UINT_MAX,
+	};
+
+	substream->runtime->hw = hw;
+
+	/* add rule between channels and sampling rate */
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		prepare_rates(&substream->runtime->hw,
+			      bebob->tx_stream_formations);
+		prepare_channels(&substream->runtime->hw,
+				 bebob->tx_stream_formations);
+		substream->runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
+		snd_pcm_hw_rule_add(substream->runtime, 0,
+				    SNDRV_PCM_HW_PARAM_CHANNELS,
+				    hw_rule_capture_channels, bebob,
+				    SNDRV_PCM_HW_PARAM_RATE, -1);
+		snd_pcm_hw_rule_add(substream->runtime, 0,
+				    SNDRV_PCM_HW_PARAM_RATE,
+				    hw_rule_capture_rate, bebob,
+				    SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+	} else {
+		prepare_rates(&substream->runtime->hw,
+			      bebob->rx_stream_formations);
+		prepare_channels(&substream->runtime->hw,
+				 bebob->rx_stream_formations);
+		substream->runtime->hw.formats = AMDTP_OUT_PCM_FORMAT_BITS;
+		snd_pcm_hw_rule_add(substream->runtime, 0,
+				    SNDRV_PCM_HW_PARAM_CHANNELS,
+				    hw_rule_playback_channels, bebob,
+				    SNDRV_PCM_HW_PARAM_RATE, -1);
+		snd_pcm_hw_rule_add(substream->runtime, 0,
+				    SNDRV_PCM_HW_PARAM_RATE,
+				    hw_rule_playback_rate, bebob,
+				    SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+	}
+
+	/* AM824 in IEC 61883-6 can deliver 24bit data */
+	err = snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24);
+	if (err < 0)
+		goto end;
+
+	/*
+	 * AMDTP functionality in firewire-lib require periods to be aligned to
+	 * 16 bit, or 24bit inner 32bit.
+	 */
+	err = snd_pcm_hw_constraint_step(substream->runtime, 0,
+					 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
+	if (err < 0)
+		goto end;
+	err = snd_pcm_hw_constraint_step(substream->runtime, 0,
+					 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
+	if (err < 0)
+		goto end;
+
+	/*
+	 * Currently INTERRUPT_INTERVAL in amdtp.c is 16.
+	 * So snd_pcm_period_elapsed() can be called every 2m sec.
+	 */
+	err = snd_pcm_hw_constraint_minmax(substream->runtime,
+					   SNDRV_PCM_HW_PARAM_PERIOD_TIME,
+					   2000, UINT_MAX);
+end:
+	return err;
+}
+
+static int
+pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_bebob *bebob = substream->private_data;
+	unsigned int sampling_rate;
+	bool internal;
+	int err;
+
+	err = pcm_init_hw_params(bebob, substream);
+	if (err < 0)
+		goto end;
+
+	err = snd_bebob_stream_check_internal_clock(bebob, &internal);
+	if (err < 0)
+		goto end;
+
+	/*
+	 * When source of clock is internal or any PCM stream are running,
+	 * the available sampling rate is limited at current sampling rate.
+	 */
+	if (!internal ||
+	    amdtp_stream_pcm_running(&bebob->tx_stream) ||
+	    amdtp_stream_pcm_running(&bebob->rx_stream)) {
+		err = snd_bebob_stream_get_rate(bebob, &sampling_rate);
+		if (err < 0)
+			goto end;
+
+		substream->runtime->hw.rate_min = sampling_rate;
+		substream->runtime->hw.rate_max = sampling_rate;
+	}
+
+	snd_pcm_set_sync(substream);
+
+end:
+	return err;
+}
+
+static int
+pcm_close(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+static int
+pcm_capture_hw_params(struct snd_pcm_substream *substream,
+		      struct snd_pcm_hw_params *hw_params)
+{
+	struct snd_bebob *bebob = substream->private_data;
+
+	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
+		bebob->capture_substreams++;
+	amdtp_stream_set_pcm_format(&bebob->tx_stream,
+				    params_format(hw_params));
+	return snd_pcm_lib_alloc_vmalloc_buffer(substream,
+						params_buffer_bytes(hw_params));
+}
+static int
+pcm_playback_hw_params(struct snd_pcm_substream *substream,
+		       struct snd_pcm_hw_params *hw_params)
+{
+	struct snd_bebob *bebob = substream->private_data;
+
+	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
+		bebob->playback_substreams++;
+	amdtp_stream_set_pcm_format(&bebob->rx_stream,
+				    params_format(hw_params));
+	return snd_pcm_lib_alloc_vmalloc_buffer(substream,
+						params_buffer_bytes(hw_params));
+}
+
+static int
+pcm_capture_hw_free(struct snd_pcm_substream *substream)
+{
+	struct snd_bebob *bebob = substream->private_data;
+
+	if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
+		bebob->capture_substreams--;
+
+	snd_bebob_stream_stop_duplex(bebob);
+
+	return snd_pcm_lib_free_vmalloc_buffer(substream);
+}
+static int
+pcm_playback_hw_free(struct snd_pcm_substream *substream)
+{
+	struct snd_bebob *bebob = substream->private_data;
+
+	if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
+		bebob->playback_substreams--;
+
+	snd_bebob_stream_stop_duplex(bebob);
+
+	return snd_pcm_lib_free_vmalloc_buffer(substream);
+}
+
+static int
+pcm_capture_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_bebob *bebob = substream->private_data;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int err;
+
+	err = snd_bebob_stream_start_duplex(bebob, &bebob->tx_stream,
+					    runtime->rate);
+	if (err >= 0)
+		amdtp_stream_pcm_prepare(&bebob->tx_stream);
+
+	return err;
+}
+static int
+pcm_playback_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_bebob *bebob = substream->private_data;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int err;
+
+	err = snd_bebob_stream_start_duplex(bebob, &bebob->rx_stream,
+					    runtime->rate);
+	if (err >= 0)
+		amdtp_stream_pcm_prepare(&bebob->rx_stream);
+
+	return err;
+}
+
+static int
+pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_bebob *bebob = substream->private_data;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		amdtp_stream_pcm_trigger(&bebob->tx_stream, substream);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		amdtp_stream_pcm_trigger(&bebob->tx_stream, NULL);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+static int
+pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_bebob *bebob = substream->private_data;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		amdtp_stream_pcm_trigger(&bebob->rx_stream, substream);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		amdtp_stream_pcm_trigger(&bebob->rx_stream, NULL);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static snd_pcm_uframes_t
+pcm_capture_pointer(struct snd_pcm_substream *sbstrm)
+{
+	struct snd_bebob *bebob = sbstrm->private_data;
+	return amdtp_stream_pcm_pointer(&bebob->tx_stream);
+}
+static snd_pcm_uframes_t
+pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
+{
+	struct snd_bebob *bebob = sbstrm->private_data;
+	return amdtp_stream_pcm_pointer(&bebob->rx_stream);
+}
+
+static const struct snd_pcm_ops pcm_capture_ops = {
+	.open		= pcm_open,
+	.close		= pcm_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= pcm_capture_hw_params,
+	.hw_free	= pcm_capture_hw_free,
+	.prepare	= pcm_capture_prepare,
+	.trigger	= pcm_capture_trigger,
+	.pointer	= pcm_capture_pointer,
+	.page		= snd_pcm_lib_get_vmalloc_page,
+};
+static const struct snd_pcm_ops pcm_playback_ops = {
+	.open		= pcm_open,
+	.close		= pcm_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= pcm_playback_hw_params,
+	.hw_free	= pcm_playback_hw_free,
+	.prepare	= pcm_playback_prepare,
+	.trigger	= pcm_playback_trigger,
+	.pointer	= pcm_playback_pointer,
+	.page		= snd_pcm_lib_get_vmalloc_page,
+	.mmap		= snd_pcm_lib_mmap_vmalloc,
+};
+
+int snd_bebob_create_pcm_devices(struct snd_bebob *bebob)
+{
+	struct snd_pcm *pcm;
+	int err;
+
+	err = snd_pcm_new(bebob->card, bebob->card->driver, 0, 1, 1, &pcm);
+	if (err < 0)
+		goto end;
+
+	pcm->private_data = bebob;
+	snprintf(pcm->name, sizeof(pcm->name),
+		 "%s PCM", bebob->card->shortname);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_playback_ops);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops);
+end:
+	return err;
+}
-- 
1.8.3.2

  parent reply index

Thread overview: 69+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-02-28  3:27 [GIT PULL][PATCH 00/39] Enhancement of support for Firewire devices Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 01/39] firewire-lib: Rename functions, structure, member for AMDTP Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 02/39] firewire-lib: Add macros instead of fixed value " Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 03/39] firewire-lib: Add 'direction' member to 'amdtp_stream' structure Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 04/39] firewire-lib: Split some codes into functions to reuse for both streams Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 05/39] firewire-lib: Add support for AMDTP in-stream and PCM capture Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 06/39] firewire-lib: Add support for MIDI capture/playback Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 07/39] firewire-lib: Give syt value as parameter to handle_out_packet() Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 08/39] firewire-lib: Add support for duplex streams synchronization in blocking mode Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 09/39] firewire-lib: Add sort function for transmitted packet Takashi Sakamoto
2014-02-28  6:40   ` Takashi Iwai
2014-02-28 14:31     ` Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 10/39] firewire-lib: Add transfer delay to synchronized duplex streams Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 11/39] firewire-lib: Add support for channel mapping Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 12/39] firewire-lib: Rename macros, variables and functions for CMP Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 13/39] firewire-lib: Add 'direction' member to 'cmp_connection' structure Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 14/39] firewire-lib: Add handling output connection by CMP Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 15/39] firewire-lib: Add a new function to check others' connection Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 16/39] firewire-lib: Add some AV/C general commands Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 17/39] firewire-lib: Add quirks for Fireworks Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 18/39] firewire-lib: Add a fallback at RCODE_CANCELLED Takashi Sakamoto
2014-02-28 20:25   ` Stefan Richter
2014-02-28 20:39     ` Stefan Richter
2014-03-01  3:18     ` Takashi Sakamoto
2014-03-01 10:10       ` Stefan Richter
2014-03-01 12:22         ` Takashi Sakamoto
2014-03-01 14:20           ` Stefan Richter
2014-03-04  1:35             ` [FFADO-devel] " Jonathan Woithe
2014-03-04  8:33               ` Stefan Richter
2014-03-04  9:28                 ` Stefan Richter
2014-03-01 10:34   ` Stefan Richter
2014-03-01 12:23     ` Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 19/39] fireworks: Add skelton for Fireworks based devices Takashi Sakamoto
2014-02-28  6:51   ` Takashi Iwai
2014-02-28 15:05     ` Takashi Sakamoto
2014-02-28 15:10       ` Takashi Iwai
2014-02-28 15:36         ` Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 20/39] fireworks: Add transaction and some commands Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 21/39] fireworks: Add connection and stream management Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 22/39] fireworks: Add proc interface for debugging purpose Takashi Sakamoto
2014-02-28  6:54   ` Takashi Iwai
2014-03-01 13:17     ` Takashi Sakamoto
2014-03-03  9:01       ` Takashi Iwai
2014-03-04 14:10         ` Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 23/39] fireworks: Add MIDI interface Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 24/39] fireworks: Add PCM interface Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 25/39] fireworks: Add hwdep interface Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 26/39] fireworks: Add command/response functionality into " Takashi Sakamoto
2014-02-28  6:58   ` Takashi Iwai
2014-03-01 13:18     ` Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 27/39] bebob: Add skelton for BeBoB based devices Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 28/39] bebob: Add commands and connections/streams management Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 29/39] bebob: Add proc interface for debugging purpose Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 30/39] bebob: Add MIDI interface Takashi Sakamoto
2014-02-28  3:27 ` Takashi Sakamoto [this message]
2014-02-28  3:27 ` [PATCH 32/39] bebob: Add hwdep interface Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 33/39] bebob: Prepare for device specific operations Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 34/39] bebob: Add support for Terratec PHASE, EWS series and Aureon Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 35/39] bebob: Add support for Yamaha GO series Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 36/39] bebob: Add support for Focusrite Saffire/SaffirePro series Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 37/39] bebob: Add support for M-Audio usual Firewire series Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 38/39] bebob: Send a cue to load firmware for M-Audio " Takashi Sakamoto
2014-02-28  3:27 ` [PATCH 39/39] bebob: Add support for M-Audio special " Takashi Sakamoto
2014-03-01 10:53   ` Stefan Richter
2014-03-01 13:06     ` Takashi Sakamoto
2014-03-01 14:32       ` Stefan Richter
2014-02-28  6:36 ` [GIT PULL][PATCH 00/39] Enhancement of support for Firewire devices Takashi Iwai
2014-03-01 13:14   ` Takashi Sakamoto
     [not found] <5316963F.1000206@sakamocchi.jp>
2014-03-05 10:47 ` [GIT PULL][PATCH 00/39 v2] " Takashi Sakamoto
2014-03-05 10:48   ` [PATCH 31/39] bebob: Add PCM interface Takashi Sakamoto

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1393558072-25926-32-git-send-email-o-takashi@sakamocchi.jp \
    --to=o-takashi@sakamocchi.jp \
    --cc=alsa-devel@alsa-project.org \
    --cc=clemens@ladisch.de \
    --cc=ffado-devel@lists.sf.net \
    --cc=perex@perex.cz \
    --cc=tiwai@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Alsa-Devel Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/alsa-devel/0 alsa-devel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 alsa-devel alsa-devel/ https://lore.kernel.org/alsa-devel \
		alsa-devel@alsa-project.org
	public-inbox-index alsa-devel

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.alsa-project.alsa-devel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git