1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2017 Intel Corporation. All rights reserved.
4 //
5 // Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
6 // Liam Girdwood <liam.r.girdwood@linux.intel.com>
7 // Keyon Jie <yang.jie@linux.intel.com>
8
9 #include <sof/audio/eq_fir/eq_fir.h>
10 #include <sof/audio/buffer.h>
11 #include <sof/audio/component.h>
12 #include <sof/audio/pipeline.h>
13 #include <sof/audio/ipc-config.h>
14 #include <sof/common.h>
15 #include <sof/debug/panic.h>
16 #include <sof/ipc/msg.h>
17 #include <sof/lib/alloc.h>
18 #include <sof/lib/memory.h>
19 #include <sof/lib/uuid.h>
20 #include <sof/list.h>
21 #include <sof/math/fir_config.h>
22 #include <sof/platform.h>
23 #include <sof/string.h>
24 #include <sof/ut.h>
25 #include <sof/trace/trace.h>
26 #include <ipc/control.h>
27 #include <ipc/stream.h>
28 #include <ipc/topology.h>
29 #include <kernel/abi.h>
30 #include <user/eq.h>
31 #include <user/fir.h>
32 #include <user/trace.h>
33 #include <errno.h>
34 #include <stddef.h>
35 #include <stdint.h>
36
37 static const struct comp_driver comp_eq_fir;
38
39 /* 43a90ce7-f3a5-41df-ac06-ba98651ae6a3 */
40 DECLARE_SOF_RT_UUID("eq-fir", eq_fir_uuid, 0x43a90ce7, 0xf3a5, 0x41df,
41 0xac, 0x06, 0xba, 0x98, 0x65, 0x1a, 0xe6, 0xa3);
42
43 DECLARE_TR_CTX(eq_fir_tr, SOF_UUID(eq_fir_uuid), LOG_LEVEL_INFO);
44
45 /* src component private data */
46 struct comp_data {
47 struct fir_state_32x16 fir[PLATFORM_MAX_CHANNELS]; /**< filters state */
48 struct comp_data_blob_handler *model_handler;
49 struct sof_eq_fir_config *config;
50 int32_t *fir_delay; /**< pointer to allocated RAM */
51 size_t fir_delay_size; /**< allocated size */
52 void (*eq_fir_func)(struct fir_state_32x16 fir[],
53 const struct audio_stream *source,
54 struct audio_stream *sink,
55 int frames, int nch);
56 };
57
58 /*
59 * The optimized FIR functions variants need to be updated into function
60 * set_fir_func.
61 */
62
63 #if FIR_HIFI3 || FIR_HIFIEP
64 #if CONFIG_FORMAT_S16LE
set_s16_fir(struct comp_data * cd)65 static inline void set_s16_fir(struct comp_data *cd)
66 {
67 cd->eq_fir_func = eq_fir_2x_s16;
68 }
69 #endif /* CONFIG_FORMAT_S16LE */
70 #if CONFIG_FORMAT_S24LE
set_s24_fir(struct comp_data * cd)71 static inline void set_s24_fir(struct comp_data *cd)
72 {
73 cd->eq_fir_func = eq_fir_2x_s24;
74 }
75 #endif /* CONFIG_FORMAT_S24LE */
76 #if CONFIG_FORMAT_S32LE
set_s32_fir(struct comp_data * cd)77 static inline void set_s32_fir(struct comp_data *cd)
78 {
79 cd->eq_fir_func = eq_fir_2x_s32;
80 }
81 #endif /* CONFIG_FORMAT_S32LE */
82
83 #else
84 /* FIR_GENERIC */
85 #if CONFIG_FORMAT_S16LE
set_s16_fir(struct comp_data * cd)86 static inline void set_s16_fir(struct comp_data *cd)
87 {
88 cd->eq_fir_func = eq_fir_s16;
89 }
90 #endif /* CONFIG_FORMAT_S16LE */
91 #if CONFIG_FORMAT_S24LE
set_s24_fir(struct comp_data * cd)92 static inline void set_s24_fir(struct comp_data *cd)
93 {
94 cd->eq_fir_func = eq_fir_s24;
95 }
96 #endif /* CONFIG_FORMAT_S24LE */
97 #if CONFIG_FORMAT_S32LE
set_s32_fir(struct comp_data * cd)98 static inline void set_s32_fir(struct comp_data *cd)
99 {
100 cd->eq_fir_func = eq_fir_s32;
101 }
102 #endif /* CONFIG_FORMAT_S32LE */
103 #endif
104
set_fir_func(struct comp_dev * dev)105 static inline int set_fir_func(struct comp_dev *dev)
106 {
107 struct comp_data *cd = comp_get_drvdata(dev);
108 struct comp_buffer *sourceb;
109
110 sourceb = list_first_item(&dev->bsource_list, struct comp_buffer,
111 sink_list);
112
113 switch (sourceb->stream.frame_fmt) {
114 #if CONFIG_FORMAT_S16LE
115 case SOF_IPC_FRAME_S16_LE:
116 comp_info(dev, "set_fir_func(), SOF_IPC_FRAME_S16_LE");
117 set_s16_fir(cd);
118 break;
119 #endif /* CONFIG_FORMAT_S16LE */
120 #if CONFIG_FORMAT_S24LE
121 case SOF_IPC_FRAME_S24_4LE:
122 comp_info(dev, "set_fir_func(), SOF_IPC_FRAME_S24_4LE");
123 set_s24_fir(cd);
124 break;
125 #endif /* CONFIG_FORMAT_S24LE */
126 #if CONFIG_FORMAT_S32LE
127 case SOF_IPC_FRAME_S32_LE:
128 comp_info(dev, "set_fir_func(), SOF_IPC_FRAME_S32_LE");
129 set_s32_fir(cd);
130 break;
131 #endif /* CONFIG_FORMAT_S32LE */
132 default:
133 comp_err(dev, "set_fir_func(), invalid frame_fmt");
134 return -EINVAL;
135 }
136 return 0;
137 }
138
139 /* Pass-through functions to replace FIR core while not configured for
140 * response.
141 */
142
eq_fir_passthrough(struct fir_state_32x16 fir[],const struct audio_stream * source,struct audio_stream * sink,int frames,int nch)143 static void eq_fir_passthrough(struct fir_state_32x16 fir[],
144 const struct audio_stream *source,
145 struct audio_stream *sink,
146 int frames, int nch)
147 {
148 audio_stream_copy(source, 0, sink, 0, frames * nch);
149 }
150
eq_fir_free_delaylines(struct comp_data * cd)151 static void eq_fir_free_delaylines(struct comp_data *cd)
152 {
153 struct fir_state_32x16 *fir = cd->fir;
154 int i = 0;
155
156 /* Free the common buffer for all EQs and point then
157 * each FIR channel delay line to NULL.
158 */
159 rfree(cd->fir_delay);
160 cd->fir_delay = NULL;
161 cd->fir_delay_size = 0;
162 for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
163 fir[i].delay = NULL;
164 }
165
eq_fir_init_coef(struct sof_eq_fir_config * config,struct fir_state_32x16 * fir,int nch)166 static int eq_fir_init_coef(struct sof_eq_fir_config *config,
167 struct fir_state_32x16 *fir, int nch)
168 {
169 struct sof_fir_coef_data *lookup[SOF_EQ_FIR_MAX_RESPONSES];
170 struct sof_fir_coef_data *eq;
171 int16_t *assign_response;
172 int16_t *coef_data;
173 size_t size_sum = 0;
174 int resp = 0;
175 int i;
176 int j;
177 int s;
178
179 comp_cl_info(&comp_eq_fir, "eq_fir_init_coef(), response assign for %u channels, %u responses",
180 config->channels_in_config,
181 config->number_of_responses);
182
183 /* Sanity checks */
184 if (nch > PLATFORM_MAX_CHANNELS ||
185 config->channels_in_config > PLATFORM_MAX_CHANNELS ||
186 !config->channels_in_config) {
187 comp_cl_err(&comp_eq_fir, "eq_fir_init_coef(), invalid channels count");
188 return -EINVAL;
189 }
190 if (config->number_of_responses > SOF_EQ_FIR_MAX_RESPONSES) {
191 comp_cl_err(&comp_eq_fir, "eq_fir_init_coef(), # of resp exceeds max");
192 return -EINVAL;
193 }
194
195 /* Collect index of respose start positions in all_coefficients[] */
196 j = 0;
197 assign_response = ASSUME_ALIGNED(&config->data[0], 4);
198 coef_data = ASSUME_ALIGNED(&config->data[config->channels_in_config],
199 4);
200 for (i = 0; i < SOF_EQ_FIR_MAX_RESPONSES; i++) {
201 if (i < config->number_of_responses) {
202 eq = (struct sof_fir_coef_data *)&coef_data[j];
203 lookup[i] = eq;
204 j += SOF_FIR_COEF_NHEADER + coef_data[j];
205 } else {
206 lookup[i] = NULL;
207 }
208 }
209
210 /* Initialize 1st phase */
211 for (i = 0; i < nch; i++) {
212 /* Check for not reading past blob response to channel assign
213 * map. The previous channel response is assigned for any
214 * additional channels in the stream. It allows to use single
215 * channel configuration to setup multi channel equalization
216 * with the same response.
217 */
218 if (i < config->channels_in_config)
219 resp = assign_response[i];
220
221 if (resp < 0) {
222 /* Initialize EQ channel to bypass and continue with
223 * next channel response.
224 */
225 comp_cl_info(&comp_eq_fir, "eq_fir_init_coef(), ch %d is set to bypass",
226 i);
227 fir_reset(&fir[i]);
228 continue;
229 }
230
231 if (resp >= config->number_of_responses) {
232 comp_cl_err(&comp_eq_fir, "eq_fir_init_coef(), requested response %d exceeds what has been defined",
233 resp);
234 return -EINVAL;
235 }
236
237 /* Initialize EQ coefficients. */
238 eq = lookup[resp];
239 s = fir_delay_size(eq);
240 if (s > 0) {
241 size_sum += s;
242 } else {
243 comp_cl_info(&comp_eq_fir, "eq_fir_init_coef(), FIR length %d is invalid",
244 eq->length);
245 return -EINVAL;
246 }
247
248 #if defined FIR_MAX_LENGTH_BUILD_SPECIFIC
249 if (fir[i].taps * nch > FIR_MAX_LENGTH_BUILD_SPECIFIC) {
250 comp_cl_err(&comp_eq_fir, "Filter length %d exceeds limitation for build.",
251 fir[i].taps);
252 return -EINVAL;
253 }
254 #endif
255
256 fir_init_coef(&fir[i], eq);
257 comp_cl_info(&comp_eq_fir, "eq_fir_init_coef(), ch %d is set to response = %d",
258 i, resp);
259 }
260
261 return size_sum;
262 }
263
eq_fir_init_delay(struct fir_state_32x16 * fir,int32_t * delay_start,int nch)264 static void eq_fir_init_delay(struct fir_state_32x16 *fir,
265 int32_t *delay_start, int nch)
266 {
267 int32_t *fir_delay = delay_start;
268 int i;
269
270 /* Initialize 2nd phase to set EQ delay lines pointers */
271 for (i = 0; i < nch; i++) {
272 if (fir[i].length > 0)
273 fir_init_delay(&fir[i], &fir_delay);
274 }
275 }
276
eq_fir_setup(struct comp_data * cd,int nch)277 static int eq_fir_setup(struct comp_data *cd, int nch)
278 {
279 int delay_size;
280
281 /* Free existing FIR channels data if it was allocated */
282 eq_fir_free_delaylines(cd);
283
284 /* Set coefficients for each channel EQ from coefficient blob */
285 delay_size = eq_fir_init_coef(cd->config, cd->fir, nch);
286 if (delay_size < 0)
287 return delay_size; /* Contains error code */
288
289 /* If all channels were set to bypass there's no need to
290 * allocate delay. Just return with success.
291 */
292 if (!delay_size)
293 return 0;
294
295 /* Allocate all FIR channels data in a big chunk and clear it */
296 cd->fir_delay = rballoc(0, SOF_MEM_CAPS_RAM, delay_size);
297 if (!cd->fir_delay) {
298 comp_cl_err(&comp_eq_fir, "eq_fir_setup(), delay allocation failed for size %d",
299 delay_size);
300 return -ENOMEM;
301 }
302
303 memset(cd->fir_delay, 0, delay_size);
304 cd->fir_delay_size = delay_size;
305
306 /* Assign delay line to each channel EQ */
307 eq_fir_init_delay(cd->fir, cd->fir_delay, nch);
308 return 0;
309 }
310
311 /*
312 * End of algorithm code. Next the standard component methods.
313 */
314
eq_fir_new(const struct comp_driver * drv,struct comp_ipc_config * config,void * spec)315 static struct comp_dev *eq_fir_new(const struct comp_driver *drv,
316 struct comp_ipc_config *config,
317 void *spec)
318 {
319 struct comp_dev *dev = NULL;
320 struct comp_data *cd = NULL;
321 struct ipc_config_process *ipc_fir = spec;
322 size_t bs = ipc_fir->size;
323 int i;
324 int ret;
325
326 comp_cl_info(&comp_eq_fir, "eq_fir_new()");
327
328 /* Check first before proceeding with dev and cd that coefficients
329 * blob size is sane.
330 */
331 if (bs > SOF_EQ_FIR_MAX_SIZE) {
332 comp_cl_err(&comp_eq_fir, "eq_fir_new(): coefficients blob size = %u > SOF_EQ_FIR_MAX_SIZE",
333 bs);
334 return NULL;
335 }
336
337 dev = comp_alloc(drv, sizeof(*dev));
338 if (!dev)
339 return NULL;
340 dev->ipc_config = *config;
341
342 cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd));
343 if (!cd)
344 goto fail;
345
346 comp_set_drvdata(dev, cd);
347
348 cd->eq_fir_func = NULL;
349 cd->fir_delay = NULL;
350 cd->fir_delay_size = 0;
351
352 /* component model data handler */
353 cd->model_handler = comp_data_blob_handler_new(dev);
354 if (!cd->model_handler) {
355 comp_cl_err(&comp_eq_fir, "eq_fir_new(): comp_data_blob_handler_new() failed.");
356 goto cd_fail;
357 }
358
359 /* Allocate and make a copy of the coefficients blob and reset FIR. If
360 * the EQ is configured later in run-time the size is zero.
361 */
362 ret = comp_init_data_blob(cd->model_handler, bs, ipc_fir->data);
363 if (ret < 0) {
364 comp_cl_err(&comp_eq_fir, "eq_fir_new(): comp_init_data_blob() failed.");
365 goto cd_fail;
366 }
367
368 for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
369 fir_reset(&cd->fir[i]);
370
371 dev->state = COMP_STATE_READY;
372 return dev;
373
374 cd_fail:
375 comp_data_blob_handler_free(cd->model_handler);
376 rfree(cd);
377 fail:
378 rfree(dev);
379 return NULL;
380 }
381
eq_fir_free(struct comp_dev * dev)382 static void eq_fir_free(struct comp_dev *dev)
383 {
384 struct comp_data *cd = comp_get_drvdata(dev);
385
386 comp_info(dev, "eq_fir_free()");
387
388 eq_fir_free_delaylines(cd);
389 comp_data_blob_handler_free(cd->model_handler);
390
391 rfree(cd);
392 rfree(dev);
393 }
394
fir_cmd_get_data(struct comp_dev * dev,struct sof_ipc_ctrl_data * cdata,int max_size)395 static int fir_cmd_get_data(struct comp_dev *dev,
396 struct sof_ipc_ctrl_data *cdata, int max_size)
397 {
398 struct comp_data *cd = comp_get_drvdata(dev);
399 int ret = 0;
400
401 switch (cdata->cmd) {
402 case SOF_CTRL_CMD_BINARY:
403 comp_info(dev, "fir_cmd_get_data(), SOF_CTRL_CMD_BINARY");
404 ret = comp_data_blob_get_cmd(cd->model_handler, cdata,
405 max_size);
406 break;
407 default:
408 comp_err(dev, "fir_cmd_get_data(): invalid cdata->cmd");
409 ret = -EINVAL;
410 break;
411 }
412 return ret;
413 }
414
fir_cmd_set_data(struct comp_dev * dev,struct sof_ipc_ctrl_data * cdata)415 static int fir_cmd_set_data(struct comp_dev *dev,
416 struct sof_ipc_ctrl_data *cdata)
417 {
418 struct comp_data *cd = comp_get_drvdata(dev);
419 int ret = 0;
420
421 switch (cdata->cmd) {
422 case SOF_CTRL_CMD_BINARY:
423 comp_info(dev, "fir_cmd_set_data(), SOF_CTRL_CMD_BINARY");
424 ret = comp_data_blob_set_cmd(cd->model_handler, cdata);
425 break;
426 default:
427 comp_err(dev, "fir_cmd_set_data(): invalid cdata->cmd");
428 ret = -EINVAL;
429 break;
430 }
431
432 return ret;
433 }
434
435 /* used to pass standard and bespoke commands (with data) to component */
eq_fir_cmd(struct comp_dev * dev,int cmd,void * data,int max_data_size)436 static int eq_fir_cmd(struct comp_dev *dev, int cmd, void *data,
437 int max_data_size)
438 {
439 struct sof_ipc_ctrl_data *cdata = ASSUME_ALIGNED(data, 4);
440 int ret = 0;
441
442 comp_info(dev, "eq_fir_cmd()");
443
444 switch (cmd) {
445 case COMP_CMD_SET_DATA:
446 ret = fir_cmd_set_data(dev, cdata);
447 break;
448 case COMP_CMD_GET_DATA:
449 ret = fir_cmd_get_data(dev, cdata, max_data_size);
450 break;
451 default:
452 comp_err(dev, "eq_fir_cmd(): invalid command");
453 ret = -EINVAL;
454 }
455
456 return ret;
457 }
458
eq_fir_trigger(struct comp_dev * dev,int cmd)459 static int eq_fir_trigger(struct comp_dev *dev, int cmd)
460 {
461 struct comp_data *cd = comp_get_drvdata(dev);
462
463 comp_info(dev, "eq_fir_trigger()");
464
465 if (cmd == COMP_TRIGGER_START || cmd == COMP_TRIGGER_RELEASE)
466 assert(cd->eq_fir_func);
467
468 return comp_set_state(dev, cmd);
469 }
470
eq_fir_process(struct comp_dev * dev,struct comp_buffer * source,struct comp_buffer * sink,int frames,uint32_t source_bytes,uint32_t sink_bytes)471 static void eq_fir_process(struct comp_dev *dev, struct comp_buffer *source,
472 struct comp_buffer *sink, int frames,
473 uint32_t source_bytes, uint32_t sink_bytes)
474 {
475 struct comp_data *cd = comp_get_drvdata(dev);
476
477 buffer_invalidate(source, source_bytes);
478
479 cd->eq_fir_func(cd->fir, &source->stream, &sink->stream, frames,
480 source->stream.channels);
481
482 buffer_writeback(sink, sink_bytes);
483
484 /* calc new free and available */
485 comp_update_buffer_consume(source, source_bytes);
486 comp_update_buffer_produce(sink, sink_bytes);
487 }
488
489 /* copy and process stream data from source to sink buffers */
eq_fir_copy(struct comp_dev * dev)490 static int eq_fir_copy(struct comp_dev *dev)
491 {
492 struct comp_copy_limits cl;
493 struct comp_buffer *sourceb;
494 struct comp_buffer *sinkb;
495 struct comp_data *cd = comp_get_drvdata(dev);
496 int ret;
497 int n;
498
499 comp_dbg(dev, "eq_fir_copy()");
500
501 sourceb = list_first_item(&dev->bsource_list, struct comp_buffer,
502 sink_list);
503
504 /* Check for changed configuration */
505 if (comp_is_new_data_blob_available(cd->model_handler)) {
506 cd->config = comp_get_data_blob(cd->model_handler, NULL, NULL);
507 ret = eq_fir_setup(cd, sourceb->stream.channels);
508 if (ret < 0) {
509 comp_err(dev, "eq_fir_copy(), failed FIR setup");
510 return ret;
511 }
512 }
513
514 sinkb = list_first_item(&dev->bsink_list, struct comp_buffer,
515 source_list);
516
517 /* Get source, sink, number of frames etc. to process. */
518 comp_get_copy_limits_with_lock(sourceb, sinkb, &cl);
519
520 /*
521 * Process only even number of frames with the FIR function. The
522 * optimized filter function loads the successive input samples from
523 * internal delay line with a 64 bit load operation. The other odd
524 * (or any) number of frames capable FIR version would permanently
525 * break the delay line alignment if called with odd number of frames
526 * so it can't be used here.
527 */
528 if (cl.frames >= 2) {
529 n = (cl.frames >> 1) << 1;
530
531 /* Run EQ function */
532 eq_fir_process(dev, sourceb, sinkb, n,
533 n * cl.source_frame_bytes,
534 n * cl.sink_frame_bytes);
535 }
536
537 return 0;
538 }
539
eq_fir_prepare(struct comp_dev * dev)540 static int eq_fir_prepare(struct comp_dev *dev)
541 {
542 struct comp_data *cd = comp_get_drvdata(dev);
543 struct comp_buffer *sourceb;
544 struct comp_buffer *sinkb;
545 uint32_t sink_period_bytes;
546 int ret;
547
548 comp_info(dev, "eq_fir_prepare()");
549
550 ret = comp_set_state(dev, COMP_TRIGGER_PREPARE);
551 if (ret < 0)
552 return ret;
553
554 if (ret == COMP_STATUS_STATE_ALREADY_SET)
555 return PPL_STATUS_PATH_STOP;
556
557 /* EQ component will only ever have 1 source and 1 sink buffer. */
558 sourceb = list_first_item(&dev->bsource_list,
559 struct comp_buffer, sink_list);
560 sinkb = list_first_item(&dev->bsink_list,
561 struct comp_buffer, source_list);
562
563 sink_period_bytes = audio_stream_period_bytes(&sinkb->stream,
564 dev->frames);
565
566 if (sinkb->stream.size < sink_period_bytes) {
567 comp_err(dev, "eq_fir_prepare(): sink buffer size %d is insufficient < %d",
568 sinkb->stream.size, sink_period_bytes);
569 ret = -ENOMEM;
570 goto err;
571 }
572
573 cd->config = comp_get_data_blob(cd->model_handler, NULL, NULL);
574
575 if (cd->config) {
576 ret = eq_fir_setup(cd, sourceb->stream.channels);
577 if (ret < 0) {
578 comp_err(dev, "eq_fir_prepare(): eq_fir_setup failed.");
579 goto err;
580 }
581
582 ret = set_fir_func(dev);
583 return ret;
584 }
585
586 cd->eq_fir_func = eq_fir_passthrough;
587
588 return ret;
589
590 err:
591 comp_set_state(dev, COMP_TRIGGER_RESET);
592 return ret;
593 }
594
eq_fir_reset(struct comp_dev * dev)595 static int eq_fir_reset(struct comp_dev *dev)
596 {
597 int i;
598 struct comp_data *cd = comp_get_drvdata(dev);
599
600 comp_info(dev, "eq_fir_reset()");
601
602 eq_fir_free_delaylines(cd);
603
604 cd->eq_fir_func = NULL;
605 for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
606 fir_reset(&cd->fir[i]);
607
608 comp_set_state(dev, COMP_TRIGGER_RESET);
609 return 0;
610 }
611
612 static const struct comp_driver comp_eq_fir = {
613 .type = SOF_COMP_EQ_FIR,
614 .uid = SOF_RT_UUID(eq_fir_uuid),
615 .tctx = &eq_fir_tr,
616 .ops = {
617 .create = eq_fir_new,
618 .free = eq_fir_free,
619 .cmd = eq_fir_cmd,
620 .trigger = eq_fir_trigger,
621 .copy = eq_fir_copy,
622 .prepare = eq_fir_prepare,
623 .reset = eq_fir_reset,
624 },
625 };
626
627 static SHARED_DATA struct comp_driver_info comp_eq_fir_info = {
628 .drv = &comp_eq_fir,
629 };
630
sys_comp_eq_fir_init(void)631 UT_STATIC void sys_comp_eq_fir_init(void)
632 {
633 comp_register(platform_shared_get(&comp_eq_fir_info,
634 sizeof(comp_eq_fir_info)));
635 }
636
637 DECLARE_MODULE(sys_comp_eq_fir_init);
638