1
0
Fork 0

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: 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>
alistair/sensors
Cezary Rojewski 2020-02-18 15:39:20 +01:00 committed by Mark Brown
parent f3b433e469
commit e145e9af23
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
7 changed files with 246 additions and 1 deletions

View File

@ -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.

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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)
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 */

View File

@ -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)

View File

@ -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 {
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;