[Sound-open-firmware] [PATCH v1 3/3] Passthrough component added

Liam Girdwood liam.r.girdwood at intel.com
Mon Sep 4 15:58:44 CEST 2017


On Mon, 2017-09-04 at 14:35 +0100, Ranjani Sridharan wrote:
> This patch adds a passthrough component that copies the input sample from
> the source buffer to the sink buffer. It is meant to serve as a template
> for creating new components.
> 
> Signed-off-by: Ranjani Sridharan <ranjani.sridharan at linux.intel.com>
> ---
>  src/audio/Makefile.am    |   3 +-
>  src/audio/passthrough.c  | 216 +++++++++++++++++++++++++++++++++++++++++++++++
>  src/include/reef/trace.h |   1 +
>  src/include/uapi/ipc.h   |   7 ++
>  4 files changed, 226 insertions(+), 1 deletion(-)
>  create mode 100644 src/audio/passthrough.c
> 
> diff --git a/src/audio/Makefile.am b/src/audio/Makefile.am
> index 285422e..c71430c 100644
> --- a/src/audio/Makefile.am
> +++ b/src/audio/Makefile.am
> @@ -17,7 +17,8 @@ libaudio_a_SOURCES = \
>  	pipeline.c \
>  	pipeline_static.c \
>  	component.c \
> -	buffer.c
> +	buffer.c \
> +	passthrough.c
>  
>  libaudio_a_CFLAGS = \
>  	$(ARCH_CFLAGS) \
> diff --git a/src/audio/passthrough.c b/src/audio/passthrough.c
> new file mode 100644
> index 0000000..1056a03
> --- /dev/null
> +++ b/src/audio/passthrough.c
> @@ -0,0 +1,216 @@
> +/*
> + * Copyright (c) 2016, Intel Corporation
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions are met:
> + *   * Redistributions of source code must retain the above copyright
> + *     notice, this list of conditions and the following disclaimer.
> + *   * Redistributions in binary form must reproduce the above copyright
> + *     notice, this list of conditions and the following disclaimer in the
> + *     documentation and/or other materials provided with the distribution.
> + *   * Neither the name of the Intel Corporation nor the
> + *     names of its contributors may be used to endorse or promote products
> + *     derived from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + *
> + * Author: Ranjani Sridharan <ranjani.sridharan at linux.intel.com>
> + */
> +
> +#include <stdio.h>
> +#include <stdint.h>
> +#include <stddef.h>
> +#include <reef/lock.h>
> +#include <reef/alloc.h>
> +#include <reef/list.h>
> +#include <reef/stream.h>
> +#include <reef/trace.h>
> +#include <reef/audio/component.h>
> +#include <reef/audio/pipeline.h>
> +#include <uapi/ipc.h>
> +
> +/* tracing */
> +#define trace_pass(__e)	trace_event(TRACE_CLASS_PASS, __e)
> +#define trace_pass_error(__e)   trace_error(TRACE_CLASS_PASS, __e)
> +#define tracev_pass(__e)        tracev_event(TRACE_CLASS_PASS, __e)
> +


Probably best to write a short description of that this comp does and
how it's intended as satrting point and template for other components.

> +/*
> + * passthrough_comp_data structure
> + *	passthrough_func - function that performs the routing of input buffer
> + *			 to the output buffer based on config
> + */
> +struct passthrough_comp_data {
> +	int (*passthrough_func)(struct comp_dev *dev, struct comp_buffer *sink,
> +		struct comp_buffer *source, uint32_t frames);
> +
> +};


> +
> +/* passthrough function to copy data from source to sink buffer */
> +static int passthrough_function(struct comp_dev *dev,
> +	struct comp_buffer *sink_buffer,
> +	struct comp_buffer *source_buffer, uint32_t frames)
> +{
> +	struct sof_ipc_comp_config *config = COMP_GET_CONFIG(dev);
> +	int32_t *src = (int32_t *) source_buffer->r_ptr;
> +	int32_t *dest = (int32_t *) sink_buffer->w_ptr;
> +	int nch = dev->params.channels;
> +	int ret = 0;
> +
> +	/* copy frames from source to destination */
> +	switch (config->frame_fmt) {
> +	case SOF_IPC_FRAME_S16_LE:
> +		memcpy(dest, src, frames * nch * sizeof(int16_t));
> +		break;
> +	case SOF_IPC_FRAME_S32_LE:
> +	case SOF_IPC_FRAME_S24_4LE:
> +	case SOF_IPC_FRAME_FLOAT:
> +		memcpy(dest, src, frames * nch * sizeof(int32_t));
> +		break;
> +	default:
> +		trace_pass_error("PTp");

same issues as with mux here.

> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +static struct comp_dev *passthrough_new(struct sof_ipc_comp *comp)
> +{
> +	struct comp_dev *dev;
> +	struct passthrough_comp_data *cd;
> +
> +	trace_pass("PTn");
> +	dev = rzalloc(RZONE_RUNTIME, RFLAGS_NONE,
> +		COMP_SIZE(struct sof_ipc_comp_passthrough));
> +	if (dev == NULL)
> +		return NULL;
> +
> +	memcpy(&dev->comp, comp, sizeof(struct sof_ipc_comp_passthrough));
> +
> +	cd = rzalloc(RZONE_RUNTIME, RFLAGS_NONE, sizeof(*cd));
> +	if (cd == NULL) {
> +		rfree(dev);
> +		return NULL;
> +	}
> +
> +	comp_set_drvdata(dev, cd);
> +	cd->passthrough_func = passthrough_function;
> +

Can you be verbose with comments throughout this file since it will be a
template too.

> +	return dev;
> +}
> +
> +static void passthrough_free(struct comp_dev *dev)
> +{
> +	struct passthrough_comp_data *cd = comp_get_drvdata(dev);
> +
> +	rfree(cd);
> +	rfree(dev);
> +}
> +
> +/* set component audio stream parameters */
> +static int passthrough_params(struct comp_dev *dev)
> +{
> +	return 0;
> +}
> +
> +/* used to pass standard and bespoke commands (with data) to component */
> +static int passthrough_cmd(struct comp_dev *dev, int cmd, void *data)
> +{
> +	int ret = 0;
> +
> +	switch (cmd) {
> +	case COMP_CMD_START:
> +	case COMP_CMD_STOP:
> +	case COMP_CMD_PAUSE:
> +	case COMP_CMD_RELEASE:
> +	default:
> +		ret = comp_set_state(dev, cmd);
> +		break;
> +	}
> +

> +	return ret;
> +}
> +
> +/* copy and process stream data from source to sink buffers */
> +static int passthrough_copy(struct comp_dev *dev)
> +{
> +	struct passthrough_comp_data *cd = comp_get_drvdata(dev);
> +	struct comp_buffer *source_buffer = NULL, *sink_buffer = NULL;
> +	uint32_t copy_bytes;
> +
> +	/* get source and sink buffers */
> +	source_buffer = list_first_item(&dev->bsource_list, struct comp_buffer,
> +		sink_list);
> +	sink_buffer = list_first_item(&dev->bsink_list, struct comp_buffer,
> +		source_list);
> +
> +	/* check that source has enough frames available and sink enough
> +	 * frames free
> +	 */
> +	copy_bytes = comp_buffer_get_copy_bytes(dev, source_buffer,
> +			sink_buffer);
> +
> +	if (copy_bytes < dev->frames * dev->frame_bytes) {
> +		trace_pass_error("PTc");
> +		return -EINVAL;
> +	}
> +
> +	/* Run passthrough if buffers have enough room */
> +	cd->passthrough_func(dev, sink_buffer, source_buffer, dev->frames);
> +
> +	comp_update_buffer_consume(source_buffer,
> +		dev->params.host_period_bytes);
> +	comp_update_buffer_produce(sink_buffer, dev->params.host_period_bytes);
> +
> +	return 0;
> +}
> +
> +static int passthrough_preload(struct comp_dev *dev)
> +{
> +	return passthrough_copy(dev);
> +}
> +
> +static int passthrough_reset(struct comp_dev *dev)
> +{
> +	trace_pass("PTe");
> +	dev->state = COMP_STATE_INIT;
> +	return 0;
> +}
> +
> +static int passthrough_prepare(struct comp_dev *dev)
> +{
> +	trace_pass("PTl");
> +	dev->state = COMP_STATE_PREPARE;
> +	return 0;
> +}
> +
> +struct comp_driver comp_passthrough = {
> +	.type	= SOF_COMP_PASSTHROUGH,
> +	.ops	= {
> +		.new		= passthrough_new,
> +		.free		= passthrough_free,
> +		.params		= passthrough_params,
> +		.cmd		= passthrough_cmd,
> +		.copy		= passthrough_copy,
> +		.prepare	= passthrough_prepare,
> +		.reset		= passthrough_reset,
> +		.preload	= passthrough_preload,
> +	},
> +};
> +
> +void sys_comp_passthrough_init(void)
> +{
> +	comp_register(&comp_passthrough);
> +}
> diff --git a/src/include/reef/trace.h b/src/include/reef/trace.h
> index 300e8d8..b7ec31a 100644
> --- a/src/include/reef/trace.h
> +++ b/src/include/reef/trace.h
> @@ -87,6 +87,7 @@
>  #define TRACE_CLASS_TONE        (18 << 24)
>  #define TRACE_CLASS_EQ_FIR      (19 << 24)
>  #define TRACE_CLASS_EQ_IIR      (20 << 24)
> +#define TRACE_CLASS_PASS	(21 << 24)
>  
>  /* move to config.h */
>  #define TRACE	1
> diff --git a/src/include/uapi/ipc.h b/src/include/uapi/ipc.h
> index e0d0303..cb79e26 100644
> --- a/src/include/uapi/ipc.h
> +++ b/src/include/uapi/ipc.h
> @@ -474,6 +474,7 @@ enum sof_comp_type {
>  	SOF_COMP_EQ_FIR,
>          SOF_COMP_FILEREAD,	/* host test based file IO */
>          SOF_COMP_FILEWRITE,	/* host test based file IO */
> +	SOF_COMP_PASSTHROUGH,
>  };
>  
>  /* XRUN action for component */
> @@ -573,6 +574,12 @@ struct sof_ipc_comp_mux {
>  	struct sof_ipc_comp_config config;
>  } __attribute__((packed));
>  
> +/* generic passthrough component */
> +struct sof_ipc_comp_passthrough {
> +	struct sof_ipc_comp comp;
> +	struct sof_ipc_comp_config config;
> +} __attribute__((packed));
> +
>  /* generic tone generator component */
>  struct sof_ipc_comp_tone {
>  	struct sof_ipc_comp comp;


---------------------------------------------------------------------
Intel Corporation (UK) Limited
Registered No. 1134945 (England)
Registered Office: Pipers Way, Swindon SN3 1RJ
VAT No: 860 2173 47

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.


More information about the Sound-open-firmware mailing list