1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2018 Intel Corporation. All rights reserved.
4 
5 #include <stdint.h>
6 #include <stddef.h>
7 #include <time.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <rtos/string.h>
11 #include <math.h>
12 #include <rtos/sof.h>
13 #include <rtos/task.h>
14 #include <rtos/alloc.h>
15 #include <sof/lib/notifier.h>
16 #include <sof/ipc/driver.h>
17 #include <sof/ipc/topology.h>
18 #include <sof/lib/agent.h>
19 #include <sof/lib/dai.h>
20 #include <sof/lib/dma.h>
21 #include <sof/schedule/edf_schedule.h>
22 #include <sof/schedule/ll_schedule.h>
23 #include <sof/schedule/ll_schedule_domain.h>
24 #include <sof/schedule/schedule.h>
25 #include <rtos/wait.h>
26 #include <sof/audio/pipeline.h>
27 #include <sof/audio/component_ext.h>
28 #include "testbench/common_test.h"
29 #include "testbench/trace.h"
30 #include <tplg_parser/topology.h>
31 
32 /* testbench helper functions for pipeline setup and trigger */
33 
tb_setup(struct sof * sof,struct testbench_prm * tp)34 int tb_setup(struct sof *sof, struct testbench_prm *tp)
35 {
36 	struct ll_schedule_domain domain = {0};
37 
38 	domain.next_tick = tp->tick_period_us;
39 
40 	/* init components */
41 	sys_comp_init(sof);
42 	sys_comp_file_init();
43 	sys_comp_asrc_init();
44 	sys_comp_crossover_init();
45 	sys_comp_dcblock_init();
46 	sys_comp_drc_init();
47 	sys_comp_multiband_drc_init();
48 	sys_comp_selector_init();
49 	sys_comp_src_init();
50 
51 	/* Module adapter components */
52 	sys_comp_module_demux_interface_init();
53 	sys_comp_module_eq_fir_interface_init();
54 	sys_comp_module_eq_iir_interface_init();
55 	sys_comp_module_mux_interface_init();
56 	sys_comp_module_tdfb_interface_init();
57 	sys_comp_module_volume_interface_init();
58 
59 	/* other necessary initializations, todo: follow better SOF init */
60 	pipeline_posn_init(sof);
61 	init_system_notify(sof);
62 
63 	/* init IPC */
64 	if (ipc_init(sof) < 0) {
65 		fprintf(stderr, "error: IPC init\n");
66 		return -EINVAL;
67 	}
68 
69 	/* init LL scheduler */
70 	if (scheduler_init_ll(&domain) < 0) {
71 		fprintf(stderr, "error: edf scheduler init\n");
72 		return -EINVAL;
73 	}
74 
75 	/* init EDF scheduler */
76 	if (scheduler_init_edf() < 0) {
77 		fprintf(stderr, "error: edf scheduler init\n");
78 		return -EINVAL;
79 	}
80 
81 	debug_print("ipc and scheduler initialized\n");
82 
83 	return 0;
84 }
85 
86 struct ipc_data {
87 	struct ipc_data_host_buffer dh_buffer;
88 };
89 
tb_free(struct sof * sof)90 void tb_free(struct sof *sof)
91 {
92 	struct schedule_data *sch;
93 	struct schedulers **schedulers;
94 	struct list_item *slist, *_slist;
95 	struct notify **notify = arch_notify_get();
96 	struct ipc_data *iipc;
97 
98 	free(*notify);
99 
100 	/* free all scheduler data */
101 	schedule_free(0);
102 	schedulers = arch_schedulers_get();
103 	list_for_item_safe(slist, _slist, &(*schedulers)->list) {
104 		sch = container_of(slist, struct schedule_data, list);
105 		free(sch);
106 	}
107 	free(*arch_schedulers_get());
108 
109 	/* free IPC data */
110 	iipc = sof->ipc->private;
111 	free(sof->ipc->comp_data);
112 	free(iipc->dh_buffer.page_table);
113 	free(iipc);
114 	free(sof->ipc);
115 }
116 
117 /* Get pipeline host component */
tb_get_pipeline_host(struct pipeline * p)118 static struct comp_dev *tb_get_pipeline_host(struct pipeline *p)
119 {
120 	struct comp_dev *cd;
121 
122 	cd = p->source_comp;
123 	if (cd->direction == SOF_IPC_STREAM_CAPTURE)
124 		cd = p->sink_comp;
125 
126 	return cd;
127 }
128 
129 /* set up pcm params, prepare and trigger pipeline */
tb_pipeline_start(struct ipc * ipc,struct pipeline * p)130 int tb_pipeline_start(struct ipc *ipc, struct pipeline *p)
131 {
132 	struct comp_dev *cd;
133 	int ret;
134 
135 	/* Get pipeline host component */
136 	cd = tb_get_pipeline_host(p);
137 
138 	/* Component prepare */
139 	ret = pipeline_prepare(p, cd);
140 	if (ret < 0) {
141 		fprintf(stderr, "error: Failed prepare pipeline command: %s\n",
142 			strerror(ret));
143 		return ret;
144 	}
145 
146 	/* Start the pipeline */
147 	ret = pipeline_trigger(cd->pipeline, cd, COMP_TRIGGER_PRE_START);
148 	if (ret < 0) {
149 		fprintf(stderr, "error: Failed to start pipeline command: %s\n",
150 			strerror(ret));
151 		return ret;
152 	}
153 
154 	return ret;
155 }
156 
157 /* set up pcm params, prepare and trigger pipeline */
tb_pipeline_stop(struct ipc * ipc,struct pipeline * p)158 int tb_pipeline_stop(struct ipc *ipc, struct pipeline *p)
159 {
160 	struct comp_dev *cd;
161 	int ret;
162 
163 	/* Get pipeline host component */
164 	cd = tb_get_pipeline_host(p);
165 
166 	ret = pipeline_trigger(cd->pipeline, cd, COMP_TRIGGER_STOP);
167 	if (ret < 0) {
168 		fprintf(stderr, "error: Failed to stop pipeline command: %s\n",
169 			strerror(ret));
170 	}
171 
172 	return ret;
173 }
174 
175 /* set up pcm params, prepare and trigger pipeline */
tb_pipeline_reset(struct ipc * ipc,struct pipeline * p)176 int tb_pipeline_reset(struct ipc *ipc, struct pipeline *p)
177 {
178 	struct comp_dev *cd;
179 	int ret;
180 
181 	/* Get pipeline host component */
182 	cd = tb_get_pipeline_host(p);
183 
184 	ret = pipeline_reset(p, cd);
185 	if (ret < 0)
186 		fprintf(stderr, "error: pipeline reset\n");
187 
188 	return ret;
189 }
190 
191 /* pipeline pcm params */
tb_pipeline_params(struct testbench_prm * tp,struct ipc * ipc,struct pipeline * p,struct tplg_context * ctx)192 int tb_pipeline_params(struct testbench_prm *tp, struct ipc *ipc, struct pipeline *p,
193 		       struct tplg_context *ctx)
194 {
195 	struct ipc_comp_dev *pcm_dev;
196 	struct comp_dev *cd;
197 	struct sof_ipc_pcm_params params = {{0}};
198 	char message[DEBUG_MSG_LEN];
199 	int fs_period;
200 	int period;
201 	int ret = 0;
202 
203 	if (!p) {
204 		fprintf(stderr, "error: pipeline is NULL\n");
205 		return -EINVAL;
206 	}
207 
208 	period = p->period;
209 
210 	/* Compute period from sample rates */
211 	fs_period = (int)(0.9999 + tp->fs_in * period / 1e6);
212 	sprintf(message, "period sample count %d\n", fs_period);
213 	debug_print(message);
214 
215 	/* set pcm params */
216 	params.comp_id = p->comp_id;
217 	params.params.buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED;
218 	params.params.frame_fmt = tp->frame_fmt;
219 	params.params.rate = tp->fs_in;
220 	params.params.channels = tp->channels_in;
221 
222 	switch (params.params.frame_fmt) {
223 	case SOF_IPC_FRAME_S16_LE:
224 		params.params.sample_container_bytes = 2;
225 		params.params.sample_valid_bytes = 2;
226 		break;
227 	case SOF_IPC_FRAME_S24_4LE:
228 		params.params.sample_container_bytes = 4;
229 		params.params.sample_valid_bytes = 3;
230 		break;
231 	case SOF_IPC_FRAME_S32_LE:
232 		params.params.sample_container_bytes = 4;
233 		params.params.sample_valid_bytes = 4;
234 		break;
235 	default:
236 		fprintf(stderr, "error: invalid frame format\n");
237 		return -EINVAL;
238 	}
239 
240 	params.params.host_period_bytes = fs_period * params.params.channels *
241 		params.params.sample_container_bytes;
242 
243 	/* get scheduling component device for pipeline*/
244 	pcm_dev = ipc_get_comp_by_id(ipc, p->sched_id);
245 	if (!pcm_dev) {
246 		fprintf(stderr, "error: ipc get comp\n");
247 		return -EINVAL;
248 	}
249 
250 	/* Get pipeline host component */
251 	cd = tb_get_pipeline_host(p);
252 
253 	/* Set pipeline params direction from scheduling component */
254 	params.params.direction = cd->direction;
255 
256 	printf("test params: rate %d channels %d format %d\n",
257 	       params.params.rate, params.params.channels,
258 	       params.params.frame_fmt);
259 
260 	/* pipeline params */
261 	ret = pipeline_params(p, cd, &params);
262 	if (ret < 0)
263 		fprintf(stderr, "error: pipeline_params\n");
264 
265 	return ret;
266 }
267 
268 /* print debug messages */
debug_print(char * message)269 void debug_print(char *message)
270 {
271 	if (debug)
272 		printf("debug: %s", message);
273 }
274 
275 /* enable trace in testbench */
tb_enable_trace(bool enable)276 void tb_enable_trace(bool enable)
277 {
278 	test_bench_trace = enable;
279 	if (enable)
280 		debug_print("trace print enabled\n");
281 	else
282 		debug_print("trace print disabled\n");
283 }
284