Commit e145e9af authored by Cezary Rojewski's avatar Cezary Rojewski Committed by Mark Brown

ASoC: SOF: Generic probe compress operations

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: default avatarCezary Rojewski <cezary.rojewski@intel.com>
Acked-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20200218143924.10565-6-cezary.rojewski@intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent f3b433e4
...@@ -43,6 +43,7 @@ config SND_SOC_SOF_OF ...@@ -43,6 +43,7 @@ config SND_SOC_SOF_OF
config SND_SOC_SOF_DEBUG_PROBES config SND_SOC_SOF_DEBUG_PROBES
bool "SOF enable data probing" bool "SOF enable data probing"
select SND_SOC_COMPRESS
help help
This option enables the data probing feature that can be used to This option enables the data probing feature that can be used to
gather data directly from specific points of the audio pipeline. gather data directly from specific points of the audio pipeline.
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
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 snd-sof-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += probe.o compress.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
......
// 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);
/* 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
...@@ -14,6 +14,9 @@ ...@@ -14,6 +14,9 @@
#include <sound/sof.h> #include <sound/sof.h>
#include "sof-priv.h" #include "sof-priv.h"
#include "ops.h" #include "ops.h"
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
#include "probe.h"
#endif
/* see SOF_DBG_ flags */ /* see SOF_DBG_ flags */
int sof_core_debug; int sof_core_debug;
...@@ -292,6 +295,9 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) ...@@ -292,6 +295,9 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
sdev->pdata = plat_data; sdev->pdata = plat_data;
sdev->first_boot = true; sdev->first_boot = true;
sdev->fw_state = SOF_FW_BOOT_NOT_STARTED; 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); dev_set_drvdata(dev, sdev);
/* check all mandatory ops */ /* check all mandatory ops */
......
...@@ -393,6 +393,49 @@ snd_sof_pcm_platform_pointer(struct snd_sof_dev *sdev, ...@@ -393,6 +393,49 @@ snd_sof_pcm_platform_pointer(struct snd_sof_dev *sdev,
return 0; 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 */ /* machine driver */
static inline int static inline int
snd_sof_machine_register(struct snd_sof_dev *sdev, void *pdata) snd_sof_machine_register(struct snd_sof_dev *sdev, void *pdata)
......
...@@ -170,6 +170,27 @@ struct snd_sof_dsp_ops { ...@@ -170,6 +170,27 @@ struct snd_sof_dsp_ops {
snd_pcm_uframes_t (*pcm_pointer)(struct snd_sof_dev *sdev, snd_pcm_uframes_t (*pcm_pointer)(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream); /* optional */ 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 */ /* host read DSP stream data */
void (*ipc_msg_data)(struct snd_sof_dev *sdev, void (*ipc_msg_data)(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream, struct snd_pcm_substream *substream,
...@@ -405,6 +426,10 @@ struct snd_sof_dev { ...@@ -405,6 +426,10 @@ struct snd_sof_dev {
wait_queue_head_t waitq; wait_queue_head_t waitq;
int code_loading; int code_loading;
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
unsigned int extractor_stream_tag;
#endif
/* DMA for Trace */ /* DMA for Trace */
struct snd_dma_buffer dmatb; struct snd_dma_buffer dmatb;
struct snd_dma_buffer dmatp; struct snd_dma_buffer dmatp;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment