[alsa-devel] [PATCH v3 08/11] ASoC: SOF: Generic probe compress operations
Cezary Rojewski
cezary.rojewski at intel.com
Tue Jan 28 11:43:53 CET 2020
Define system-agnostic probe compress flow which serves as a base for
actual, hardware-dependent implementations.
As per firmware spec, maximum of one extraction stream is allowed, while
for injection, there can be plenty.
Apart from probe_pointer, all probe compress operations are mandatory.
Copy operation is defined as unified as its flow should be shared across
all SOF systems.
Signed-off-by: Cezary Rojewski <cezary.rojewski at intel.com>
---
Changes in v3:
- 'extractor' field has been relocated to this patch from: "[PATCH v3
07/11] ASoC: SOF: Implement Probe IPC API"
- 'extractor' field has been renamed to 'extractor_stream_tag'
- _DEBUG_PROBES kconfig moved outside of _DEVELOPER_SUPPORT block
sound/soc/sof/Kconfig | 9 +++
sound/soc/sof/Makefile | 1 +
sound/soc/sof/compress.c | 140 +++++++++++++++++++++++++++++++++++++++
sound/soc/sof/compress.h | 29 ++++++++
sound/soc/sof/ops.h | 43 ++++++++++++
sound/soc/sof/sof-priv.h | 24 +++++++
6 files changed, 246 insertions(+)
create mode 100644 sound/soc/sof/compress.c
create mode 100644 sound/soc/sof/compress.h
diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig
index 827b0ec92522..4dda4b62509f 100644
--- a/sound/soc/sof/Kconfig
+++ b/sound/soc/sof/Kconfig
@@ -41,6 +41,15 @@ config SND_SOC_SOF_OF
required to enable i.MX8 devices.
Say Y if you need this option. If unsure select "N".
+config SND_SOC_SOF_DEBUG_PROBES
+ bool "SOF enable data probing"
+ select SND_SOC_COMPRESS
+ help
+ This option enables the data probing feature that can be used to
+ gather data directly from specific points of the audio pipeline.
+ Say Y if you want to enable probes.
+ If unsure, select "N".
+
config SND_SOC_SOF_DEVELOPER_SUPPORT
bool "SOF developer options support"
depends on EXPERT
diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile
index 99c26420d9e5..437ec1b40c14 100644
--- a/sound/soc/sof/Makefile
+++ b/sound/soc/sof/Makefile
@@ -2,6 +2,7 @@
snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\
control.o probe.o trace.o utils.o sof-audio.o
+snd-sof-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += compress.o
snd-sof-pci-objs := sof-pci-dev.o
snd-sof-acpi-objs := sof-acpi-dev.o
diff --git a/sound/soc/sof/compress.c b/sound/soc/sof/compress.c
new file mode 100644
index 000000000000..a5f644711aff
--- /dev/null
+++ b/sound/soc/sof/compress.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+//
+// This file is provided under a dual BSD/GPLv2 license. When using or
+// redistributing this file, you may do so under either license.
+//
+// Copyright(c) 2019-2020 Intel Corporation. All rights reserved.
+//
+// Author: Cezary Rojewski <cezary.rojewski at intel.com>
+//
+
+#include <sound/soc.h>
+#include "compress.h"
+#include "ops.h"
+#include "probe.h"
+
+int sof_probe_compr_open(struct snd_compr_stream *cstream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_sof_dev *sdev =
+ snd_soc_component_get_drvdata(dai->component);
+ int ret;
+
+ ret = snd_sof_probe_compr_assign(sdev, cstream, dai);
+ if (ret < 0) {
+ dev_err(dai->dev, "Failed to assign probe stream: %d\n", ret);
+ return ret;
+ }
+
+ sdev->extractor_stream_tag = ret;
+ return 0;
+}
+EXPORT_SYMBOL(sof_probe_compr_open);
+
+int sof_probe_compr_free(struct snd_compr_stream *cstream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_sof_dev *sdev =
+ snd_soc_component_get_drvdata(dai->component);
+ struct sof_probe_point_desc *desc;
+ size_t num_desc;
+ int i, ret;
+
+ /* disconnect all probe points */
+ ret = sof_ipc_probe_points_info(sdev, &desc, &num_desc);
+ if (ret < 0) {
+ dev_err(dai->dev, "Failed to get probe points: %d\n", ret);
+ goto exit;
+ }
+
+ for (i = 0; i < num_desc; i++)
+ sof_ipc_probe_points_remove(sdev, &desc[i].buffer_id, 1);
+ kfree(desc);
+
+exit:
+ ret = sof_ipc_probe_deinit(sdev);
+ if (ret < 0)
+ dev_err(dai->dev, "Failed to deinit probe: %d\n", ret);
+
+ snd_compr_free_pages(cstream);
+
+ return snd_sof_probe_compr_free(sdev, cstream, dai);
+}
+EXPORT_SYMBOL(sof_probe_compr_free);
+
+int sof_probe_compr_set_params(struct snd_compr_stream *cstream,
+ struct snd_compr_params *params, struct snd_soc_dai *dai)
+{
+ struct snd_compr_runtime *rtd = cstream->runtime;
+ struct snd_sof_dev *sdev =
+ snd_soc_component_get_drvdata(dai->component);
+ int ret;
+
+ cstream->dma_buffer.dev.type = SNDRV_DMA_TYPE_DEV_SG;
+ cstream->dma_buffer.dev.dev = sdev->dev;
+ ret = snd_compr_malloc_pages(cstream, rtd->buffer_size);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_sof_probe_compr_set_params(sdev, cstream, params, dai);
+ if (ret < 0)
+ return ret;
+
+ ret = sof_ipc_probe_init(sdev, sdev->extractor_stream_tag,
+ rtd->dma_bytes);
+ if (ret < 0) {
+ dev_err(dai->dev, "Failed to init probe: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(sof_probe_compr_set_params);
+
+int sof_probe_compr_trigger(struct snd_compr_stream *cstream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct snd_sof_dev *sdev =
+ snd_soc_component_get_drvdata(dai->component);
+
+ return snd_sof_probe_compr_trigger(sdev, cstream, cmd, dai);
+}
+EXPORT_SYMBOL(sof_probe_compr_trigger);
+
+int sof_probe_compr_pointer(struct snd_compr_stream *cstream,
+ struct snd_compr_tstamp *tstamp, struct snd_soc_dai *dai)
+{
+ struct snd_sof_dev *sdev =
+ snd_soc_component_get_drvdata(dai->component);
+
+ return snd_sof_probe_compr_pointer(sdev, cstream, tstamp, dai);
+}
+EXPORT_SYMBOL(sof_probe_compr_pointer);
+
+int sof_probe_compr_copy(struct snd_compr_stream *cstream,
+ char __user *buf, size_t count)
+{
+ struct snd_compr_runtime *rtd = cstream->runtime;
+ unsigned int offset, n;
+ void *ptr;
+ int ret;
+
+ if (count > rtd->buffer_size)
+ count = rtd->buffer_size;
+
+ div_u64_rem(rtd->total_bytes_transferred, rtd->buffer_size, &offset);
+ ptr = rtd->dma_area + offset;
+ n = rtd->buffer_size - offset;
+
+ if (count < n) {
+ ret = copy_to_user(buf, ptr, count);
+ } else {
+ ret = copy_to_user(buf, ptr, n);
+ ret += copy_to_user(buf + n, rtd->dma_area, count - n);
+ }
+
+ if (ret)
+ return count - ret;
+ return count;
+}
+EXPORT_SYMBOL(sof_probe_compr_copy);
diff --git a/sound/soc/sof/compress.h b/sound/soc/sof/compress.h
new file mode 100644
index 000000000000..dccc9e008f81
--- /dev/null
+++ b/sound/soc/sof/compress.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * Copyright(c) 2019-2020 Intel Corporation. All rights reserved.
+ *
+ * Author: Cezary Rojewski <cezary.rojewski at intel.com>
+ */
+
+#ifndef __SOF_COMPRESS_H
+#define __SOF_COMPRESS_H
+
+#include <sound/compress_driver.h>
+
+int sof_probe_compr_open(struct snd_compr_stream *cstream,
+ struct snd_soc_dai *dai);
+int sof_probe_compr_free(struct snd_compr_stream *cstream,
+ struct snd_soc_dai *dai);
+int sof_probe_compr_set_params(struct snd_compr_stream *cstream,
+ struct snd_compr_params *params, struct snd_soc_dai *dai);
+int sof_probe_compr_trigger(struct snd_compr_stream *cstream, int cmd,
+ struct snd_soc_dai *dai);
+int sof_probe_compr_pointer(struct snd_compr_stream *cstream,
+ struct snd_compr_tstamp *tstamp, struct snd_soc_dai *dai);
+int sof_probe_compr_copy(struct snd_compr_stream *cstream,
+ char __user *buf, size_t count);
+
+#endif
diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h
index e929a6e0058f..33e399c36825 100644
--- a/sound/soc/sof/ops.h
+++ b/sound/soc/sof/ops.h
@@ -391,6 +391,49 @@ snd_sof_pcm_platform_pointer(struct snd_sof_dev *sdev,
return 0;
}
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
+static inline int
+snd_sof_probe_compr_assign(struct snd_sof_dev *sdev,
+ struct snd_compr_stream *cstream, struct snd_soc_dai *dai)
+{
+ return sof_ops(sdev)->probe_assign(sdev, cstream, dai);
+}
+
+static inline int
+snd_sof_probe_compr_free(struct snd_sof_dev *sdev,
+ struct snd_compr_stream *cstream, struct snd_soc_dai *dai)
+{
+ return sof_ops(sdev)->probe_free(sdev, cstream, dai);
+}
+
+static inline int
+snd_sof_probe_compr_set_params(struct snd_sof_dev *sdev,
+ struct snd_compr_stream *cstream,
+ struct snd_compr_params *params, struct snd_soc_dai *dai)
+{
+ return sof_ops(sdev)->probe_set_params(sdev, cstream, params, dai);
+}
+
+static inline int
+snd_sof_probe_compr_trigger(struct snd_sof_dev *sdev,
+ struct snd_compr_stream *cstream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ return sof_ops(sdev)->probe_trigger(sdev, cstream, cmd, dai);
+}
+
+static inline int
+snd_sof_probe_compr_pointer(struct snd_sof_dev *sdev,
+ struct snd_compr_stream *cstream,
+ struct snd_compr_tstamp *tstamp, struct snd_soc_dai *dai)
+{
+ if (sof_ops(sdev) && sof_ops(sdev)->probe_pointer)
+ return sof_ops(sdev)->probe_pointer(sdev, cstream, tstamp, dai);
+
+ return 0;
+}
+#endif
+
/* machine driver */
static inline int
snd_sof_machine_register(struct snd_sof_dev *sdev, void *pdata)
diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
index bc2337cf1142..b08e1811ac06 100644
--- a/sound/soc/sof/sof-priv.h
+++ b/sound/soc/sof/sof-priv.h
@@ -154,6 +154,27 @@ struct snd_sof_dsp_ops {
snd_pcm_uframes_t (*pcm_pointer)(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream); /* optional */
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
+ /* Except for probe_pointer, all probe ops are mandatory */
+ int (*probe_assign)(struct snd_sof_dev *sdev,
+ struct snd_compr_stream *cstream,
+ struct snd_soc_dai *dai); /* mandatory */
+ int (*probe_free)(struct snd_sof_dev *sdev,
+ struct snd_compr_stream *cstream,
+ struct snd_soc_dai *dai); /* mandatory */
+ int (*probe_set_params)(struct snd_sof_dev *sdev,
+ struct snd_compr_stream *cstream,
+ struct snd_compr_params *params,
+ struct snd_soc_dai *dai); /* mandatory */
+ int (*probe_trigger)(struct snd_sof_dev *sdev,
+ struct snd_compr_stream *cstream, int cmd,
+ struct snd_soc_dai *dai); /* mandatory */
+ int (*probe_pointer)(struct snd_sof_dev *sdev,
+ struct snd_compr_stream *cstream,
+ struct snd_compr_tstamp *tstamp,
+ struct snd_soc_dai *dai); /* optional */
+#endif
+
/* host read DSP stream data */
void (*ipc_msg_data)(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
@@ -387,6 +408,9 @@ struct snd_sof_dev {
wait_queue_head_t waitq;
int code_loading;
+ /* probes */
+ unsigned int extractor_stream_tag;
+
/* DMA for Trace */
struct snd_dma_buffer dmatb;
struct snd_dma_buffer dmatp;
--
2.17.1
More information about the Alsa-devel
mailing list