diff options
author | Mark Brown <broonie@kernel.org> | 2021-09-16 16:06:45 +0100 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2021-09-16 16:06:45 +0100 |
commit | 8e0850f98df947ec96d560a262a198f37409c6bd (patch) | |
tree | ff7509b37f1df42829968eedb0aac88652e83fb0 /sound | |
parent | 8461d7d83f1fe878c4cff72e322711dfcb5a53ca (diff) | |
parent | 49efed50588547b0f13897b6fc69f155c2e2af50 (diff) | |
download | linux-8e0850f98df947ec96d560a262a198f37409c6bd.tar.gz |
Merge series "ASoC: SOF: Clean up the probe support" from Peter Ujfalusi <peter.ujfalusi@linux.intel.com>:
Hi, The probe debug feature of SOF can be used to extract streams of data from a given point of a pipeline for analysis. The support is implemented by using the ALSA/ASoC compress support for the capture stream, but the code can not be used by/for a normal compressed data stream. It is a debug feature. Merge the probe implementation in the core (compress.c/h and probe.c/h) into one file: sof-probes.c/h Rename the Intel HDA specific probe implementation from hda-compressc.c to hda-probes.c We also need to add IPC logging support for the probes messages and drop the unused references to SOF compress to have reasonably clean code. Regards, Peter --- Peter Ujfalusi (5): ASoC: SOF: ipc: Add probe message logging to ipc_log_header() ASoC: SOF: pcm: Remove non existent CONFIG_SND_SOC_SOF_COMPRESS reference ASoC: SOF: probe: Merge and clean up the probe and compress files ASoC: SOF: Intel: Rename hda-compress.c to hda-probes.c ASoC: SOF: sof-probes: Correct the function names used for snd_soc_cdai_ops Ranjani Sridharan (1): ASoC: SOF: compress: move and export sof_probe_compr_ops sound/soc/sof/Makefile | 3 +- sound/soc/sof/compress.c | 147 --------- sound/soc/sof/compress.h | 32 -- sound/soc/sof/core.c | 2 +- sound/soc/sof/debug.c | 2 +- sound/soc/sof/intel/Makefile | 2 +- sound/soc/sof/intel/hda-dai.c | 16 +- .../intel/{hda-compress.c => hda-probes.c} | 0 sound/soc/sof/ipc.c | 23 ++ sound/soc/sof/pcm.c | 6 +- sound/soc/sof/probe.h | 85 ------ sound/soc/sof/sof-priv.h | 5 - sound/soc/sof/{probe.c => sof-probes.c} | 280 +++++++++++------- sound/soc/sof/sof-probes.h | 38 +++ 14 files changed, 248 insertions(+), 393 deletions(-) delete mode 100644 sound/soc/sof/compress.c delete mode 100644 sound/soc/sof/compress.h rename sound/soc/sof/intel/{hda-compress.c => hda-probes.c} (100%) delete mode 100644 sound/soc/sof/probe.h rename sound/soc/sof/{probe.c => sof-probes.c} (52%) create mode 100644 sound/soc/sof/sof-probes.h -- 2.33.0
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/sof/Makefile | 3 | ||||
-rw-r--r-- | sound/soc/sof/compress.c | 147 | ||||
-rw-r--r-- | sound/soc/sof/compress.h | 32 | ||||
-rw-r--r-- | sound/soc/sof/core.c | 2 | ||||
-rw-r--r-- | sound/soc/sof/debug.c | 2 | ||||
-rw-r--r-- | sound/soc/sof/intel/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/sof/intel/hda-dai.c | 16 | ||||
-rw-r--r-- | sound/soc/sof/intel/hda-probes.c (renamed from sound/soc/sof/intel/hda-compress.c) | 0 | ||||
-rw-r--r-- | sound/soc/sof/ipc.c | 23 | ||||
-rw-r--r-- | sound/soc/sof/pcm.c | 6 | ||||
-rw-r--r-- | sound/soc/sof/probe.h | 85 | ||||
-rw-r--r-- | sound/soc/sof/sof-priv.h | 5 | ||||
-rw-r--r-- | sound/soc/sof/sof-probes.c (renamed from sound/soc/sof/probe.c) | 280 | ||||
-rw-r--r-- | sound/soc/sof/sof-probes.h | 38 |
14 files changed, 248 insertions, 393 deletions
diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index 606d8137cd98..bdea0faac117 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile @@ -2,7 +2,8 @@ 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 compress.o + +snd-sof-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += sof-probes.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 deleted file mode 100644 index 57d5bf0a171e..000000000000 --- a/sound/soc/sof/compress.c +++ /dev/null @@ -1,147 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0-only 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" - -const struct snd_compress_ops sof_probe_compressed_ops = { - .copy = sof_probe_compr_copy, -}; -EXPORT_SYMBOL(sof_probe_compressed_ops); - -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_soc_component *component, - 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 deleted file mode 100644 index 4448c799e14b..000000000000 --- a/sound/soc/sof/compress.h +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0-only 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> - -extern const struct snd_compress_ops sof_probe_compressed_ops; - -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_soc_component *component, - struct snd_compr_stream *cstream, - char __user *buf, size_t count); - -#endif diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 9cbf7d72ae92..7f28fdd3084c 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -15,7 +15,7 @@ #include "sof-priv.h" #include "ops.h" #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) -#include "probe.h" +#include "sof-probes.h" #endif /* see SOF_DBG_ flags */ diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index af92baacd23e..f37ea1956406 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -20,7 +20,7 @@ #include "ops.h" #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) -#include "probe.h" +#include "sof-probes.h" /** * strsplit_u32 - Split string into sequence of u32 tokens diff --git a/sound/soc/sof/intel/Makefile b/sound/soc/sof/intel/Makefile index feae487f0227..9635dd47a17d 100644 --- a/sound/soc/sof/intel/Makefile +++ b/sound/soc/sof/intel/Makefile @@ -9,7 +9,7 @@ snd-sof-intel-hda-common-objs := hda.o hda-loader.o hda-stream.o hda-trace.o \ hda-dsp.o hda-ipc.o hda-ctrl.o hda-pcm.o \ hda-dai.o hda-bus.o \ apl.o cnl.o tgl.o icl.o -snd-sof-intel-hda-common-$(CONFIG_SND_SOC_SOF_HDA_PROBES) += hda-compress.o +snd-sof-intel-hda-common-$(CONFIG_SND_SOC_SOF_HDA_PROBES) += hda-probes.o snd-sof-intel-hda-objs := hda-codec.o diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index c1f9f0f58464..2f54a659b78a 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -16,6 +16,10 @@ #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) +#include "../sof-probes.h" +#endif + struct hda_pipe_params { u8 host_dma_id; u8 link_dma_id; @@ -400,18 +404,6 @@ static const struct snd_soc_dai_ops hda_link_dai_ops = { .prepare = hda_link_pcm_prepare, }; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES) -#include "../compress.h" - -static struct snd_soc_cdai_ops sof_probe_compr_ops = { - .startup = sof_probe_compr_open, - .shutdown = sof_probe_compr_free, - .set_params = sof_probe_compr_set_params, - .trigger = sof_probe_compr_trigger, - .pointer = sof_probe_compr_pointer, -}; - -#endif #endif static int ssp_dai_hw_params(struct snd_pcm_substream *substream, diff --git a/sound/soc/sof/intel/hda-compress.c b/sound/soc/sof/intel/hda-probes.c index fe2f3f7d236b..fe2f3f7d236b 100644 --- a/sound/soc/sof/intel/hda-compress.c +++ b/sound/soc/sof/intel/hda-probes.c diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 18e0bfc1d8a9..8145b0d5564a 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -192,6 +192,29 @@ static void ipc_log_header(struct device *dev, u8 *text, u32 cmd) str2 = "unknown type"; break; } break; + case SOF_IPC_GLB_PROBE: + str = "GLB_PROBE"; + switch (type) { + case SOF_IPC_PROBE_INIT: + str2 = "INIT"; break; + case SOF_IPC_PROBE_DEINIT: + str2 = "DEINIT"; break; + case SOF_IPC_PROBE_DMA_ADD: + str2 = "DMA_ADD"; break; + case SOF_IPC_PROBE_DMA_INFO: + str2 = "DMA_INFO"; break; + case SOF_IPC_PROBE_DMA_REMOVE: + str2 = "DMA_REMOVE"; break; + case SOF_IPC_PROBE_POINT_ADD: + str2 = "POINT_ADD"; break; + case SOF_IPC_PROBE_POINT_INFO: + str2 = "POINT_INFO"; break; + case SOF_IPC_PROBE_POINT_REMOVE: + str2 = "POINT_REMOVE"; break; + default: + str2 = "unknown type"; break; + } + break; default: str = "unknown GLB command"; break; } diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 9893b182da43..b4280459e5db 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -17,7 +17,7 @@ #include "sof-audio.h" #include "ops.h" #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) -#include "compress.h" +#include "sof-probes.h" #endif /* Create DMA buffer page table for DSP */ @@ -829,11 +829,7 @@ void snd_sof_new_platform_drv(struct snd_sof_dev *sdev) pd->trigger = sof_pcm_trigger; pd->pointer = sof_pcm_pointer; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMPRESS) - pd->compress_ops = &sof_compressed_ops; -#endif #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) - /* override cops when probe support is enabled */ pd->compress_ops = &sof_probe_compressed_ops; #endif pd->pcm_construct = sof_pcm_new; diff --git a/sound/soc/sof/probe.h b/sound/soc/sof/probe.h deleted file mode 100644 index 5e159ab239fa..000000000000 --- a/sound/soc/sof/probe.h +++ /dev/null @@ -1,85 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0-only 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_PROBE_H -#define __SOF_PROBE_H - -#include <sound/sof/header.h> - -struct snd_sof_dev; - -#define SOF_PROBE_INVALID_NODE_ID UINT_MAX - -struct sof_probe_dma { - unsigned int stream_tag; - unsigned int dma_buffer_size; -} __packed; - -enum sof_connection_purpose { - SOF_CONNECTION_PURPOSE_EXTRACT = 1, - SOF_CONNECTION_PURPOSE_INJECT, -}; - -struct sof_probe_point_desc { - unsigned int buffer_id; - unsigned int purpose; - unsigned int stream_tag; -} __packed; - -struct sof_ipc_probe_dma_add_params { - struct sof_ipc_cmd_hdr hdr; - unsigned int num_elems; - struct sof_probe_dma dma[]; -} __packed; - -struct sof_ipc_probe_info_params { - struct sof_ipc_reply rhdr; - unsigned int num_elems; - union { - struct sof_probe_dma dma[0]; - struct sof_probe_point_desc desc[0]; - }; -} __packed; - -struct sof_ipc_probe_dma_remove_params { - struct sof_ipc_cmd_hdr hdr; - unsigned int num_elems; - unsigned int stream_tag[]; -} __packed; - -struct sof_ipc_probe_point_add_params { - struct sof_ipc_cmd_hdr hdr; - unsigned int num_elems; - struct sof_probe_point_desc desc[]; -} __packed; - -struct sof_ipc_probe_point_remove_params { - struct sof_ipc_cmd_hdr hdr; - unsigned int num_elems; - unsigned int buffer_id[]; -} __packed; - -int sof_ipc_probe_init(struct snd_sof_dev *sdev, - u32 stream_tag, size_t buffer_size); -int sof_ipc_probe_deinit(struct snd_sof_dev *sdev); -int sof_ipc_probe_dma_info(struct snd_sof_dev *sdev, - struct sof_probe_dma **dma, size_t *num_dma); -int sof_ipc_probe_dma_add(struct snd_sof_dev *sdev, - struct sof_probe_dma *dma, size_t num_dma); -int sof_ipc_probe_dma_remove(struct snd_sof_dev *sdev, - unsigned int *stream_tag, size_t num_stream_tag); -int sof_ipc_probe_points_info(struct snd_sof_dev *sdev, - struct sof_probe_point_desc **desc, size_t *num_desc); -int sof_ipc_probe_points_add(struct snd_sof_dev *sdev, - struct sof_probe_point_desc *desc, size_t num_desc); -int sof_ipc_probe_points_remove(struct snd_sof_dev *sdev, - unsigned int *buffer_id, size_t num_buffer_id); - -#endif diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 80e4a8c29280..aa9db448e0a3 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -539,11 +539,6 @@ int snd_sof_debugfs_add_region_item_iomem(struct snd_sof_dev *sdev, const char *name, enum sof_debugfs_access_type access_type); /* - * Platform specific ops. - */ -extern struct snd_compress_ops sof_compressed_ops; - -/* * DSP Architectures. */ static inline void sof_stack(struct snd_sof_dev *sdev, void *oops, u32 *stack, diff --git a/sound/soc/sof/probe.c b/sound/soc/sof/sof-probes.c index 14509f4d3f86..5586af9f1a25 100644 --- a/sound/soc/sof/probe.c +++ b/sound/soc/sof/sof-probes.c @@ -3,13 +3,46 @@ // 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. -// +// Copyright(c) 2019-2021 Intel Corporation. All rights reserved. // Author: Cezary Rojewski <cezary.rojewski@intel.com> // +#include <sound/soc.h> +#include "ops.h" #include "sof-priv.h" -#include "probe.h" +#include "sof-probes.h" + +struct sof_probe_dma { + unsigned int stream_tag; + unsigned int dma_buffer_size; +} __packed; + +struct sof_ipc_probe_dma_add_params { + struct sof_ipc_cmd_hdr hdr; + unsigned int num_elems; + struct sof_probe_dma dma[]; +} __packed; + +struct sof_ipc_probe_info_params { + struct sof_ipc_reply rhdr; + unsigned int num_elems; + union { + struct sof_probe_dma dma[0]; + struct sof_probe_point_desc desc[0]; + }; +} __packed; + +struct sof_ipc_probe_point_add_params { + struct sof_ipc_cmd_hdr hdr; + unsigned int num_elems; + struct sof_probe_point_desc desc[]; +} __packed; + +struct sof_ipc_probe_point_remove_params { + struct sof_ipc_cmd_hdr hdr; + unsigned int num_elems; + unsigned int buffer_id[]; +} __packed; /** * sof_ipc_probe_init - initialize data probing @@ -25,8 +58,8 @@ * Probing is initialized only once and each INIT request must be * matched by DEINIT call. */ -int sof_ipc_probe_init(struct snd_sof_dev *sdev, - u32 stream_tag, size_t buffer_size) +static int sof_ipc_probe_init(struct snd_sof_dev *sdev, u32 stream_tag, + size_t buffer_size) { struct sof_ipc_probe_dma_add_params *msg; struct sof_ipc_reply reply; @@ -47,7 +80,6 @@ int sof_ipc_probe_init(struct snd_sof_dev *sdev, kfree(msg); return ret; } -EXPORT_SYMBOL(sof_ipc_probe_init); /** * sof_ipc_probe_deinit - cleanup after data probing @@ -57,7 +89,7 @@ EXPORT_SYMBOL(sof_ipc_probe_init); * on DSP side once it is no longer needed. DEINIT only when there * are no probes connected and with all injectors detached. */ -int sof_ipc_probe_deinit(struct snd_sof_dev *sdev) +static int sof_ipc_probe_deinit(struct snd_sof_dev *sdev) { struct sof_ipc_cmd_hdr msg; struct sof_ipc_reply reply; @@ -68,10 +100,9 @@ int sof_ipc_probe_deinit(struct snd_sof_dev *sdev) return sof_ipc_tx_message(sdev->ipc, msg.cmd, &msg, msg.size, &reply, sizeof(reply)); } -EXPORT_SYMBOL(sof_ipc_probe_deinit); static int sof_ipc_probe_info(struct snd_sof_dev *sdev, unsigned int cmd, - void **params, size_t *num_params) + void **params, size_t *num_params) { struct sof_ipc_probe_info_params msg = {{{0}}}; struct sof_ipc_probe_info_params *reply; @@ -113,97 +144,6 @@ exit: } /** - * sof_ipc_probe_dma_info - retrieve list of active injection dmas - * @sdev: SOF sound device - * @dma: Returned list of active dmas - * @num_dma: Returned count of active dmas - * - * Host sends DMA_INFO request to obtain list of injection dmas it - * can use to transfer data over with. - * - * Note that list contains only injection dmas as there is only one - * extractor (dma) and it is always assigned on probing init. - * DSP knows exactly where data from extraction probes is going to, - * which is not the case for injection where multiple streams - * could be engaged. - */ -int sof_ipc_probe_dma_info(struct snd_sof_dev *sdev, - struct sof_probe_dma **dma, size_t *num_dma) -{ - return sof_ipc_probe_info(sdev, SOF_IPC_PROBE_DMA_INFO, - (void **)dma, num_dma); -} -EXPORT_SYMBOL(sof_ipc_probe_dma_info); - -/** - * sof_ipc_probe_dma_add - attach to specified dmas - * @sdev: SOF sound device - * @dma: List of streams (dmas) to attach to - * @num_dma: Number of elements in @dma - * - * Contrary to extraction, injection streams are never assigned - * on init. Before attempting any data injection, host is responsible - * for specifying streams which will be later used to transfer data - * to connected probe points. - */ -int sof_ipc_probe_dma_add(struct snd_sof_dev *sdev, - struct sof_probe_dma *dma, size_t num_dma) -{ - struct sof_ipc_probe_dma_add_params *msg; - struct sof_ipc_reply reply; - size_t size = struct_size(msg, dma, num_dma); - int ret; - - msg = kmalloc(size, GFP_KERNEL); - if (!msg) - return -ENOMEM; - msg->hdr.size = size; - msg->num_elems = num_dma; - msg->hdr.cmd = SOF_IPC_GLB_PROBE | SOF_IPC_PROBE_DMA_ADD; - memcpy(&msg->dma[0], dma, size - sizeof(*msg)); - - ret = sof_ipc_tx_message(sdev->ipc, msg->hdr.cmd, msg, msg->hdr.size, - &reply, sizeof(reply)); - kfree(msg); - return ret; -} -EXPORT_SYMBOL(sof_ipc_probe_dma_add); - -/** - * sof_ipc_probe_dma_remove - detach from specified dmas - * @sdev: SOF sound device - * @stream_tag: List of stream tags to detach from - * @num_stream_tag: Number of elements in @stream_tag - * - * Host sends DMA_REMOVE request to free previously attached stream - * from being occupied for injection. Each detach operation should - * match equivalent DMA_ADD. Detach only when all probes tied to - * given stream have been disconnected. - */ -int sof_ipc_probe_dma_remove(struct snd_sof_dev *sdev, - unsigned int *stream_tag, size_t num_stream_tag) -{ - struct sof_ipc_probe_dma_remove_params *msg; - struct sof_ipc_reply reply; - size_t size = struct_size(msg, stream_tag, num_stream_tag); - int ret; - - msg = kmalloc(size, GFP_KERNEL); - if (!msg) - return -ENOMEM; - msg->hdr.size = size; - msg->num_elems = num_stream_tag; - msg->hdr.cmd = SOF_IPC_GLB_PROBE | SOF_IPC_PROBE_DMA_REMOVE; - memcpy(&msg->stream_tag[0], stream_tag, size - sizeof(*msg)); - - ret = sof_ipc_tx_message(sdev->ipc, msg->hdr.cmd, msg, msg->hdr.size, - &reply, sizeof(reply)); - kfree(msg); - return ret; -} -EXPORT_SYMBOL(sof_ipc_probe_dma_remove); - -/** * sof_ipc_probe_points_info - retrieve list of active probe points * @sdev: SOF sound device * @desc: Returned list of active probes @@ -214,7 +154,8 @@ EXPORT_SYMBOL(sof_ipc_probe_dma_remove); * required. */ int sof_ipc_probe_points_info(struct snd_sof_dev *sdev, - struct sof_probe_point_desc **desc, size_t *num_desc) + struct sof_probe_point_desc **desc, + size_t *num_desc) { return sof_ipc_probe_info(sdev, SOF_IPC_PROBE_POINT_INFO, (void **)desc, num_desc); @@ -235,7 +176,7 @@ EXPORT_SYMBOL(sof_ipc_probe_points_info); * request when no longer needed. */ int sof_ipc_probe_points_add(struct snd_sof_dev *sdev, - struct sof_probe_point_desc *desc, size_t num_desc) + struct sof_probe_point_desc *desc, size_t num_desc) { struct sof_ipc_probe_point_add_params *msg; struct sof_ipc_reply reply; @@ -267,7 +208,7 @@ EXPORT_SYMBOL(sof_ipc_probe_points_add); * points and frees all resources on DSP side. */ int sof_ipc_probe_points_remove(struct snd_sof_dev *sdev, - unsigned int *buffer_id, size_t num_buffer_id) + unsigned int *buffer_id, size_t num_buffer_id) { struct sof_ipc_probe_point_remove_params *msg; struct sof_ipc_reply reply; @@ -288,3 +229,136 @@ int sof_ipc_probe_points_remove(struct snd_sof_dev *sdev, return ret; } EXPORT_SYMBOL(sof_ipc_probe_points_remove); + +static int sof_probe_compr_startup(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; +} + +static int sof_probe_compr_shutdown(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); +} + +static int sof_probe_compr_set_params(struct snd_compr_stream *cstream, + struct snd_compr_params *params, + struct snd_soc_dai *dai) +{ + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component); + struct snd_compr_runtime *rtd = cstream->runtime; + 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; +} + +static 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); +} + +static 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); +} + +struct snd_soc_cdai_ops sof_probe_compr_ops = { + .startup = sof_probe_compr_startup, + .shutdown = sof_probe_compr_shutdown, + .set_params = sof_probe_compr_set_params, + .trigger = sof_probe_compr_trigger, + .pointer = sof_probe_compr_pointer, +}; +EXPORT_SYMBOL(sof_probe_compr_ops); + +static int sof_probe_compr_copy(struct snd_soc_component *component, + 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; +} + +const struct snd_compress_ops sof_probe_compressed_ops = { + .copy = sof_probe_compr_copy, +}; +EXPORT_SYMBOL(sof_probe_compressed_ops); diff --git a/sound/soc/sof/sof-probes.h b/sound/soc/sof/sof-probes.h new file mode 100644 index 000000000000..35e1dd8d9e03 --- /dev/null +++ b/sound/soc/sof/sof-probes.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: (GPL-2.0-only 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-2021 Intel Corporation. All rights reserved. + * Author: Cezary Rojewski <cezary.rojewski@intel.com> + */ + +#ifndef __SOF_PROBES_H +#define __SOF_PROBES_H + +#include <sound/compress_driver.h> +#include <sound/sof/header.h> + +struct snd_sof_dev; + +#define SOF_PROBE_INVALID_NODE_ID UINT_MAX + +struct sof_probe_point_desc { + unsigned int buffer_id; + unsigned int purpose; + unsigned int stream_tag; +} __packed; + +int sof_ipc_probe_points_info(struct snd_sof_dev *sdev, + struct sof_probe_point_desc **desc, + size_t *num_desc); +int sof_ipc_probe_points_add(struct snd_sof_dev *sdev, + struct sof_probe_point_desc *desc, + size_t num_desc); +int sof_ipc_probe_points_remove(struct snd_sof_dev *sdev, + unsigned int *buffer_id, size_t num_buffer_id); + +extern struct snd_soc_cdai_ops sof_probe_compr_ops; +extern const struct snd_compress_ops sof_probe_compressed_ops; + +#endif |