On Thu, 2018-05-31 at 19:29 -0700, Ranjani Sridharan wrote:
This patch adds the common header and source files required for all component testbench. These files include routines for parsing topology files, initializing sof ipc, scheduler, memory allocation and pipeline structures. It also provides simpler implementations for some of the SOF features such as tracing.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com
src/host/Makefile.am | 19 + src/host/alloc.c | 63 +++ src/host/common_test.c | 206 +++++++ src/host/ipc.c | 81 +++ src/host/schedule.c | 98 ++++ src/host/topology.c | 954 +++++++++++++++++++++++++++++++++ src/host/trace.c | 181 +++++++ src/include/host/common_test.h | 65 +++ src/include/host/topology.h | 202 +++++++ src/include/host/trace.h | 49 ++ 10 files changed, 1918 insertions(+) create mode 100644 src/host/Makefile.am create mode 100644 src/host/alloc.c create mode 100644 src/host/common_test.c create mode 100644 src/host/ipc.c create mode 100644 src/host/schedule.c create mode 100644 src/host/topology.c create mode 100644 src/host/trace.c create mode 100644 src/include/host/common_test.h create mode 100644 src/include/host/topology.h create mode 100644 src/include/host/trace.h
diff --git a/src/host/Makefile.am b/src/host/Makefile.am new file mode 100644 index 0000000..a1044a5 --- /dev/null +++ b/src/host/Makefile.am @@ -0,0 +1,19 @@ +AUTOMAKE_OPTIONS = subdir-objects
+SOF_INC = $(prefix)/include/sof +DEFINE = -DSOF_INC="$(SOF_INC)"
+AM_CPPFLAGS = -I $(SOF_INC) $(SOF_INCDIR) $(DEFINE) +AM_CFLAGS = -g -Wall +AM_LDFLAGS = -L$(prefix)/lib
+noinst_LIBRARIES = libtb_common.a
+libtb_common_a_SOURCES = \
- common_test.c \
- topology.c \
- file.c \
- trace.c \
- ipc.c \
- schedule.c \
- alloc.c
diff --git a/src/host/alloc.c b/src/host/alloc.c new file mode 100644 index 0000000..beda37c --- /dev/null +++ b/src/host/alloc.c @@ -0,0 +1,63 @@ +/*
- Copyright (c) 2018, 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: Seppo Ingalsuo seppo.ingalsuo@linux.intel.com
Liam Girdwood <liam.r.girdwood@linux.intel.com>
Keyon Jie <yang.jie@linux.intel.com>
Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
- */
+#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <sof/alloc.h> +#include "host/common_test.h"
+/* testbench mem alloc definition */
+void *rmalloc(int zone, uint32_t caps, size_t bytes) +{
- return malloc(bytes);
+}
+void *rzalloc(int zone, uint32_t caps, size_t bytes) +{
- void *x;
- x = calloc(1, bytes);
- return x;
+}
Can't we just
return calloc(1, bytes); ?
+void rfree(void *ptr) +{
- free(ptr);
+}
+void *rballoc(int zone, uint32_t caps, size_t bytes) +{
- return malloc(bytes);
+} diff --git a/src/host/common_test.c b/src/host/common_test.c new file mode 100644 index 0000000..e286883 --- /dev/null +++ b/src/host/common_test.c @@ -0,0 +1,206 @@ +/*
- Copyright (c) 2018, 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(s): Seppo Ingalsuo seppo.ingalsuo@linux.intel.com
Liam Girdwood <liam.r.girdwood@linux.intel.com>
Keyon Jie <yang.jie@linux.intel.com>
Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
- */
+#include <stdint.h> +#include <stddef.h> +#include <time.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <sof/task.h> +#include <sof/alloc.h> +#include <sof/ipc.h> +#include <sof/dai.h> +#include <sof/dma.h> +#include <sof/work.h> +#include <sof/wait.h> +#include <sof/intel-ipc.h> +#include <sof/audio/pipeline.h> +#include "host/common_test.h" +#include "host/topology.h"
+/* print debug messages */ +void debug_print(char *message) +{
- if (debug)
printf("debug: %s", message);
+}
+/* testbench helper functions for pipeline setup and trigger */
+int tb_pipeline_setup(struct sof *sof) +{
- /* init components */
- sys_comp_init();
- /* init IPC */
- if (ipc_init(sof) < 0) {
fprintf(stderr, "error: IPC init\n");
return -EINVAL;
- }
errors should be handled like :-
err = func(val); if (err < 0) { fprintf(stderr, "error: blah %d\n", err); return err; }
This will need to be changed for all similar code like the above, otherwise we lose the error value and re-write it.
- /* init scheduler */
- if (scheduler_init(sof) < 0) {
fprintf(stderr, "error: scheduler init\n");
return -EINVAL;
- }
- debug_print("ipc and scheduler initialized\n");
- return 0;
+}
+/* set up pcm params, prepare and trigger pipeline */ +int tb_pipeline_start(struct ipc *ipc, int nch, char *bits_in,
struct sof_ipc_pipe_new *ipc_pipe)
+{
- struct ipc_comp_dev *pcm_dev;
- struct pipeline *p;
- struct comp_dev *cd;
- int ret;
- /* set up pipeline params */
- ret = tb_pipeline_params(ipc, nch, bits_in, ipc_pipe);
- if (ret < 0) {
fprintf(stderr, "error: pipeline params\n");
return -EINVAL;
- }
- /* Get IPC component device for pipeline */
- pcm_dev = ipc_get_comp(ipc, ipc_pipe->sched_id);
- if (!pcm_dev) {
fprintf(stderr, "error: ipc get comp\n");
return -EINVAL;
- }
- /* Point to pipeline */
- cd = pcm_dev->cd;
- p = pcm_dev->cd->pipeline;
- /* Component prepare */
- ret = pipeline_prepare(p, cd);
- /* Start the pipeline */
- ret = pipeline_trigger(p, cd, COMP_TRIGGER_START);
- if (ret < 0)
printf("Warning: Failed start pipeline command.\n");
- return ret;
+}
+/* pipeline pcm params */ +int tb_pipeline_params(struct ipc *ipc, int nch, char *bits_in,
struct sof_ipc_pipe_new *ipc_pipe)
+{
- int fs_period, ret = 0;
- struct ipc_comp_dev *pcm_dev;
- struct pipeline *p;
- struct comp_dev *cd;
- struct sof_ipc_pcm_params params;
- int fs, deadline;
- char message[DEBUG_MSG_LEN];
- deadline = ipc_pipe->deadline;
- fs = deadline * ipc_pipe->frames_per_sched;
- /* Compute period from sample rates */
- fs_period = (int)(0.9999 + fs * deadline / 1e6);
- sprintf(message, "period sample count %d\n", fs_period);
- debug_print(message);
- /* set pcm params */
- params.comp_id = ipc_pipe->comp_id;
- params.params.buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED;
- params.params.frame_fmt = find_format(bits_in);
- params.params.direction = SOF_IPC_STREAM_PLAYBACK;
- params.params.rate = fs;
- params.params.channels = nch;
- switch (params.params.frame_fmt) {
- case(SOF_IPC_FRAME_S16_LE):
params.params.sample_container_bytes = 2;
best to use sizeof(uint16_t) here and below.
params.params.sample_valid_bytes = 2;
params.params.host_period_bytes = fs_period * nch *
params.params.sample_container_bytes;
break;
- case(SOF_IPC_FRAME_S24_4LE):
params.params.sample_container_bytes = 4;
params.params.sample_valid_bytes = 3;
params.params.host_period_bytes = fs_period * nch *
params.params.sample_container_bytes;
break;
- case(SOF_IPC_FRAME_S32_LE):
params.params.sample_container_bytes = 4;
params.params.sample_valid_bytes = 4;
params.params.host_period_bytes = fs_period * nch *
params.params.sample_container_bytes;
break;
- default:
fprintf(stderr, "error: invalid frame format\n");
return -EINVAL;
- }
- /* get scheduling component device for pipeline*/
- pcm_dev = ipc_get_comp(ipc, ipc_pipe->sched_id);
- if (!pcm_dev) {
fprintf(stderr, "error: ipc get comp\n");
return -EINVAL;
- }
- /* point to pipeline */
- cd = pcm_dev->cd;
- p = pcm_dev->cd->pipeline;
- if (!p) {
fprintf(stderr, "error: pipeline NULL\n");
return -EINVAL;
- }
- /* pipeline params */
- ret = pipeline_params(p, cd, ¶ms);
- if (ret < 0)
fprintf(stderr, "error: pipeline_params\n");
- return ret;
+}
+/* The following definitions are to satisfy libsof linker errors */
+struct dai *dai_get(uint32_t type, uint32_t index) +{
- return NULL;
+}
+struct dma *dma_get(int dmac_id) +{
- return NULL;
+} diff --git a/src/host/ipc.c b/src/host/ipc.c new file mode 100644 index 0000000..0cbb61a --- /dev/null +++ b/src/host/ipc.c @@ -0,0 +1,81 @@ +/*
- Copyright (c) 2018, 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: Seppo Ingalsuo seppo.ingalsuo@linux.intel.com
Liam Girdwood <liam.r.girdwood@linux.intel.com>
Keyon Jie <yang.jie@linux.intel.com>
Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
- */
+#include <sof/ipc.h> +#include <sof/intel-ipc.h>
+/* testbench ipc */ +struct ipc *_ipc;
+int platform_ipc_init(struct ipc *ipc) +{
- struct intel_ipc_data *iipc;
- int i;
- _ipc = ipc;
- /* init ipc data */
- iipc = malloc(sizeof(struct intel_ipc_data));
- ipc_set_drvdata(_ipc, iipc);
- _ipc->dsp_msg = NULL;
- list_init(&ipc->empty_list);
- list_init(&ipc->msg_list);
- spinlock_init(&ipc->lock);
- for (i = 0; i < MSG_QUEUE_SIZE; i++)
list_item_prepend(&ipc->message[i].list, &ipc->empty_list);
- /* allocate page table buffer */
- iipc->page_table = malloc(HOST_PAGE_SIZE);
- if (iipc->page_table)
bzero(iipc->page_table, HOST_PAGE_SIZE);
- /* PM */
- iipc->pm_prepare_D3 = 0;
- return 0;
+}
+/* The following definitions are to satisfy libsof linker errors */
+int ipc_stream_send_position(struct comp_dev *cdev,
struct sof_ipc_stream_posn *posn)
+{
- return 0;
+}
+int ipc_stream_send_xrun(struct comp_dev *cdev,
struct sof_ipc_stream_posn *posn)
+{
Should we have some printf logging here ?
- return 0;
+} diff --git a/src/host/schedule.c b/src/host/schedule.c new file mode 100644 index 0000000..614a2b6 --- /dev/null +++ b/src/host/schedule.c @@ -0,0 +1,98 @@ +/*
- Copyright (c) 2018, 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: Seppo Ingalsuo seppo.ingalsuo@linux.intel.com
Liam Girdwood <liam.r.girdwood@linux.intel.com>
Keyon Jie <yang.jie@linux.intel.com>
Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
- */
+#include <sof/audio/component.h> +#include <sof/task.h> +#include <stdint.h> +#include <sof/wait.h>
+/* scheduler testbench definition */
+struct schedule_data {
- spinlock_t lock;
- struct list_item list; /* list of tasks in priority queue */
- uint32_t clock;
+};
+static struct schedule_data *sch;
+void schedule_task_complete(struct task *task) +{
- list_item_del(&task->list);
- task->state = TASK_STATE_COMPLETED;
+}
+/* schedule task */ +void schedule_task(struct task *task, uint64_t start, uint64_t deadline) +{
- task->deadline = deadline;
- list_item_prepend(&task->list, &sch->list);
- task->state = TASK_STATE_QUEUED;
- if (task->func)
task->func(task->data);
- schedule_task_complete(task);
+}
+/* initialize scheduler */ +int scheduler_init(struct sof *sof) +{
- trace_pipe("ScI");
- sch = malloc(sizeof(*sch));
- list_init(&sch->list);
- spinlock_init(&sch->lock);
- return 0;
+}
+/* The following definitions are to satisfy libsof linker errors */
+void schedule(void) +{ +}
+void schedule_task_idle(struct task *task, uint64_t deadline) +{ +}
+/* testbench work definition */
+void work_schedule_default(struct work *w, uint64_t timeout) +{ +}
+void work_cancel_default(struct work *work) +{ +} diff --git a/src/host/topology.c b/src/host/topology.c new file mode 100644 index 0000000..46f7e66 --- /dev/null +++ b/src/host/topology.c @@ -0,0 +1,954 @@ +/*
- Copyright (c) 2018, 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@linux.intel.com
Liam Girdwood <liam.r.girdwood@linux.intel.com>
- */
+/*
- Topology parser to parse topology bin file
- and set up components and pipeline
- */
+#include <sof/ipc.h> +#include <stdio.h> +#include <string.h> +#include <dlfcn.h> +#include <sof/audio/component.h> +#include "host/topology.h" +#include "host/file.h"
+char *input_file; +char *output_file; +void *volume_lib; +FILE *file; +char pipeline_string[DEBUG_MSG_LEN];
+/*
- Register component driver
- Only needed once per component type
- */
+static void register_comp(int comp_type) +{
- static int pga_reg;
- static int file_reg;
You should use a structure here and pass it in to your function.
- switch (comp_type) {
- case SND_SOC_TPLG_DAPM_PGA:
/* register comp driver if not already registered */
if (!pga_reg) {
debug_print("register pga comp driver\n");
/* register volume driver */
void (*sys_comp_volume_init)() =
(void (*)(void))dlsym(volume_lib,
"sys_comp_volume_init")
;
This string could be constructed "sys_comp_" + type + "_init", where type could be passed in from cmd line.
sys_comp_volume_init();
pga_reg = 1;
}
break;
- case SND_SOC_TPLG_DAPM_DAI_IN:
- case SND_SOC_TPLG_DAPM_AIF_IN:
/* register comp driver if not already registered */
if (!file_reg) {
debug_print("register file comp driver\n");
/* register file driver */
sys_comp_file_init();
file_reg = 1;
}
break;
- default:
break;
- }
+}
+/* read vendor tuples array from topology */ +static int read_array(struct snd_soc_tplg_vendor_array *array) +{
- struct snd_soc_tplg_vendor_uuid_elem uuid;
- struct snd_soc_tplg_vendor_string_elem string;
- struct snd_soc_tplg_vendor_value_elem value;
- int j, ret = 0;
- size_t size;
- switch (array->type) {
- case SND_SOC_TPLG_TUPLE_TYPE_UUID:
/* copy uuid elems into array */
for (j = 0; j < array->num_elems; j++) {
size = sizeof(struct snd_soc_tplg_vendor_uuid_elem);
ret = fread(&uuid, size, 1, file);
if (ret != 1)
return -EINVAL;
memcpy(&array->uuid[j], &uuid, size);
}
break;
- case SND_SOC_TPLG_TUPLE_TYPE_STRING:
/* copy string elems into array */
for (j = 0; j < array->num_elems; j++) {
size = sizeof(struct
snd_soc_tplg_vendor_string_elem);
ret = fread(&string, size, 1, file);
if (ret != 1)
return -EINVAL;
memcpy(&array->string[j], &string, size);
}
break;
- case SND_SOC_TPLG_TUPLE_TYPE_BOOL:
- case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
- case SND_SOC_TPLG_TUPLE_TYPE_WORD:
- case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
/* copy value elems into array */
for (j = 0; j < array->num_elems; j++) {
size = sizeof(struct snd_soc_tplg_vendor_value_elem);
ret = fread(&value, size, 1, file);
if (ret != 1)
return -EINVAL;
memcpy(&array->value[j], &value, size);
}
break;
- default:
printf("error: unknown token type %d\n", array->type);
return -EINVAL;
- }
- return 0;
+}
+/* load pipeline graph DAPM widget*/ +static int load_graph(struct sof *sof, struct comp_info *temp_comp_list,
int count, int num_comps, int pipeline_id)
+{
- struct sof_ipc_pipe_comp_connect connection;
- struct snd_soc_tplg_dapm_graph_elem *graph_elem;
- size_t size;
- int i, j, ret = 0;
- /* allocate memory for graph elem */
- size = sizeof(struct snd_soc_tplg_dapm_graph_elem);
- graph_elem = (struct snd_soc_tplg_dapm_graph_elem *)malloc(size);
- if (!graph_elem) {
printf("error: mem alloc\n");
return -EINVAL;
- }
- /* set up component connections */
- connection.source_id = -1;
- connection.sink_id = -1;
- for (i = 0; i < count; i++) {
size = sizeof(struct snd_soc_tplg_dapm_graph_elem);
ret = fread(graph_elem, size, 1, file);
if (ret != 1)
return -EINVAL;
Always best to get and print errno for any failed file IO ops. Will need to be done in multiple places.
/* look up component id from the component list */
for (j = 0; j < num_comps; j++) {
if (strcmp(temp_comp_list[j].name,
graph_elem->source) == 0)
connection.source_id = temp_comp_list[j].id;
if (strcmp(temp_comp_list[j].name,
graph_elem->sink) == 0)
connection.sink_id = temp_comp_list[j].id;
}
strcat(pipeline_string, graph_elem->source);
strcat(pipeline_string, "->");
if (i == (count - 1))
strcat(pipeline_string, graph_elem->sink);
/* connect source and sink */
if (connection.source_id != -1 && connection.sink_id != -1)
if (ipc_comp_connect(sof->ipc, &connection) < 0) {
fprintf(stderr, "error: comp connect\n");
return -EINVAL;
}
- }
- /* pipeline complete after pipeline connections are established */
- for (i = 0; i < num_comps; i++) {
if (temp_comp_list[i].pipeline_id == pipeline_id &&
temp_comp_list[i].type == SND_SOC_TPLG_DAPM_SCHEDULER)
ipc_pipeline_complete(sof->ipc,
temp_comp_list[i].id);
- }
- free(graph_elem);
- return 0;
+}
+/* load buffer DAPM widget */ +static int load_buffer(struct sof *sof, int comp_id, int pipeline_id, int size) +{
- struct sof_ipc_buffer buffer;
- struct snd_soc_tplg_vendor_array *array = NULL;
- int ret = 0;
- /* configure buffer */
- buffer.comp.id = comp_id;
- buffer.comp.pipeline_id = pipeline_id;
- /* allocate memory for vendor tuple array */
- array = (struct snd_soc_tplg_vendor_array *)malloc(size);
- ret = fread(array, sizeof(struct snd_soc_tplg_vendor_array), 1,
file);
- if (ret != 1)
return -EINVAL;
- read_array(array);
- /* parse buffer tokens */
- ret = sof_parse_tokens(&buffer, buffer_tokens,
ARRAY_SIZE(buffer_tokens), array,
size);
- /* create buffer component */
- if (ipc_buffer_new(sof->ipc, &buffer) < 0) {
fprintf(stderr, "error: buffer new\n");
return -EINVAL;
- }
- free(array);
- return 0;
+}
+/* load fileread component */ +static int load_fileread(struct sof *sof, int comp_id, int pipeline_id,
int size, char *bits_in, int *fr_id, int *sched_id)
+{
- struct sof_ipc_comp_file fileread;
- struct snd_soc_tplg_vendor_array *array = NULL;
- size_t total_array_size = 0, read_size;
- int ret = 0;
- fileread.config.frame_fmt = find_format(bits_in);
- /* allocate memory for vendor tuple array */
- array = (struct snd_soc_tplg_vendor_array *)malloc(size);
- if (!array) {
printf("error: mem alloc\n");
return -EINVAL;
- }
- /* read vendor tokens */
- while (total_array_size < size) {
read_size = sizeof(struct snd_soc_tplg_vendor_array);
ret = fread(array, read_size, 1, file);
if (ret != 1)
return -EINVAL;
read_array(array);
/* parse comp tokens */
ret = sof_parse_tokens(&fileread.config, comp_tokens,
ARRAY_SIZE(comp_tokens), array,
array->size);
if (ret != 0) {
printf("error: parse fileread tokens %d\n", size);
return -EINVAL;
}
total_array_size += array->size;
- }
- /* configure fileread */
- fileread.fn = strdup(input_file);
- fileread.mode = FILE_READ;
- fileread.comp.id = comp_id;
- /* use fileread comp as scheduling comp */
- *fr_id = *sched_id = comp_id;
- fileread.comp.hdr.size = sizeof(struct sof_ipc_comp_file);
- fileread.comp.type = SOF_COMP_FILEREAD;
- fileread.comp.pipeline_id = pipeline_id;
- /* create fileread component */
- if (ipc_comp_new(sof->ipc, (struct sof_ipc_comp *)&fileread) < 0) {
fprintf(stderr, "error: comp register\n");
return -EINVAL;
- }
- free(array);
- free(fileread.fn);
- return 0;
+}
+/* load filewrite component */ +static int load_filewrite(struct sof *sof, int comp_id, int pipeline_id,
int size, int *fw_id)
+{
- struct sof_ipc_comp_file filewrite;
- struct snd_soc_tplg_vendor_array *array = NULL;
- size_t total_array_size = 0, read_size;
- int ret = 0;
- /* allocate memory for vendor tuple array */
- array = (struct snd_soc_tplg_vendor_array *)malloc(size);
- if (!array) {
printf("error: mem alloc\n");
return -EINVAL;
- }
- /* read vendor tokens */
- while (total_array_size < size) {
read_size = sizeof(struct snd_soc_tplg_vendor_array);
ret = fread(array, read_size, 1, file);
if (ret != 1)
return -EINVAL;
read_array(array);
/* parse comp tokens */
ret = sof_parse_tokens(&filewrite.config, comp_tokens,
ARRAY_SIZE(comp_tokens), array,
array->size);
if (ret != 0) {
printf("error: parse filewrite tokens %d\n", size);
return -EINVAL;
}
total_array_size += array->size;
- }
- /* configure filewrite */
- filewrite.fn = strdup(output_file);
- filewrite.comp.id = comp_id;
- filewrite.mode = FILE_WRITE;
- *fw_id = comp_id;
- filewrite.comp.hdr.size = sizeof(struct sof_ipc_comp_file);
- filewrite.comp.type = SOF_COMP_FILEREAD;
- filewrite.comp.pipeline_id = pipeline_id;
- /* create filewrite component */
- if (ipc_comp_new(sof->ipc, (struct sof_ipc_comp *)&filewrite) < 0) {
fprintf(stderr, "error: comp register\n");
return -EINVAL;
free resources here ? and above, likewise for fileread.
- }
- free(array);
- free(filewrite.fn);
- return 0;
+}
+/* load pda dapm widget */ +static int load_pga(struct sof *sof, int comp_id, int pipeline_id,
int size)
+{
- struct sof_ipc_comp_volume volume;
- struct snd_soc_tplg_vendor_array *array = NULL;
- size_t total_array_size = 0, read_size;
- int ret = 0;
- /* allocate memory for vendor tuple array */
- array = (struct snd_soc_tplg_vendor_array *)malloc(size);
- if (!array) {
printf("error: mem alloc\n");
return -EINVAL;
- }
- /* read vendor tokens */
- while (total_array_size < size) {
read_size = sizeof(struct snd_soc_tplg_vendor_array);
ret = fread(array, read_size, 1, file);
if (ret != 1)
return -EINVAL;
read_array(array);
/* parse volume tokens */
ret = sof_parse_tokens(&volume.config, comp_tokens,
ARRAY_SIZE(comp_tokens), array,
array->size);
if (ret != 0) {
printf("error: parse pga tokens %d\n", size);
stderr
return -EINVAL;
please dont re-write the error value.
}
total_array_size += array->size;
- }
- /* configure volume */
- volume.comp.id = comp_id;
- volume.comp.hdr.size = sizeof(struct sof_ipc_comp_volume);
- volume.comp.type = SOF_COMP_VOLUME;
- volume.comp.pipeline_id = pipeline_id;
- /* load volume component */
- if (ipc_comp_new(sof->ipc, (struct sof_ipc_comp *)&volume) < 0) {
fprintf(stderr, "error: comp register\n");
return -EINVAL;
free array
- }
- free(array);
- return 0;
+}
+/* load scheduler dapm widget */ +static int load_pipeline(struct sof *sof, struct sof_ipc_pipe_new *pipeline,
int comp_id, int pipeline_id, int size, int
*sched_id) +{
- struct snd_soc_tplg_vendor_array *array = NULL;
- size_t total_array_size = 0, read_size;
- int ret = 0;
- /* configure pipeline */
- pipeline->sched_id = *sched_id;
- pipeline->comp_id = comp_id;
- pipeline->pipeline_id = pipeline_id;
- /* allocate memory for vendor tuple array */
- array = (struct snd_soc_tplg_vendor_array *)malloc(size);
- if (!array) {
printf("error: mem alloc\n");
return -EINVAL;
- }
- /* read vendor arrays */
- while (total_array_size < size) {
read_size = sizeof(struct snd_soc_tplg_vendor_array);
ret = fread(array, read_size, 1, file);
if (ret != 1)
return -EINVAL;
ret = read_array(array);
if (ret < 0)
return -EINVAL;
/* parse scheduler tokens */
ret = sof_parse_tokens(pipeline, sched_tokens,
ARRAY_SIZE(sched_tokens), array,
array->size);
if (ret != 0) {
printf("error: parse pipeline tokens %d\n", size);
return -EINVAL;
}
total_array_size += array->size;
- }
- /* Create pipeline */
- if (ipc_pipeline_new(sof->ipc, pipeline) < 0) {
fprintf(stderr, "error: pipeline new\n");
return -EINVAL;
- }
- free(array);
- return 0;
+}
+/* load dapm widget kcontrols
- we dont use controls in the testbench atm.
- so just skip to the next dapm widget
- */
+static int load_controls(struct sof *sof, int num_kcontrols) +{
- struct snd_soc_tplg_ctl_hdr *ctl_hdr;
- struct snd_soc_tplg_mixer_control *mixer_ctl;
- struct snd_soc_tplg_enum_control *enum_ctl;
- struct snd_soc_tplg_bytes_control *bytes_ctl;
- size_t read_size, size;
- int j, ret = 0;
- /* allocate memory */
- size = sizeof(struct snd_soc_tplg_ctl_hdr);
- ctl_hdr = (struct snd_soc_tplg_ctl_hdr *)malloc(size);
- if (!ctl_hdr) {
printf("error: mem alloc\n");
return -EINVAL;
-ENOMEM for all memory allocation failures.
- }
- size = sizeof(struct snd_soc_tplg_mixer_control);
- mixer_ctl = (struct snd_soc_tplg_mixer_control *)malloc(size);
- if (!mixer_ctl) {
printf("error: mem alloc\n");
return -EINVAL;
- }
- size = sizeof(struct snd_soc_tplg_enum_control);
- enum_ctl = (struct snd_soc_tplg_enum_control *)malloc(size);
- if (!enum_ctl) {
printf("error: mem alloc\n");
return -EINVAL;
- }
- size = sizeof(struct snd_soc_tplg_bytes_control);
- bytes_ctl = (struct snd_soc_tplg_bytes_control *)malloc(size);
- if (!bytes_ctl) {
printf("error: mem alloc\n");
return -EINVAL;
- }
- for (j = 0; j < num_kcontrols; j++) {
/* read control header */
read_size = sizeof(struct snd_soc_tplg_ctl_hdr);
ret = fread(ctl_hdr, read_size, 1, file);
if (ret != 1)
return -EINVAL;
/* load control based on type */
switch (ctl_hdr->ops.info) {
case SND_SOC_TPLG_CTL_VOLSW:
case SND_SOC_TPLG_CTL_STROBE:
case SND_SOC_TPLG_CTL_VOLSW_SX:
case SND_SOC_TPLG_CTL_VOLSW_XR_SX:
case SND_SOC_TPLG_CTL_RANGE:
case SND_SOC_TPLG_DAPM_CTL_VOLSW:
/* load mixer type control */
read_size = sizeof(struct snd_soc_tplg_ctl_hdr);
fseek(file, read_size * -1, SEEK_CUR);
read_size = sizeof(struct
snd_soc_tplg_mixer_control);
ret = fread(mixer_ctl, read_size, 1, file);
if (ret != 1)
return -EINVAL;
/* skip mixer private data */
fseek(file, mixer_ctl->priv.size, SEEK_CUR);
break;
case SND_SOC_TPLG_CTL_ENUM:
case SND_SOC_TPLG_CTL_ENUM_VALUE:
case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
/* load enum type control */
read_size = sizeof(struct snd_soc_tplg_ctl_hdr);
fseek(file, read_size * -1, SEEK_CUR);
read_size = sizeof(struct snd_soc_tplg_enum_control);
ret = fread(enum_ctl, read_size, 1, file);
if (ret != 1)
return -EINVAL;
/* skip enum private data */
fseek(file, enum_ctl->priv.size, SEEK_CUR);
break;
case SND_SOC_TPLG_CTL_BYTES:
/* load bytes type controls */
read_size = sizeof(struct snd_soc_tplg_ctl_hdr);
fseek(file, read_size * -1, SEEK_CUR);
read_size = sizeof(struct
snd_soc_tplg_bytes_control);
ret = fread(bytes_ctl, read_size, 1, file);
if (ret != 1)
return -EINVAL;
/* skip bytes private data */
fseek(file, bytes_ctl->priv.size, SEEK_CUR);
break;
default:
printf("control type not supported\n");
return -EINVAL;
}
- }
- /* free all data */
- free(mixer_ctl);
- free(enum_ctl);
- free(bytes_ctl);
- free(ctl_hdr);
- return 0;
+}
+/* load dapm widget */ +static int load_widget(struct sof *sof, int *fr_id, int *fw_id,
int *sched_id, char *bits_in,
struct comp_info *temp_comp_list,
struct sof_ipc_pipe_new *pipeline, int comp_id,
int comp_index, int pipeline_id)
+{
- struct snd_soc_tplg_dapm_widget *widget;
- char message[DEBUG_MSG_LEN];
- size_t read_size, size;
- int ret = 0;
- /* allocate memory for widget */
- size = sizeof(struct snd_soc_tplg_dapm_widget);
- widget = (struct snd_soc_tplg_dapm_widget *)malloc(size);
- if (!widget) {
printf("error: mem alloc\n");
return -EINVAL;
- }
- /* read widget data */
- read_size = sizeof(struct snd_soc_tplg_dapm_widget);
- ret = fread(widget, read_size, 1, file);
- if (ret != 1)
return -EINVAL;
- /*
* create a list with all widget info
* containing mapping between component names and ids
* which will be used for setting up component connections
*/
- temp_comp_list[comp_index].id = comp_id;
- temp_comp_list[comp_index].name = strdup(widget->name);
- temp_comp_list[comp_index].type = widget->id;
- temp_comp_list[comp_index].pipeline_id = pipeline_id;
- sprintf(message, "loading widget %s id %d\n",
temp_comp_list[comp_index].name,
temp_comp_list[comp_index].id);
- debug_print(message);
- /* register comp driver */
- register_comp(temp_comp_list[comp_index].type);
- /* load widget based on type */
- switch (temp_comp_list[comp_index].type) {
- /* load pga widget */
- case(SND_SOC_TPLG_DAPM_PGA):
if (load_pga(sof, temp_comp_list[comp_index].id,
pipeline_id, widget->priv.size) < 0) {
printf("error: load pga\n");
return -EINVAL;
}
break;
- /* replace pcm playback component with fileread in testbench */
- case(SND_SOC_TPLG_DAPM_AIF_IN):
if (load_fileread(sof, temp_comp_list[comp_index].id,
pipeline_id, widget->priv.size, bits_in,
fr_id, sched_id) < 0) {
printf("error: load fileread\n");
return -EINVAL;
}
break;
- /* replace dai in component with filewrite in testbench */
- case(SND_SOC_TPLG_DAPM_DAI_IN):
if (load_filewrite(sof, temp_comp_list[comp_index].id,
pipeline_id, widget->priv.size,
fw_id) < 0) {
printf("error: load filewrite\n");
return -EINVAL;
}
break;
- /* load buffer */
- case(SND_SOC_TPLG_DAPM_BUFFER):
if (load_buffer(sof, temp_comp_list[comp_index].id,
pipeline_id, widget->priv.size) < 0) {
printf("error: load buffer\n");
return -EINVAL;
}
break;
- /* load pipeline */
- case(SND_SOC_TPLG_DAPM_SCHEDULER):
if (load_pipeline(sof, pipeline,
temp_comp_list[comp_index].id,
pipeline_id,
widget->priv.size,
sched_id) < 0) {
printf("error: load buffer\n");
return -EINVAL;
}
break;
- /* unsupported widgets */
- default:
printf("Widget type not supported %d\n",
widget->id);
break;
- }
- /* load widget kcontrols */
- if (widget->num_kcontrols > 0)
if (load_controls(sof, widget->num_kcontrols) < 0) {
printf("error: load buffer\n");
return -EINVAL;
}
- free(widget);
- return 0;
+}
+/* parse topology file and set up pipeline */ +int parse_topology(char *filename, struct sof *sof, int *fr_id, int *fw_id,
int *sched_id, char *bits_in, char *in_file,
char *out_file, void *volume_library, char *pipeline_msg)
+{
- struct snd_soc_tplg_hdr *hdr;
- struct comp_info *temp_comp_list = NULL;
- struct sof_ipc_pipe_new pipeline;
- char message[DEBUG_MSG_LEN];
- int next_comp_id = 0, num_comps = 0;
- int i, ret = 0;
- size_t file_size, size;
- /* set volume library */
- volume_lib = volume_library;
- /* open topology file */
- file = fopen(filename, "rb");
- if (!file) {
fprintf(stderr, "error: opening file %s\n", filename);
return -EINVAL;
- }
- /* set up fileread and filewrite file names */
- input_file = strdup(in_file);
- output_file = strdup(out_file);
- /* file size */
- fseek(file, 0, SEEK_END);
- file_size = ftell(file);
- fseek(file, 0, SEEK_SET);
- /* allocate memory */
- size = sizeof(struct snd_soc_tplg_hdr);
- hdr = (struct snd_soc_tplg_hdr *)malloc(size);
- if (!hdr) {
printf("error: mem alloc\n");
return -EINVAL;
- }
- debug_print("topology parsing start\n");
- while (1) {
/* read topology header */
ret = fread(hdr, sizeof(struct snd_soc_tplg_hdr), 1, file);
if (ret != 1)
return -EINVAL;
sprintf(message, "type: %x, size: 0x%x count: %d index:
%d\n",
hdr->type, hdr->payload_size, hdr->count, hdr-
index);
debug_print(message);
/* parse header and load the next block based on type */
switch (hdr->type) {
/* load dapm widget */
case SND_SOC_TPLG_TYPE_DAPM_WIDGET:
sprintf(message, "number of DAPM widgets %d\n",
hdr->count);
debug_print(message);
size = sizeof(struct comp_info) * hdr->count;
temp_comp_list = (struct comp_info *)malloc(size);
num_comps = hdr->count;
for (i = 0; i < hdr->count; i++)
load_widget(sof, fr_id, fw_id, sched_id,
bits_in, temp_comp_list,
&pipeline, next_comp_id++,
i, hdr->index);
break;
/* set up component connections from pipeline graph */
case SND_SOC_TPLG_TYPE_DAPM_GRAPH:
if (load_graph(sof, temp_comp_list, hdr->count,
num_comps, hdr->index) < 0) {
printf("error: pipeline graph\n");
return -EINVAL;
}
if (ftell(file) == file_size)
goto finish;
break;
default:
fseek(file, hdr->payload_size, SEEK_CUR);
if (ftell(file) == file_size)
goto finish;
break;
}
- }
+finish:
- debug_print("topology parsing end\n");
- strcpy(pipeline_msg, pipeline_string);
- /* free all data */
- free(hdr);
- for (i = 0; i < num_comps; i++)
free(temp_comp_list[i].name);
- free(temp_comp_list);
- fclose(file);
- return 0;
+}
+/* parse vendor tokens in topology */ +int sof_parse_tokens(void *object, const struct sof_topology_token *tokens,
int count, struct snd_soc_tplg_vendor_array *array,
int priv_size)
+{
- int asize;
- while (priv_size > 0) {
asize = array->size;
/* validate asize */
if (asize < 0) { /* FIXME: A zero-size array makes no sense
*/
printf("error: invalid array size 0x%x\n", asize);
return -EINVAL;
}
/* make sure there is enough data before parsing */
priv_size -= asize;
if (priv_size < 0) {
printf("error: invalid array size 0x%x\n", asize);
return -EINVAL;
}
/* call correct parser depending on type */
switch (array->type) {
case SND_SOC_TPLG_TUPLE_TYPE_UUID:
sof_parse_uuid_tokens(object, tokens, count,
array);
break;
case SND_SOC_TPLG_TUPLE_TYPE_STRING:
sof_parse_string_tokens(object, tokens, count,
array);
break;
case SND_SOC_TPLG_TUPLE_TYPE_BOOL:
case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
case SND_SOC_TPLG_TUPLE_TYPE_WORD:
case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
sof_parse_word_tokens(object, tokens, count,
array);
break;
default:
printf("error: unknown token type %d\n", array-
type);
return -EINVAL;
}
/* next array */
array = (void *)array + asize;
- }
- return 0;
+}
+void sof_parse_word_tokens(void *object,
const struct sof_topology_token *tokens,
int count,
struct snd_soc_tplg_vendor_array *array)
+{
- struct snd_soc_tplg_vendor_value_elem *elem;
- int i, j;
- /* parse element by element */
- for (i = 0; i < array->num_elems; i++) {
elem = &array->value[i];
/* search for token */
for (j = 0; j < count; j++) {
/* match token type */
if (tokens[j].type != SND_SOC_TPLG_TUPLE_TYPE_WORD)
continue;
/* match token id */
if (tokens[j].token != elem->token)
continue;
/* matched - now load token */
tokens[j].get_token(elem, object, tokens[j].offset,
tokens[j].size);
}
- }
+}
+void sof_parse_uuid_tokens(void *object,
const struct sof_topology_token *tokens,
int count,
struct snd_soc_tplg_vendor_array *array)
+{
- struct snd_soc_tplg_vendor_uuid_elem *elem;
- int i, j;
- /* parse element by element */
- for (i = 0; i < array->num_elems; i++) {
elem = &array->uuid[i];
/* search for token */
for (j = 0; j < count; j++) {
/* match token type */
if (tokens[j].type != SND_SOC_TPLG_TUPLE_TYPE_UUID)
continue;
/* match token id */
if (tokens[j].token != elem->token)
continue;
/* matched - now load token */
tokens[j].get_token(elem, object, tokens[j].offset,
tokens[j].size);
}
- }
+}
+void sof_parse_string_tokens(void *object,
const struct sof_topology_token *tokens,
int count,
struct snd_soc_tplg_vendor_array *array)
+{
- struct snd_soc_tplg_vendor_string_elem *elem;
- int i, j;
- /* parse element by element */
- for (i = 0; i < array->num_elems; i++) {
elem = &array->string[i];
/* search for token */
for (j = 0; j < count; j++) {
/* match token type */
if (tokens[j].type != SND_SOC_TPLG_TUPLE_TYPE_STRING)
continue;
/* match token id */
if (tokens[j].token != elem->token)
continue;
/* matched - now load token */
tokens[j].get_token(elem, object, tokens[j].offset,
tokens[j].size);
}
- }
+}
+enum sof_ipc_frame find_format(const char *name) +{
- int i;
- for (i = 0; i < ARRAY_SIZE(sof_frames); i++) {
if (strcmp(name, sof_frames[i].name) == 0)
return sof_frames[i].frame;
- }
- /* use s32le if nothing is specified */
- return SOF_IPC_FRAME_S32_LE;
+}
+int get_token_uint32_t(void *elem, void *object, uint32_t offset,
uint32_t size)
+{
- struct snd_soc_tplg_vendor_value_elem *velem = elem;
- uint32_t *val = object + offset;
- *val = velem->value;
- return 0;
+}
+int get_token_comp_format(void *elem, void *object, uint32_t offset,
uint32_t size)
+{
- struct snd_soc_tplg_vendor_string_elem *velem = elem;
- uint32_t *val = object + offset;
- *val = find_format(velem->string);
- return 0;
+} diff --git a/src/host/trace.c b/src/host/trace.c new file mode 100644 index 0000000..a98648b --- /dev/null +++ b/src/host/trace.c @@ -0,0 +1,181 @@ +/*
- Copyright (c) 2018, 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: Seppo Ingalsuo seppo.ingalsuo@linux.intel.com
Liam Girdwood <liam.r.girdwood@linux.intel.com>
Keyon Jie <yang.jie@linux.intel.com>
Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
- */
+#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include "host/common_test.h" +#include "host/trace.h"
+#define MAX_TRACE_CLASSES 255 +/* testbench trace definition */
+/* enable trace by default in testbench */ +static int test_bench_trace = 1; +int num_trace_classes;
+/* set up trace class identifier table based on SOF trace header file */ +void setup_trace_table(void) +{
- char buffer[2048];
- char *trace = "sof/trace.h";
- char *trace_filename = malloc(strlen(SOF_INC) + strlen(trace) + 2);
- char *token;
- int ret, i = 0;
- size_t size;
- FILE *fp;
- /* set up trace file name using include directory prefix */
- sprintf(trace_filename, "%s/%s", SOF_INC, trace);
- fp = fopen(trace_filename, "r");
- if (!fp) {
fprintf(stderr, "error: opening trace include file %s\n",
trace_filename);
include errno here.
- }
- /* find number of trace classes defined */
- while (fgets(buffer, sizeof(buffer), fp)) {
char identifier[1024];
int value = 0, shift = 0;
ret = sscanf(buffer, "#define %s (%d << %d)", identifier,
&value, &shift);
if (ret == 3) {
/* if TRACE_CLASS definition */
if (strstr(identifier, "TRACE_CLASS"))
i++;
}
- }
- num_trace_classes = i;
- /* allocate memory for trace table */
- size = sizeof(struct trace_class_table);
- trace_table = (struct trace_class_table *)malloc(size *
num_trace_classes);
- /* rewind file pointer */
- fseek(fp, 0, SEEK_SET);
- i = 0;
- /* read lines from header */
Can you explain what this does in more detail.
- while (fgets(buffer, sizeof(buffer), fp)) {
char identifier[1024];
int value = 0, shift = 0;
should be declared at top of func.
ret = sscanf(buffer, "#define %s (%d << %d)", identifier,
&value, &shift);
if (ret == 3) {
/* if TRACE_CLASS definition */
if (strstr(identifier, "TRACE_CLASS")) {
/* extract subsystem name */
token = strtok(identifier, "_");
token = strtok(NULL, "_");
token = strtok(NULL, "_");
/* add trace class entry */
trace_table[i].trace_class = value;
trace_table[i].class_name = strdup(token);
i++;
}
}
- }
- fclose(fp);
- free(trace_filename);
+}
+void free_trace_table(void) +{
- int i;
- for (i = 0; i < num_trace_classes; i++)
free(trace_table[i].class_name);
- free(trace_table);
+}
+/* look up subsystem class name from table */ +static char *get_trace_class(uint32_t trace_class) +{
- int i;
- /* look up trace class table and return subsystem name */
- for (i = 0; i < num_trace_classes; i++) {
if (trace_table[i].trace_class == trace_class)
return trace_table[i].class_name;
- }
- return "value";
+}
+/* print trace event */ +void _trace_event(uint32_t event) +{
- char a, b, c;
- char *trace_class = NULL;
- if (test_bench_trace > 0) {
a = event & 0xff;
b = (event >> 8) & 0xff;
c = (event >> 16) & 0xff;
/* look up subsystem from trace class table */
trace_class = strdup(get_trace_class(event >> 24));
/* print trace event stderr*/
if (strcmp(trace_class, "value") == 0)
fprintf(stderr, "Trace value %d\n", event);
else
fprintf(stderr, "Trace %s %c%c%c\n", trace_class,
c, b, a);
- }
- free(trace_class);
+}
+void _trace_event_mbox_atomic(uint32_t event) +{
- _trace_event(event);
+}
+/* enable trace in testbench */ +void tb_enable_trace(bool enable) +{
- test_bench_trace = enable;
- if (enable)
debug_print("trace print enabled\n");
- else
debug_print("trace print disabled\n");
+} diff --git a/src/include/host/common_test.h b/src/include/host/common_test.h new file mode 100644 index 0000000..96193e5 --- /dev/null +++ b/src/include/host/common_test.h @@ -0,0 +1,65 @@ +/*
- Copyright (c) 2018, 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(s): Seppo Ingalsuo seppo.ingalsuo@linux.intel.com
Liam Girdwood <liam.r.girdwood@linux.intel.com>
Keyon Jie <yang.jie@linux.intel.com>
Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
- */
+#ifndef _COMMON_TEST_H +#define _COMMON_TEST_H
+#include <stdint.h> +#include <stddef.h> +#include <time.h> +#include <stdio.h> +#include <uapi/ipc.h> +#include <sof/sof.h> +#include <sof/audio/component.h> +#include <sof/audio/format.h>
+#define DEBUG_MSG_LEN 256
+extern int debug;
+int scheduler_init(struct sof *sof);
+void sys_comp_file_init(void);
+void sys_comp_filewrite_init(void);
+int tb_pipeline_setup(struct sof *sof);
+int tb_pipeline_start(struct ipc *ipc, int nch, char *bits_in,
struct sof_ipc_pipe_new *ipc_pipe);
+int tb_pipeline_params(struct ipc *ipc, int nch, char *bits_in,
struct sof_ipc_pipe_new *ipc_pipe);
+void debug_print(char *message);
+#endif diff --git a/src/include/host/topology.h b/src/include/host/topology.h new file mode 100644 index 0000000..b3421c8 --- /dev/null +++ b/src/include/host/topology.h @@ -0,0 +1,202 @@ +/*
- Copyright (c) 2018, 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: Liam Girdwood liam.r.girdwood@linux.intel.com
Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
- */
+#ifndef _COMMON_TPLG_H +#define _COMMON_TPLG_H
+#include <sound/asoc.h> +#include "common_test.h"
+/*
- TODO: include these token from kernel uapi header
- Tokens - must match values in topology configurations
- */
+/* buffers */ +#define SOF_TKN_BUF_SIZE 100 +#define SOF_TKN_BUF_CAPS 101
+/* scheduling */ +#define SOF_TKN_SCHED_DEADLINE 200 +#define SOF_TKN_SCHED_PRIORITY 201 +#define SOF_TKN_SCHED_MIPS 202 +#define SOF_TKN_SCHED_CORE 203 +#define SOF_TKN_SCHED_FRAMES 204 +#define SOF_TKN_SCHED_TIMER 205
+/* volume */ +#define SOF_TKN_VOLUME_RAMP_STEP_TYPE 250 +#define SOF_TKN_VOLUME_RAMP_STEP_MS 251
+/* SRC */ +#define SOF_TKN_SRC_RATE_IN 300 +#define SOF_TKN_SRC_RATE_OUT 301
+/* Generic components */ +#define SOF_TKN_COMP_PERIOD_SINK_COUNT 400 +#define SOF_TKN_COMP_PERIOD_SOURCE_COUNT 401 +#define SOF_TKN_COMP_FORMAT 402 +#define SOF_TKN_COMP_PRELOAD_COUNT 403
+struct comp_info {
- char *name;
- int id;
- int type;
- int pipeline_id;
+};
+struct frame_types {
- char *name;
- enum sof_ipc_frame frame;
+};
+static const struct frame_types sof_frames[] = {
- /* TODO: fix topology to use ALSA formats */
- {"s16le", SOF_IPC_FRAME_S16_LE},
- {"s24le", SOF_IPC_FRAME_S24_4LE},
- {"s32le", SOF_IPC_FRAME_S32_LE},
- {"float", SOF_IPC_FRAME_FLOAT},
- /* ALSA formats */
- {"S16_LE", SOF_IPC_FRAME_S16_LE},
- {"S24_LE", SOF_IPC_FRAME_S24_4LE},
- {"S32_LE", SOF_IPC_FRAME_S32_LE},
- {"FLOAT_LE", SOF_IPC_FRAME_FLOAT},
+};
+struct sof_topology_token {
- uint32_t token;
- uint32_t type;
- int (*get_token)(void *elem, void *object, uint32_t offset,
uint32_t size);
- uint32_t offset;
- uint32_t size;
+};
+enum sof_ipc_frame find_format(const char *name);
+int get_token_uint32_t(void *elem, void *object, uint32_t offset,
uint32_t size);
+int get_token_comp_format(void *elem, void *object, uint32_t offset,
uint32_t size);
+/* Buffers */ +static const struct sof_topology_token buffer_tokens[] = {
- {SOF_TKN_BUF_SIZE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_uint32_t,
offsetof(struct sof_ipc_buffer, size), 0},
- {SOF_TKN_BUF_CAPS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_uint32_t,
offsetof(struct sof_ipc_buffer, caps), 0},
+};
+/* scheduling */ +static const struct sof_topology_token sched_tokens[] = {
- {SOF_TKN_SCHED_DEADLINE, SND_SOC_TPLG_TUPLE_TYPE_WORD,
get_token_uint32_t,
offsetof(struct sof_ipc_pipe_new, deadline), 0},
- {SOF_TKN_SCHED_PRIORITY, SND_SOC_TPLG_TUPLE_TYPE_WORD,
get_token_uint32_t,
offsetof(struct sof_ipc_pipe_new, priority), 0},
- {SOF_TKN_SCHED_MIPS, SND_SOC_TPLG_TUPLE_TYPE_WORD,
get_token_uint32_t,
offsetof(struct sof_ipc_pipe_new, mips), 0},
- {SOF_TKN_SCHED_CORE, SND_SOC_TPLG_TUPLE_TYPE_WORD,
get_token_uint32_t,
offsetof(struct sof_ipc_pipe_new, core), 0},
- {SOF_TKN_SCHED_FRAMES, SND_SOC_TPLG_TUPLE_TYPE_WORD,
get_token_uint32_t,
offsetof(struct sof_ipc_pipe_new, frames_per_sched), 0},
- {SOF_TKN_SCHED_TIMER, SND_SOC_TPLG_TUPLE_TYPE_WORD,
get_token_uint32_t,
offsetof(struct sof_ipc_pipe_new, timer), 0},
+};
+/* volume */ +static const struct sof_topology_token volume_tokens[] = {
- {SOF_TKN_VOLUME_RAMP_STEP_TYPE, SND_SOC_TPLG_TUPLE_TYPE_WORD,
get_token_uint32_t,
offsetof(struct sof_ipc_comp_volume, ramp), 0},
- {SOF_TKN_VOLUME_RAMP_STEP_MS,
SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_uint32_t,
offsetof(struct sof_ipc_comp_volume, initial_ramp), 0},
+};
+/* SRC */ +static const struct sof_topology_token src_tokens[] = {
- {SOF_TKN_SRC_RATE_IN, SND_SOC_TPLG_TUPLE_TYPE_WORD,
get_token_uint32_t,
offsetof(struct sof_ipc_comp_src, source_rate), 0},
- {SOF_TKN_SRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD,
get_token_uint32_t,
offsetof(struct sof_ipc_comp_src, sink_rate), 0},
+};
+/* Tone */ +static const struct sof_topology_token tone_tokens[] = { +};
+/* Generic components */ +static const struct sof_topology_token comp_tokens[] = {
- {SOF_TKN_COMP_PERIOD_SINK_COUNT,
SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_uint32_t,
offsetof(struct sof_ipc_comp_config, periods_sink), 0},
- {SOF_TKN_COMP_PERIOD_SOURCE_COUNT,
SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_uint32_t,
offsetof(struct sof_ipc_comp_config, periods_source), 0},
- {SOF_TKN_COMP_FORMAT,
SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_comp_format,
offsetof(struct sof_ipc_comp_config, frame_fmt), 0},
- {SOF_TKN_COMP_PRELOAD_COUNT,
SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_uint32_t,
offsetof(struct sof_ipc_comp_config, preload_count), 0},
+};
+int sof_parse_tokens(void *object,
const struct sof_topology_token *tokens,
int count, struct snd_soc_tplg_vendor_array *array,
int priv_size);
+void sof_parse_string_tokens(void *object,
const struct sof_topology_token *tokens,
int count,
struct snd_soc_tplg_vendor_array *array);
+void sof_parse_uuid_tokens(void *object,
const struct sof_topology_token *tokens,
int count,
struct snd_soc_tplg_vendor_array *array);
+void sof_parse_word_tokens(void *object,
const struct sof_topology_token *tokens,
int count,
struct snd_soc_tplg_vendor_array *array);
+int parse_topology(char *filename, struct sof *sof, int *fr_id, int *fw_id,
int *sched_id, char *bits_in,
char *in_file, char *out_file, void *volume_library,
char *pipeline);
+#endif diff --git a/src/include/host/trace.h b/src/include/host/trace.h new file mode 100644 index 0000000..8c45fb4 --- /dev/null +++ b/src/include/host/trace.h @@ -0,0 +1,49 @@ +/*
- Copyright (c) 2018, 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: Seppo Ingalsuo seppo.ingalsuo@linux.intel.com
Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
- */
+#include <stdbool.h>
+#ifndef _TRACE_H +#define _TRACE_H
+struct trace_class_table {
- int trace_class;
- char *class_name;
+};
+struct trace_class_table *trace_table;
+void tb_enable_trace(bool enable);
+void setup_trace_table(void);
+void free_trace_table(void);
+#endif
--------------------------------------------------------------------- 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.