This patch updates the following in the common_test methods
testbench_pipeline_setup() updated with pointer to pipeline desc and connection description
testbench_pipeline_params() method added to set stream params
testbench_params_unmute_start() updated with the above method
formatting changes to print relevant error messages
MUX component specific convenience constructors
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com --- tune/c/include/common_test.h | 6 +- tune/c/src/common_test.c | 419 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 423 insertions(+), 2 deletions(-) create mode 100644 tune/c/src/common_test.c
diff --git a/tune/c/include/common_test.h b/tune/c/include/common_test.h index 73d6fe5..01eadec 100644 --- a/tune/c/include/common_test.h +++ b/tune/c/include/common_test.h @@ -39,6 +39,7 @@ #include <stdio.h>
#include <reef/ipc.h> +#include <reef/reef.h> #include <reef/audio/pipeline.h> #include <reef/audio/format.h>
@@ -69,6 +70,7 @@ {.comp = scomp, .min_value = vmin, .max_value = vmax,\ .config = SCONFIG} #define SPIPE_MIX(scomp) {.comp = scomp, .config = SCONFIG} +#define SPIPE_MUX(scomp) {.comp = scomp, .config = SCONFIG} #define SPIPE_SRC(scomp) {.comp = scomp, .config = SCONFIG} #define SPIPE_EQ_FIR(scomp) {.comp = scomp, .config = SCONFIG} #define SPIPE_EQ_IIR(scomp) {.comp = scomp, .config = SCONFIG} @@ -76,7 +78,6 @@ #define SPIPE_FILEREAD(scomp, fn_in) {.comp = scomp, .config = SCONFIG, .fn = fn_in} #define SPIPE_FILEWRITE(scomp, fn_out) {.comp = scomp, .config = SCONFIG, .fn = fn_out}
- /* * Static Pipeline Convenience Constructor */ @@ -96,7 +97,6 @@ {.comps = (struct sof_ipc_comp *)ccomps, .num_comps \ = ARRAY_SIZE(ccomps)}
- #define SPIPE(ncomp, sbuffer, sconnect) \ {.scomps = ncomp, .num_scomps = ARRAY_SIZE(ncomp), \ .buffer = sbuffer, .num_buffers = ARRAY_SIZE(sbuffer), \ @@ -178,6 +178,8 @@ int test_bench_pipeline_setup(struct reef *reef,
int test_bench_pipeline_params_unmute_start(struct ipc *ipc, int32_t fs, int nch, int deadline, int sched_id, int pipe_id); +int test_bench_pipeline_params(struct ipc *ipc, int32_t fs, + int nch, int host_comp_id, int deadline, uint32_t pipe_id);
void test_bench_enable_trace(void); void test_bench_disable_trace(void); diff --git a/tune/c/src/common_test.c b/tune/c/src/common_test.c new file mode 100644 index 0000000..a245286 --- /dev/null +++ b/tune/c/src/common_test.c @@ -0,0 +1,419 @@ +/* Simple test bench versions of SOF functions */ + +/* + * Copyright (c) 2017, 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 + */ + +#include <stdint.h> +#include <stddef.h> +#include <time.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include <reef/task.h> +#include <reef/alloc.h> +#include <reef/ipc.h> +#include <reef/wait.h> +#include <reef/intel-ipc.h> +#include <reef/audio/pipeline.h> +#include "common_test.h" + +/* Use simplified host test bench versions for features */ +#define TB_HOST_ALLOC_FREE_MEMCPY 1 +#define TB_TRACE 1 +#define TB_SCHEDULE 1 +#define TB_IPC 1 +#define TB_TIMER 1 + +#if TB_IPC +struct ipc *_ipc; + +int ipc_stream_send_xrun(struct comp_dev *dev, + struct sof_ipc_stream_posn *posn) +{ + return 0; +} +#endif + +#if TB_SCHEDULE + +struct schedule_data { + spinlock_t lock; + struct list_item list; /* list of tasks in priority queue */ + uint32_t clock; +}; +static struct schedule_data *sch; +#endif + +#if TB_TRACE +static int test_bench_trace = 1; +#endif + +#if TB_TRACE + +char replace_blank(char x) +{ + char y = x; + + if ((y != '-') && (y != '+') && (y != '_')) { + if (y < 'A') + y = ' '; + + if (y > 'z') + y = ' '; + } + return y; +} + +void _trace_event(uint32_t event) +{ + char a, b, c; + + if (test_bench_trace > 0) { + a = replace_blank((char) (event & 0xff)); + b = replace_blank((char) ((event >> 8) & 0xff)); + c = replace_blank((char) ((event >> 16) & 0xff)); + printf("Trace %10d %c%c%c\n", event, c, b, a); + } +} + +void test_bench_enable_trace(void) +{ + test_bench_trace = 1; + printf("Trace print enabled\n"); +} + +void test_bench_disable_trace(void) +{ + test_bench_trace = 0; + printf("Trace print disabled\n"); +} +#endif + +#if TB_HOST_ALLOC_FREE_MEMCPY + +void *rmalloc(int zone, int module, size_t bytes) +{ + return malloc(bytes); +} + +void *rzalloc(int zone, int module, size_t bytes) +{ + return malloc(bytes); +} + +void rfree(void *ptr) +{ + free(ptr); +} + +void *rballoc(int zone, int module, size_t bytes) +{ + return malloc(bytes); +} + +void rbfree(void *ptr) +{ + free(ptr); +} + +void *xthal_memcpy(void *dest, const void *src, size_t size) +{ + return memcpy(dest, src, size); +} + +#endif + +#if TB_SCHEDULE + +void schedule_task_complete(struct task *task) +{ + + list_item_del(&task->list); + task->state = TASK_STATE_COMPLETED; +} + +void schedule_task(struct task *task, uint32_t deadline, uint16_t priority, + void *data) +{ + task->deadline = deadline; + task->priority = priority; + task->sdata = data; + list_item_prepend(&task->list, &sch->list); + task->state = TASK_STATE_QUEUED; + + if (task->func) + task->func(task->data); + + schedule_task_complete(task); +} + +void schedule(void) +{ +} + +int scheduler_init(struct reef *reef) +{ + trace_pipe("ScI"); + + sch = rzalloc(RZONE_SYS, RFLAGS_NONE, sizeof(*sch)); + list_init(&sch->list); + spinlock_init(&sch->lock); + + return 0; +} + +#endif + +#if TB_IPC + +int platform_ipc_init(struct ipc *ipc) +{ + struct intel_ipc_data *iipc; + //uint32_t imrd; + int i; + + _ipc = ipc; + + /* init ipc data */ + iipc = rzalloc(RZONE_SYS, RFLAGS_NONE, 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 = rballoc(RZONE_SYS, RFLAGS_NONE, + HOST_PAGE_SIZE); + if (iipc->page_table) + bzero(iipc->page_table, HOST_PAGE_SIZE); + + /* PM */ + iipc->pm_prepare_D3 = 0; + + return 0; +} + +int ipc_stream_send_xrun(struct comp_dev *cdev, + struct sof_ipc_stream_posn *posn) +{ + return 0; +} + +#endif + +#if TB_TIMER + +/* get timestamp for DAI stream DMA position */ +void platform_dai_timestamp(struct comp_dev *dai, + struct sof_ipc_stream_posn *posn) +{ +} + +/* get timestamp for host stream DMA position */ +void platform_host_timestamp(struct comp_dev *host, + struct sof_ipc_stream_posn *posn) +{ +} + +#endif + +int test_bench_pipeline_setup(struct reef *reef, + struct sof_ipc_pipe_new *pipeline, struct spipe *spipe) +{ + struct scomps *sc; + int i, j; + struct sof_ipc_comp *c; + struct ipc *ipc; + + /* Init IPC */ + if (ipc_init(reef) < 0) { + fprintf(stderr, "error: IPC init\n"); + return -EINVAL; + } + ipc = reef->ipc; + + /* Init scheduler */ + if (scheduler_init(reef) < 0) { + fprintf(stderr, "error: scheduler init\n"); + return -EINVAL; + } + + /* Init pipeline system */ + if (pipeline_init() < 0) { + fprintf(stderr, "error: pipeline init\n"); + return -EINVAL; + } + + + /* Register components */ + sc = spipe->scomps; + for (i = 0; i < spipe->num_scomps; i++) { + c = sc[i].comps; + for (j = 0; j < sc[i].num_comps; j++) { + if (ipc_comp_new(ipc, c) < 0) { + fprintf(stderr, "error: comp register\n"); + return -EINVAL; + } + c = (void *) c + c->hdr.size; + } + } + + /* Pipeline new must be after component registration since the + * scheduling component must exist. + */ + if (ipc_pipeline_new(ipc, pipeline) < 0) { + fprintf(stderr, "error: pipeline new\n"); + return -EINVAL; + } + + /* Register buffers */ + for (i = 0; i < spipe->num_buffers; i++) { + if (ipc_buffer_new(ipc, &spipe->buffer[i]) < 0) { + fprintf(stderr, "error: buffer new\n"); + return -EINVAL; + } + } + + /* Connect components */ + for (i = 0; i < spipe->num_connections; i++) { + if (ipc_comp_connect(ipc, &spipe->connect[i]) < 0) { + fprintf(stderr, "error: comp connect\n"); + return -EINVAL; + } + } + + /* Pipeline complete */ + ipc_pipeline_complete(ipc, pipeline->comp_id); + + return 0; +} + +int test_bench_pipeline_params_unmute_start(struct ipc *ipc, + int32_t fs, int nch, int deadline, int sched_id, int pipe_id) +{ + int ret; + struct ipc_comp_dev *pcm_dev; + struct pipeline *p; + struct comp_dev *cd; + + ret = test_bench_pipeline_params(ipc, fs, nch, sched_id, deadline, + pipe_id); + if (ret < 0) { + printf("error: pipeline params\n"); + return -EINVAL; + } + + /* Get IPC component device for pipeline and f */ + pcm_dev = ipc_get_comp(ipc, sched_id); + if (pcm_dev == NULL) { + printf("error: ipc get comp\n"); + return -EINVAL; + } + + /* Point to pipeline */ + cd = pcm_dev->cd; + p = pcm_dev->cd->pipeline; + + /* Unmute and start the pipeline */ + pipeline_cmd(p, cd, COMP_CMD_UNMUTE, NULL); + pipeline_cmd(p, cd, COMP_CMD_START, NULL); + + return 0; +} + +int test_bench_pipeline_params(struct ipc *ipc, int32_t fs, + int nch, int host_comp_id, int deadline, uint32_t pipe_id) +{ + int fs_period, ret = 0; + struct ipc_comp_dev *pcm_dev; + struct pipeline *p; + struct comp_dev *cd; + struct sof_ipc_pcm_params params; + struct sof_ipc_ctrl_data ctrl_cmd; + + /* Compute period from sample rates */ + fs_period = (int) (0.9999 + fs * deadline / 1e6); + + params.comp_id = pipe_id; + params.params.buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; + params.params.frame_fmt = SOF_IPC_FRAME_S32_LE; + 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; + params.params.sample_valid_bytes = 2; + 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: + printf("error: invalid frame format\n"); + return -EINVAL; + } + + /* Get IPC component device for pipeline*/ + pcm_dev = ipc_get_comp(ipc, host_comp_id); + if (pcm_dev == NULL) { + printf("error: ipc get comp\n"); + return -EINVAL; + } + + /* Point to pipeline */ + cd = pcm_dev->cd; + p = pcm_dev->cd->pipeline; + + /* Pipeline params */ + if (p == NULL) { + printf("error: pipeline NULL\n"); + return -EINVAL; + } + + ret = pipeline_params(p, cd, ¶ms); + if (ret < 0) { + printf("error: pipeline_params\n"); + } + + return ret; +}