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
This commit is contained in:
Коммит
8e0850f98d
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\
|
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
|
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-pci-objs := sof-pci-dev.o
|
||||||
snd-sof-acpi-objs := sof-acpi-dev.o
|
snd-sof-acpi-objs := sof-acpi-dev.o
|
||||||
|
|
|
@ -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);
|
|
|
@ -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
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include "sof-priv.h"
|
#include "sof-priv.h"
|
||||||
#include "ops.h"
|
#include "ops.h"
|
||||||
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
|
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
|
||||||
#include "probe.h"
|
#include "sof-probes.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* see SOF_DBG_ flags */
|
/* see SOF_DBG_ flags */
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "ops.h"
|
#include "ops.h"
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
|
#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
|
* strsplit_u32 - Split string into sequence of u32 tokens
|
||||||
|
|
|
@ -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-dsp.o hda-ipc.o hda-ctrl.o hda-pcm.o \
|
||||||
hda-dai.o hda-bus.o \
|
hda-dai.o hda-bus.o \
|
||||||
apl.o cnl.o tgl.o icl.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
|
snd-sof-intel-hda-objs := hda-codec.o
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
|
#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 {
|
struct hda_pipe_params {
|
||||||
u8 host_dma_id;
|
u8 host_dma_id;
|
||||||
u8 link_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,
|
.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
|
#endif
|
||||||
|
|
||||||
static int ssp_dai_hw_params(struct snd_pcm_substream *substream,
|
static int ssp_dai_hw_params(struct snd_pcm_substream *substream,
|
||||||
|
|
|
@ -192,6 +192,29 @@ static void ipc_log_header(struct device *dev, u8 *text, u32 cmd)
|
||||||
str2 = "unknown type"; break;
|
str2 = "unknown type"; break;
|
||||||
}
|
}
|
||||||
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:
|
default:
|
||||||
str = "unknown GLB command"; break;
|
str = "unknown GLB command"; break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include "sof-audio.h"
|
#include "sof-audio.h"
|
||||||
#include "ops.h"
|
#include "ops.h"
|
||||||
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
|
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
|
||||||
#include "compress.h"
|
#include "sof-probes.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Create DMA buffer page table for DSP */
|
/* 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->trigger = sof_pcm_trigger;
|
||||||
pd->pointer = sof_pcm_pointer;
|
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)
|
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
|
||||||
/* override cops when probe support is enabled */
|
|
||||||
pd->compress_ops = &sof_probe_compressed_ops;
|
pd->compress_ops = &sof_probe_compressed_ops;
|
||||||
#endif
|
#endif
|
||||||
pd->pcm_construct = sof_pcm_new;
|
pd->pcm_construct = sof_pcm_new;
|
||||||
|
|
|
@ -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
|
|
|
@ -538,11 +538,6 @@ int snd_sof_debugfs_add_region_item_iomem(struct snd_sof_dev *sdev,
|
||||||
enum snd_sof_fw_blk_type blk_type, u32 offset, size_t size,
|
enum snd_sof_fw_blk_type blk_type, u32 offset, size_t size,
|
||||||
const char *name, enum sof_debugfs_access_type access_type);
|
const char *name, enum sof_debugfs_access_type access_type);
|
||||||
|
|
||||||
/*
|
|
||||||
* Platform specific ops.
|
|
||||||
*/
|
|
||||||
extern struct snd_compress_ops sof_compressed_ops;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DSP Architectures.
|
* DSP Architectures.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -3,13 +3,46 @@
|
||||||
// This file is provided under a dual BSD/GPLv2 license. When using or
|
// This file is provided under a dual BSD/GPLv2 license. When using or
|
||||||
// redistributing this file, you may do so under either license.
|
// 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>
|
// Author: Cezary Rojewski <cezary.rojewski@intel.com>
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <sound/soc.h>
|
||||||
|
#include "ops.h"
|
||||||
#include "sof-priv.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
|
* sof_ipc_probe_init - initialize data probing
|
||||||
|
@ -25,8 +58,8 @@
|
||||||
* Probing is initialized only once and each INIT request must be
|
* Probing is initialized only once and each INIT request must be
|
||||||
* matched by DEINIT call.
|
* matched by DEINIT call.
|
||||||
*/
|
*/
|
||||||
int sof_ipc_probe_init(struct snd_sof_dev *sdev,
|
static int sof_ipc_probe_init(struct snd_sof_dev *sdev, u32 stream_tag,
|
||||||
u32 stream_tag, size_t buffer_size)
|
size_t buffer_size)
|
||||||
{
|
{
|
||||||
struct sof_ipc_probe_dma_add_params *msg;
|
struct sof_ipc_probe_dma_add_params *msg;
|
||||||
struct sof_ipc_reply reply;
|
struct sof_ipc_reply reply;
|
||||||
|
@ -47,7 +80,6 @@ int sof_ipc_probe_init(struct snd_sof_dev *sdev,
|
||||||
kfree(msg);
|
kfree(msg);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(sof_ipc_probe_init);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sof_ipc_probe_deinit - cleanup after data probing
|
* 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
|
* on DSP side once it is no longer needed. DEINIT only when there
|
||||||
* are no probes connected and with all injectors detached.
|
* 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_cmd_hdr msg;
|
||||||
struct sof_ipc_reply reply;
|
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,
|
return sof_ipc_tx_message(sdev->ipc, msg.cmd, &msg, msg.size,
|
||||||
&reply, sizeof(reply));
|
&reply, sizeof(reply));
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(sof_ipc_probe_deinit);
|
|
||||||
|
|
||||||
static int sof_ipc_probe_info(struct snd_sof_dev *sdev, unsigned int cmd,
|
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 msg = {{{0}}};
|
||||||
struct sof_ipc_probe_info_params *reply;
|
struct sof_ipc_probe_info_params *reply;
|
||||||
|
@ -112,97 +143,6 @@ exit:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
* sof_ipc_probe_points_info - retrieve list of active probe points
|
||||||
* @sdev: SOF sound device
|
* @sdev: SOF sound device
|
||||||
|
@ -214,7 +154,8 @@ EXPORT_SYMBOL(sof_ipc_probe_dma_remove);
|
||||||
* required.
|
* required.
|
||||||
*/
|
*/
|
||||||
int sof_ipc_probe_points_info(struct snd_sof_dev *sdev,
|
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,
|
return sof_ipc_probe_info(sdev, SOF_IPC_PROBE_POINT_INFO,
|
||||||
(void **)desc, num_desc);
|
(void **)desc, num_desc);
|
||||||
|
@ -235,7 +176,7 @@ EXPORT_SYMBOL(sof_ipc_probe_points_info);
|
||||||
* request when no longer needed.
|
* request when no longer needed.
|
||||||
*/
|
*/
|
||||||
int sof_ipc_probe_points_add(struct snd_sof_dev *sdev,
|
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_probe_point_add_params *msg;
|
||||||
struct sof_ipc_reply reply;
|
struct sof_ipc_reply reply;
|
||||||
|
@ -267,7 +208,7 @@ EXPORT_SYMBOL(sof_ipc_probe_points_add);
|
||||||
* points and frees all resources on DSP side.
|
* points and frees all resources on DSP side.
|
||||||
*/
|
*/
|
||||||
int sof_ipc_probe_points_remove(struct snd_sof_dev *sdev,
|
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_probe_point_remove_params *msg;
|
||||||
struct sof_ipc_reply reply;
|
struct sof_ipc_reply reply;
|
||||||
|
@ -288,3 +229,136 @@ int sof_ipc_probe_points_remove(struct snd_sof_dev *sdev,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(sof_ipc_probe_points_remove);
|
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);
|
|
@ -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
|
Загрузка…
Ссылка в новой задаче