All of lore.kernel.org
 help / color / mirror / Atom feed
From: Oleksandr Andrushchenko <andr2000@gmail.com>
To: alsa-devel@alsa-project.org, xen-devel@lists.xen.org,
	linux-kernel@vger.kernel.org
Cc: perex@perex.cz, tiwai@suse.com, andr2000@gmail.com,
	Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
Subject: [PATCH RESEND 03/11] ALSA: vsnd: Read sound driver configuration from Xen store
Date: Mon,  7 Aug 2017 14:50:37 +0300	[thread overview]
Message-ID: <1502106645-6731-4-git-send-email-andr2000@gmail.com> (raw)
In-Reply-To: <1502106645-6731-1-git-send-email-andr2000@gmail.com>

From: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>

Read configuration values from Xen store according
to xen/interface/io/sndif.h protocol:
- introduce configuration structures for different
  components, e.g. sound card, device, stream
- read PCM HW parameters, e.g rate, format etc.
- detect stream type (capture/playback)
- read device and card parameters

Fill in platform data with the configuration read, so
it can be passed to sound driver later.

Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
---
 sound/drivers/xen-front.c | 530 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 530 insertions(+)

diff --git a/sound/drivers/xen-front.c b/sound/drivers/xen-front.c
index c4fd21cac3a7..ef48cbf44cf2 100644
--- a/sound/drivers/xen-front.c
+++ b/sound/drivers/xen-front.c
@@ -20,24 +20,554 @@
 
 #include <linux/module.h>
 
+#include <sound/core.h>
+#include <sound/pcm.h>
+
 #include <xen/platform_pci.h>
 #include <xen/xen.h>
 #include <xen/xenbus.h>
 
 #include <xen/interface/io/sndif.h>
 
+/* maximum number of supported streams */
+#define VSND_MAX_STREAM		8
+
+struct cfg_stream {
+	int unique_id;
+	char *xenstore_path;
+	struct snd_pcm_hardware pcm_hw;
+};
+
+struct cfg_pcm_instance {
+	char name[80];
+	int device_id;
+	struct snd_pcm_hardware pcm_hw;
+	int  num_streams_pb;
+	struct cfg_stream *streams_pb;
+	int  num_streams_cap;
+	struct cfg_stream *streams_cap;
+};
+
+struct cfg_card {
+	char name_short[32];
+	char name_long[80];
+	struct snd_pcm_hardware pcm_hw;
+	int num_pcm_instances;
+	struct cfg_pcm_instance *pcm_instances;
+};
+
+struct sdev_card_plat_data {
+	struct xdrv_info *xdrv_info;
+	struct cfg_card cfg_card;
+};
+
 struct xdrv_info {
 	struct xenbus_device *xb_dev;
 	spinlock_t io_lock;
 	struct mutex mutex;
+	struct sdev_card_plat_data cfg_plat_data;
 };
 
+#define MAX_XEN_BUFFER_SIZE	(64 * 1024)
+#define MAX_BUFFER_SIZE		MAX_XEN_BUFFER_SIZE
+#define MIN_PERIOD_SIZE		64
+#define MAX_PERIOD_SIZE		(MAX_BUFFER_SIZE / 8)
+#define USE_FORMATS		(SNDRV_PCM_FMTBIT_U8 | \
+				 SNDRV_PCM_FMTBIT_S16_LE)
+#define USE_RATE		(SNDRV_PCM_RATE_CONTINUOUS | \
+				 SNDRV_PCM_RATE_8000_48000)
+#define USE_RATE_MIN		5512
+#define USE_RATE_MAX		48000
+#define USE_CHANNELS_MIN	1
+#define USE_CHANNELS_MAX	2
+#define USE_PERIODS_MIN		2
+#define USE_PERIODS_MAX		8
+
+static struct snd_pcm_hardware sdrv_pcm_hw_default = {
+	.info = (SNDRV_PCM_INFO_MMAP |
+		 SNDRV_PCM_INFO_INTERLEAVED |
+		 SNDRV_PCM_INFO_RESUME |
+		 SNDRV_PCM_INFO_MMAP_VALID),
+	.formats = USE_FORMATS,
+	.rates = USE_RATE,
+	.rate_min = USE_RATE_MIN,
+	.rate_max = USE_RATE_MAX,
+	.channels_min = USE_CHANNELS_MIN,
+	.channels_max = USE_CHANNELS_MAX,
+	.buffer_bytes_max = MAX_BUFFER_SIZE,
+	.period_bytes_min = MIN_PERIOD_SIZE,
+	.period_bytes_max = MAX_PERIOD_SIZE,
+	.periods_min = USE_PERIODS_MIN,
+	.periods_max = USE_PERIODS_MAX,
+	.fifo_size = 0,
+};
+
+struct CFG_HW_SAMPLE_RATE {
+	const char *name;
+	unsigned int mask;
+	unsigned int value;
+};
+
+static struct CFG_HW_SAMPLE_RATE cfg_hw_supported_rates[] = {
+	{ .name = "5512",   .mask = SNDRV_PCM_RATE_5512,   .value = 5512 },
+	{ .name = "8000",   .mask = SNDRV_PCM_RATE_8000,   .value = 8000 },
+	{ .name = "11025",  .mask = SNDRV_PCM_RATE_11025,  .value = 11025 },
+	{ .name = "16000",  .mask = SNDRV_PCM_RATE_16000,  .value = 16000 },
+	{ .name = "22050",  .mask = SNDRV_PCM_RATE_22050,  .value = 22050 },
+	{ .name = "32000",  .mask = SNDRV_PCM_RATE_32000,  .value = 32000 },
+	{ .name = "44100",  .mask = SNDRV_PCM_RATE_44100,  .value = 44100 },
+	{ .name = "48000",  .mask = SNDRV_PCM_RATE_48000,  .value = 48000 },
+	{ .name = "64000",  .mask = SNDRV_PCM_RATE_64000,  .value = 64000 },
+	{ .name = "96000",  .mask = SNDRV_PCM_RATE_96000,  .value = 96000 },
+	{ .name = "176400", .mask = SNDRV_PCM_RATE_176400, .value = 176400 },
+	{ .name = "192000", .mask = SNDRV_PCM_RATE_192000, .value = 192000 },
+};
+
+struct CFG_HW_SAMPLE_FORMAT {
+	const char *name;
+	u64 mask;
+};
+
+static struct CFG_HW_SAMPLE_FORMAT cfg_hw_supported_formats[] = {
+	{
+		.name = XENSND_PCM_FORMAT_U8_STR,
+		.mask = SNDRV_PCM_FMTBIT_U8
+	},
+	{
+		.name = XENSND_PCM_FORMAT_S8_STR,
+		.mask = SNDRV_PCM_FMTBIT_S8
+	},
+	{
+		.name = XENSND_PCM_FORMAT_U16_LE_STR,
+		.mask = SNDRV_PCM_FMTBIT_U16_LE
+	},
+	{
+		.name = XENSND_PCM_FORMAT_U16_BE_STR,
+		.mask = SNDRV_PCM_FMTBIT_U16_BE
+	},
+	{
+		.name = XENSND_PCM_FORMAT_S16_LE_STR,
+		.mask = SNDRV_PCM_FMTBIT_S16_LE
+	},
+	{
+		.name = XENSND_PCM_FORMAT_S16_BE_STR,
+		.mask = SNDRV_PCM_FMTBIT_S16_BE
+	},
+	{
+		.name = XENSND_PCM_FORMAT_U24_LE_STR,
+		.mask = SNDRV_PCM_FMTBIT_U24_LE
+	},
+	{
+		.name = XENSND_PCM_FORMAT_U24_BE_STR,
+		.mask = SNDRV_PCM_FMTBIT_U24_BE
+	},
+	{
+		.name = XENSND_PCM_FORMAT_S24_LE_STR,
+		.mask = SNDRV_PCM_FMTBIT_S24_LE
+	},
+	{
+		.name = XENSND_PCM_FORMAT_S24_BE_STR,
+		.mask = SNDRV_PCM_FMTBIT_S24_BE
+	},
+	{
+		.name = XENSND_PCM_FORMAT_U32_LE_STR,
+		.mask = SNDRV_PCM_FMTBIT_U32_LE
+	},
+	{
+		.name = XENSND_PCM_FORMAT_U32_BE_STR,
+		.mask = SNDRV_PCM_FMTBIT_U32_BE
+	},
+	{
+		.name = XENSND_PCM_FORMAT_S32_LE_STR,
+		.mask = SNDRV_PCM_FMTBIT_S32_LE
+	},
+	{
+		.name = XENSND_PCM_FORMAT_S32_BE_STR,
+		.mask = SNDRV_PCM_FMTBIT_S32_BE
+	},
+	{
+		.name = XENSND_PCM_FORMAT_A_LAW_STR,
+		.mask = SNDRV_PCM_FMTBIT_A_LAW
+	},
+	{
+		.name = XENSND_PCM_FORMAT_MU_LAW_STR,
+		.mask = SNDRV_PCM_FMTBIT_MU_LAW
+	},
+	{
+		.name = XENSND_PCM_FORMAT_F32_LE_STR,
+		.mask = SNDRV_PCM_FMTBIT_FLOAT_LE
+	},
+	{
+		.name = XENSND_PCM_FORMAT_F32_BE_STR,
+		.mask = SNDRV_PCM_FMTBIT_FLOAT_BE
+	},
+	{
+		.name = XENSND_PCM_FORMAT_F64_LE_STR,
+		.mask = SNDRV_PCM_FMTBIT_FLOAT64_LE
+	},
+	{
+		.name = XENSND_PCM_FORMAT_F64_BE_STR,
+		.mask = SNDRV_PCM_FMTBIT_FLOAT64_BE
+	},
+	{
+		.name = XENSND_PCM_FORMAT_IEC958_SUBFRAME_LE_STR,
+		.mask = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE
+	},
+	{
+		.name = XENSND_PCM_FORMAT_IEC958_SUBFRAME_BE_STR,
+		.mask = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE
+	},
+	{
+		.name = XENSND_PCM_FORMAT_IMA_ADPCM_STR,
+		.mask = SNDRV_PCM_FMTBIT_IMA_ADPCM
+	},
+	{
+		.name = XENSND_PCM_FORMAT_MPEG_STR,
+		.mask = SNDRV_PCM_FMTBIT_MPEG
+	},
+	{
+		.name = XENSND_PCM_FORMAT_GSM_STR,
+		.mask = SNDRV_PCM_FMTBIT_GSM
+	},
+};
+
+static void cfg_hw_rates(char *list, unsigned int len,
+	const char *path, struct snd_pcm_hardware *pcm_hw)
+{
+	char *cur_rate;
+	unsigned int cur_mask;
+	unsigned int cur_value;
+	unsigned int rates;
+	unsigned int rate_min;
+	unsigned int rate_max;
+	int i;
+
+	rates = 0;
+	rate_min = -1;
+	rate_max = 0;
+	while ((cur_rate = strsep(&list, XENSND_LIST_SEPARATOR))) {
+		for (i = 0; i < ARRAY_SIZE(cfg_hw_supported_rates); i++)
+			if (!strncasecmp(cur_rate,
+					cfg_hw_supported_rates[i].name,
+					XENSND_SAMPLE_RATE_MAX_LEN)) {
+				cur_mask = cfg_hw_supported_rates[i].mask;
+				cur_value = cfg_hw_supported_rates[i].value;
+				rates |= cur_mask;
+				if (rate_min > cur_value)
+					rate_min = cur_value;
+				if (rate_max < cur_value)
+					rate_max = cur_value;
+			}
+	}
+
+	if (rates) {
+		pcm_hw->rates = rates;
+		pcm_hw->rate_min = rate_min;
+		pcm_hw->rate_max = rate_max;
+	}
+}
+
+static void cfg_formats(char *list, unsigned int len,
+	const char *path, struct snd_pcm_hardware *pcm_hw)
+{
+	u64 formats;
+	char *cur_format;
+	int i;
+
+	formats = 0;
+	while ((cur_format = strsep(&list, XENSND_LIST_SEPARATOR))) {
+		for (i = 0; i < ARRAY_SIZE(cfg_hw_supported_formats); i++)
+			if (!strncasecmp(cur_format,
+					cfg_hw_supported_formats[i].name,
+					XENSND_SAMPLE_FORMAT_MAX_LEN))
+				formats |= cfg_hw_supported_formats[i].mask;
+	}
+
+	if (formats)
+		pcm_hw->formats = formats;
+}
+
+static void cfg_pcm_hw(const char *path,
+	struct snd_pcm_hardware *parent_pcm_hw,
+	struct snd_pcm_hardware *pcm_hw)
+{
+	char *list;
+	int val;
+	size_t buf_sz;
+	unsigned int len;
+
+	/* inherit parent's PCM HW and read overrides if any */
+	*pcm_hw = *parent_pcm_hw;
+
+	val = xenbus_read_unsigned(path, XENSND_FIELD_CHANNELS_MIN, 0);
+	if (val)
+		pcm_hw->channels_min = val;
+
+	val = xenbus_read_unsigned(path, XENSND_FIELD_CHANNELS_MAX, 0);
+	if (val)
+		pcm_hw->channels_max = val;
+
+	list = xenbus_read(XBT_NIL, path, XENSND_FIELD_SAMPLE_RATES, &len);
+	if (!IS_ERR(list)) {
+		cfg_hw_rates(list, len, path, pcm_hw);
+		kfree(list);
+	}
+
+	list = xenbus_read(XBT_NIL, path, XENSND_FIELD_SAMPLE_FORMATS, &len);
+	if (!IS_ERR(list)) {
+		cfg_formats(list, len, path, pcm_hw);
+		kfree(list);
+	}
+
+	buf_sz = xenbus_read_unsigned(path, XENSND_FIELD_BUFFER_SIZE, 0);
+	if (buf_sz)
+		pcm_hw->buffer_bytes_max = buf_sz;
+}
+
+static int cfg_get_stream_type(const char *path, int index,
+	int *num_pb, int *num_cap)
+{
+	char *str = NULL;
+	char *stream_path;
+	int ret;
+
+	*num_pb = 0;
+	*num_cap = 0;
+	stream_path = kasprintf(GFP_KERNEL, "%s/%d", path, index);
+	if (!stream_path) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	str = xenbus_read(XBT_NIL, stream_path, XENSND_FIELD_TYPE, NULL);
+	if (IS_ERR(str)) {
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	if (!strncasecmp(str, XENSND_STREAM_TYPE_PLAYBACK,
+		sizeof(XENSND_STREAM_TYPE_PLAYBACK)))
+		(*num_pb)++;
+	else if (!strncasecmp(str, XENSND_STREAM_TYPE_CAPTURE,
+		sizeof(XENSND_STREAM_TYPE_CAPTURE)))
+		(*num_cap)++;
+	else {
+		ret = -EINVAL;
+		goto fail;
+	}
+	ret = 0;
+
+fail:
+	kfree(stream_path);
+	kfree(str);
+	return ret;
+}
+
+static int cfg_stream(struct xdrv_info *drv_info,
+	struct cfg_pcm_instance *pcm_instance,
+	const char *path, int index, int *cur_pb, int *cur_cap,
+	int *stream_idx)
+{
+	char *str = NULL;
+	char *stream_path;
+	struct cfg_stream *stream;
+	int ret;
+
+	stream_path = devm_kasprintf(&drv_info->xb_dev->dev,
+		GFP_KERNEL, "%s/%d", path, index);
+	if (!stream_path) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	str = xenbus_read(XBT_NIL, stream_path, XENSND_FIELD_TYPE, NULL);
+	if (IS_ERR(str)) {
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	if (!strncasecmp(str, XENSND_STREAM_TYPE_PLAYBACK,
+		sizeof(XENSND_STREAM_TYPE_PLAYBACK))) {
+		stream = &pcm_instance->streams_pb[(*cur_pb)++];
+	} else if (!strncasecmp(str, XENSND_STREAM_TYPE_CAPTURE,
+		sizeof(XENSND_STREAM_TYPE_CAPTURE))) {
+		stream = &pcm_instance->streams_cap[(*cur_cap)++];
+	} else {
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	/* get next stream index */
+	stream->unique_id = (*stream_idx)++;
+	stream->xenstore_path = stream_path;
+	/*
+	 * check in Xen store if PCM HW configuration exists for this stream
+	 * and update if so, e.g. we inherit all values from device's PCM HW,
+	 * but can still override some of the values for the stream
+	 */
+	cfg_pcm_hw(stream->xenstore_path,
+		&pcm_instance->pcm_hw, &stream->pcm_hw);
+	ret = 0;
+
+fail:
+	kfree(str);
+	return ret;
+}
+
+static int cfg_device(struct xdrv_info *drv_info,
+	struct cfg_pcm_instance *pcm_instance,
+	struct snd_pcm_hardware *parent_pcm_hw,
+	const char *path, int node_index, int *stream_idx)
+{
+	char *str;
+	char *device_path;
+	int ret, i, num_streams;
+	int num_pb, num_cap;
+	int cur_pb, cur_cap;
+	char node[3];
+
+	device_path = kasprintf(GFP_KERNEL, "%s/%d", path, node_index);
+	if (!device_path)
+		return -ENOMEM;
+
+	str = xenbus_read(XBT_NIL, device_path, XENSND_FIELD_DEVICE_NAME, NULL);
+	if (!IS_ERR(str)) {
+		strncpy(pcm_instance->name, str, sizeof(pcm_instance->name));
+		kfree(str);
+	}
+
+	pcm_instance->device_id = node_index;
+
+	/*
+	 * check in Xen store if PCM HW configuration exists for this device
+	 * and update if so, e.g. we inherit all values from card's PCM HW,
+	 * but can still override some of the values for the device
+	 */
+	cfg_pcm_hw(device_path, parent_pcm_hw, &pcm_instance->pcm_hw);
+
+	/*
+	 * find out how many streams were configured in Xen store:
+	 * streams must have sequential unique IDs, so stop when one
+	 * does not exist
+	 */
+	num_streams = 0;
+	do {
+		snprintf(node, sizeof(node), "%d", num_streams);
+		if (!xenbus_exists(XBT_NIL, device_path, node))
+			break;
+
+		num_streams++;
+	} while (num_streams < VSND_MAX_STREAM);
+
+	pcm_instance->num_streams_pb = 0;
+	pcm_instance->num_streams_cap = 0;
+	/* get number of playback and capture streams */
+	for (i = 0; i < num_streams; i++) {
+		ret = cfg_get_stream_type(device_path, i, &num_pb, &num_cap);
+		if (ret < 0)
+			goto fail;
+
+		pcm_instance->num_streams_pb += num_pb;
+		pcm_instance->num_streams_cap += num_cap;
+	}
+
+	if (pcm_instance->num_streams_pb) {
+		pcm_instance->streams_pb = devm_kcalloc(
+			&drv_info->xb_dev->dev,
+			pcm_instance->num_streams_pb,
+			sizeof(struct cfg_stream), GFP_KERNEL);
+		if (!pcm_instance->streams_pb) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+	}
+
+	if (pcm_instance->num_streams_cap) {
+		pcm_instance->streams_cap = devm_kcalloc(
+			&drv_info->xb_dev->dev,
+			pcm_instance->num_streams_cap,
+			sizeof(struct cfg_stream), GFP_KERNEL);
+		if (!pcm_instance->streams_cap) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+	}
+
+	cur_pb = 0;
+	cur_cap = 0;
+	for (i = 0; i < num_streams; i++) {
+		ret = cfg_stream(drv_info,
+			pcm_instance, device_path, i, &cur_pb, &cur_cap,
+			stream_idx);
+		if (ret < 0)
+			goto fail;
+	}
+	ret = 0;
+
+fail:
+	kfree(device_path);
+	return ret;
+}
+
+static int cfg_card(struct xdrv_info *drv_info,
+	struct sdev_card_plat_data *plat_data, int *stream_idx)
+{
+	struct xenbus_device *xb_dev = drv_info->xb_dev;
+	int ret, num_devices, i;
+	char node[3];
+
+	num_devices = 0;
+	do {
+		snprintf(node, sizeof(node), "%d", num_devices);
+		if (!xenbus_exists(XBT_NIL, xb_dev->nodename, node))
+			break;
+
+		num_devices++;
+	} while (num_devices < SNDRV_PCM_DEVICES);
+
+	if (!num_devices) {
+		dev_warn(&xb_dev->dev,
+			"No devices configured for sound card at %s\n",
+			xb_dev->nodename);
+		return -ENODEV;
+	}
+
+	/* start from default PCM HW configuration for the card */
+	cfg_pcm_hw(xb_dev->nodename, &sdrv_pcm_hw_default,
+		&plat_data->cfg_card.pcm_hw);
+
+	plat_data->cfg_card.pcm_instances = devm_kcalloc(
+		&drv_info->xb_dev->dev, num_devices,
+		sizeof(struct cfg_pcm_instance), GFP_KERNEL);
+	if (!plat_data->cfg_card.pcm_instances)
+		return -ENOMEM;
+
+	for (i = 0; i < num_devices; i++) {
+		ret = cfg_device(drv_info,
+			&plat_data->cfg_card.pcm_instances[i],
+			&plat_data->cfg_card.pcm_hw,
+			xb_dev->nodename, i, stream_idx);
+		if (ret < 0)
+			return ret;
+	}
+	plat_data->cfg_card.num_pcm_instances = num_devices;
+	return 0;
+}
+
 static void xdrv_remove_internal(struct xdrv_info *drv_info)
 {
 }
 
 static int xdrv_be_on_initwait(struct xdrv_info *drv_info)
 {
+	int stream_idx;
+	int ret;
+
+	drv_info->cfg_plat_data.xdrv_info = drv_info;
+	stream_idx = 0;
+	ret = cfg_card(drv_info, &drv_info->cfg_plat_data, &stream_idx);
+	if (ret < 0)
+		return ret;
 	return 0;
 }
 
-- 
2.7.4

  parent reply	other threads:[~2017-08-07 11:51 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-07 11:50 [PATCH RESEND 00/11] ALSA: vsnd: Add Xen para-virtualized frontend driver Oleksandr Andrushchenko
2017-08-07 11:50 ` Oleksandr Andrushchenko
2017-08-07 11:50 ` [PATCH RESEND 01/11] ALSA: vsnd: Implement driver's probe/remove Oleksandr Andrushchenko
2017-08-07 11:50 ` Oleksandr Andrushchenko
2017-08-07 11:50 ` [PATCH RESEND 02/11] ALSA: vsnd: Implement Xen bus state handling Oleksandr Andrushchenko
2017-08-07 11:50   ` Oleksandr Andrushchenko
2017-08-07 11:50 ` [PATCH RESEND 03/11] ALSA: vsnd: Read sound driver configuration from Xen store Oleksandr Andrushchenko
2017-08-07 11:50 ` Oleksandr Andrushchenko [this message]
2017-08-07 11:50 ` [PATCH RESEND 04/11] ALSA: vsnd: Implement Xen event channel handling Oleksandr Andrushchenko
2017-08-07 11:50 ` Oleksandr Andrushchenko
2017-08-07 11:50 ` [PATCH RESEND 05/11] ALSA: vsnd: Implement handling of shared buffers Oleksandr Andrushchenko
2017-08-07 11:50   ` Oleksandr Andrushchenko
2017-08-07 11:50 ` [PATCH RESEND 06/11] ALSA: vsnd: Introduce ALSA virtual sound driver Oleksandr Andrushchenko
2017-08-07 11:50 ` Oleksandr Andrushchenko
2017-08-07 11:50 ` [PATCH RESEND 07/11] ALSA: vsnd: Initialize virtul sound card Oleksandr Andrushchenko
2017-08-07 11:50 ` Oleksandr Andrushchenko
2017-08-07 11:50 ` [PATCH RESEND 08/11] ALSA: vsnd: Add timer for period interrupt emulation Oleksandr Andrushchenko
2017-08-07 11:50   ` Oleksandr Andrushchenko
2017-08-07 11:50 ` [PATCH RESEND 09/11] ALSA: vsnd: Implement ALSA PCM operations Oleksandr Andrushchenko
2017-08-07 11:50   ` Oleksandr Andrushchenko
2017-08-07 11:50 ` [PATCH RESEND 10/11] ALSA: vsnd: Implement communication with backend Oleksandr Andrushchenko
2017-08-07 11:50   ` Oleksandr Andrushchenko
2017-08-07 11:50 ` [PATCH RESEND 11/11] ALSA: vsnd: Introduce Kconfig option to enable Xen PV sound Oleksandr Andrushchenko
2017-08-07 11:50 ` Oleksandr Andrushchenko
2017-08-07 12:09 ` [PATCH RESEND 00/11] ALSA: vsnd: Add Xen para-virtualized frontend driver Takashi Sakamoto
2017-08-07 12:18   ` Oleksandr Andrushchenko
2017-08-07 12:30     ` Takashi Sakamoto
2017-08-07 12:33       ` Oleksandr Andrushchenko
2017-08-07 12:33       ` Oleksandr Andrushchenko
2017-08-07 12:30     ` Takashi Sakamoto
2017-08-07 12:18   ` Oleksandr Andrushchenko
2017-08-07 12:09 ` 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=1502106645-6731-4-git-send-email-andr2000@gmail.com \
    --to=andr2000@gmail.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=oleksandr_andrushchenko@epam.com \
    --cc=perex@perex.cz \
    --cc=tiwai@suse.com \
    --cc=xen-devel@lists.xen.org \
    /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
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.