]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
ASoC: SOF: Generic probe compress operations
authorCezary Rojewski <cezary.rojewski@intel.com>
Tue, 18 Feb 2020 14:39:20 +0000 (15:39 +0100)
committerMark Brown <broonie@kernel.org>
Tue, 18 Feb 2020 21:52:07 +0000 (21:52 +0000)
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@intel.com>
Acked-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20200218143924.10565-6-cezary.rojewski@intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/Kconfig
sound/soc/sof/Makefile
sound/soc/sof/compress.c [new file with mode: 0644]
sound/soc/sof/compress.h [new file with mode: 0644]
sound/soc/sof/core.c
sound/soc/sof/ops.h
sound/soc/sof/sof-priv.h

index 65c3cfbcb812f79c231f759346a354db592e4ae2..4dda4b62509f04559a53532c6e2e4233d10dc49e 100644 (file)
@@ -43,6 +43,7 @@ config SND_SOC_SOF_OF
 
 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.
index 18d7cab9046e4cd82381aa9a6c20b01e1e76b736..8eca2f85c90e39bb8b48001c37665c648eeb29ed 100644 (file)
@@ -2,7 +2,7 @@
 
 snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\
                control.o trace.o utils.o sof-audio.o
-snd-sof-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += probe.o
+snd-sof-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += probe.o 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 (file)
index 0000000..e87cc81
--- /dev/null
@@ -0,0 +1,141 @@
+// 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@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);
+
+       sdev->extractor_stream_tag = SOF_PROBE_INVALID_NODE_ID;
+       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 (file)
index 0000000..dccc9e0
--- /dev/null
@@ -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@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
index 1d07450aff7774f7892c85437e9ce589d8470271..91acfae7935c99287e4f15f99296a896b42e6c84 100644 (file)
@@ -14,6 +14,9 @@
 #include <sound/sof.h>
 #include "sof-priv.h"
 #include "ops.h"
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
+#include "probe.h"
+#endif
 
 /* see SOF_DBG_ flags */
 int sof_core_debug;
@@ -292,6 +295,9 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
        sdev->pdata = plat_data;
        sdev->first_boot = true;
        sdev->fw_state = SOF_FW_BOOT_NOT_STARTED;
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
+       sdev->extractor_stream_tag = SOF_PROBE_INVALID_NODE_ID;
+#endif
        dev_set_drvdata(dev, sdev);
 
        /* check all mandatory ops */
index 7f532bcc8e9dd3df376548ef08c9b94d8f647f13..a771500ac442410378542e422c79e709d548e0de 100644 (file)
@@ -393,6 +393,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)
index 00084471d0de193452e05a8d5aeb9d318910f97f..5d16f668d16aa79ea90321f60a323756492eddb6 100644 (file)
@@ -170,6 +170,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,
@@ -405,6 +426,10 @@ struct snd_sof_dev {
        wait_queue_head_t waitq;
        int code_loading;
 
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
+       unsigned int extractor_stream_tag;
+#endif
+
        /* DMA for Trace */
        struct snd_dma_buffer dmatb;
        struct snd_dma_buffer dmatp;