1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2020 Google LLC. All rights reserved.
4 //
5 // Author: Pin-chih Lin <johnylin@google.com>
6
7 #include <sof/audio/buffer.h>
8 #include <sof/audio/crossover/crossover_algorithm.h>
9 #include <sof/audio/drc/drc_algorithm.h>
10 #include <sof/audio/multiband_drc/multiband_drc.h>
11 #include <sof/audio/format.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/numbers.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 <user/eq.h>
30 #include <user/trace.h>
31 #include <errno.h>
32 #include <stddef.h>
33 #include <stdint.h>
34
35 static const struct comp_driver comp_multiband_drc;
36
37 /* 0d9f2256-8e4f-47b3-8448-239a334f1191 */
38 DECLARE_SOF_RT_UUID("multiband_drc", multiband_drc_uuid, 0x0d9f2256, 0x8e4f, 0x47b3,
39 0x84, 0x48, 0x23, 0x9a, 0x33, 0x4f, 0x11, 0x91);
40
41 DECLARE_TR_CTX(multiband_drc_tr, SOF_UUID(multiband_drc_uuid), LOG_LEVEL_INFO);
42
multiband_drc_iir_reset_state_ch(struct iir_state_df2t * iir)43 static inline void multiband_drc_iir_reset_state_ch(struct iir_state_df2t *iir)
44 {
45 rfree(iir->coef);
46 rfree(iir->delay);
47
48 iir->coef = NULL;
49 iir->delay = NULL;
50 }
51
multiband_drc_reset_state(struct multiband_drc_state * state)52 static inline void multiband_drc_reset_state(struct multiband_drc_state *state)
53 {
54 int i;
55
56 /* Reset emphasis eq-iir state */
57 for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
58 multiband_drc_iir_reset_state_ch(&state->emphasis[i]);
59
60 /* Reset crossover state */
61 for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
62 crossover_reset_state_ch(&state->crossover[i]);
63
64 /* Reset drc kernel state */
65 for (i = 0; i < SOF_MULTIBAND_DRC_MAX_BANDS; i++)
66 drc_reset_state(&state->drc[i]);
67
68 /* Reset deemphasis eq-iir state */
69 for (i = 0; i < PLATFORM_MAX_CHANNELS; i++)
70 multiband_drc_iir_reset_state_ch(&state->deemphasis[i]);
71 }
72
multiband_drc_eq_init_coef_ch(struct sof_eq_iir_biquad_df2t * coef,struct iir_state_df2t * eq)73 static int multiband_drc_eq_init_coef_ch(struct sof_eq_iir_biquad_df2t *coef,
74 struct iir_state_df2t *eq)
75 {
76 int ret;
77
78 eq->coef = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM,
79 sizeof(struct sof_eq_iir_biquad_df2t) * SOF_EMP_DEEMP_BIQUADS);
80 if (!eq->coef)
81 return -ENOMEM;
82
83 /* Coefficients of the first biquad and second biquad */
84 ret = memcpy_s(eq->coef, sizeof(struct sof_eq_iir_biquad_df2t) * SOF_EMP_DEEMP_BIQUADS,
85 coef, sizeof(struct sof_eq_iir_biquad_df2t) * SOF_EMP_DEEMP_BIQUADS);
86 assert(!ret);
87
88 /* EQ filters are two 2nd order filters, so only need 4 delay slots
89 * delay[0..1] -> state for first biquad
90 * delay[2..3] -> state for second biquad
91 */
92 eq->delay = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM,
93 sizeof(uint64_t) * CROSSOVER_NUM_DELAYS_LR4);
94 if (!eq->delay)
95 return -ENOMEM;
96
97 eq->biquads = SOF_EMP_DEEMP_BIQUADS;
98 eq->biquads_in_series = SOF_EMP_DEEMP_BIQUADS;
99
100 return 0;
101 }
102
multiband_drc_init_coef(struct multiband_drc_comp_data * cd,int16_t nch,uint32_t rate)103 static int multiband_drc_init_coef(struct multiband_drc_comp_data *cd, int16_t nch, uint32_t rate)
104 {
105 struct sof_eq_iir_biquad_df2t *crossover;
106 struct sof_eq_iir_biquad_df2t *emphasis;
107 struct sof_eq_iir_biquad_df2t *deemphasis;
108 struct sof_multiband_drc_config *config = cd->config;
109 struct multiband_drc_state *state = &cd->state;
110 uint32_t sample_bytes = get_sample_bytes(cd->source_format);
111 int num_bands = cd->config->num_bands;
112 int i, ch, ret;
113
114 if (!config) {
115 comp_cl_err(&comp_multiband_drc, "multiband_drc_init_coef(), no config is set");
116 return -EINVAL;
117 }
118
119 /* Sanity checks */
120 if (nch > PLATFORM_MAX_CHANNELS) {
121 comp_cl_err(&comp_multiband_drc,
122 "multiband_drc_init_coef(), invalid channels count(%i)",
123 nch);
124 return -EINVAL;
125 }
126 if (config->num_bands > SOF_MULTIBAND_DRC_MAX_BANDS) {
127 comp_cl_err(&comp_multiband_drc,
128 "multiband_drc_init_coef(), invalid bands count(%i)",
129 config->num_bands);
130 return -EINVAL;
131 }
132
133 comp_cl_info(&comp_multiband_drc,
134 "multiband_drc_init_coef(), initiliazing %i-way crossover",
135 config->num_bands);
136
137 /* Crossover: collect the coef array and assign it to every channel */
138 crossover = config->crossover_coef;
139 for (ch = 0; ch < nch; ch++) {
140 ret = crossover_init_coef_ch(crossover, &state->crossover[ch],
141 config->num_bands);
142 /* Free all previously allocated blocks in case of an error */
143 if (ret < 0) {
144 comp_cl_err(&comp_multiband_drc,
145 "multiband_drc_init_coef(), could not assign coeffs to ch %d",
146 ch);
147 goto err;
148 }
149 }
150
151 comp_cl_info(&comp_multiband_drc, "multiband_drc_init_coef(), initiliazing emphasis_eq");
152
153 /* Emphasis: collect the coef array and assign it to every channel */
154 emphasis = config->emp_coef;
155 for (ch = 0; ch < nch; ch++) {
156 ret = multiband_drc_eq_init_coef_ch(emphasis, &state->emphasis[ch]);
157 /* Free all previously allocated blocks in case of an error */
158 if (ret < 0) {
159 comp_cl_err(&comp_multiband_drc,
160 "multiband_drc_init_coef(), could not assign coeffs to ch %d",
161 ch);
162 goto err;
163 }
164 }
165
166 comp_cl_info(&comp_multiband_drc, "multiband_drc_init_coef(), initiliazing deemphasis_eq");
167
168 /* Deemphasis: collect the coef array and assign it to every channel */
169 deemphasis = config->deemp_coef;
170 for (ch = 0; ch < nch; ch++) {
171 ret = multiband_drc_eq_init_coef_ch(deemphasis, &state->deemphasis[ch]);
172 /* Free all previously allocated blocks in case of an error */
173 if (ret < 0) {
174 comp_cl_err(&comp_multiband_drc,
175 "multiband_drc_init_coef(), could not assign coeffs to ch %d",
176 ch);
177 goto err;
178 }
179 }
180
181 /* Allocate all DRC pre-delay buffers and set delay time with band number */
182 for (i = 0; i < num_bands; i++) {
183 comp_cl_info(&comp_multiband_drc,
184 "multiband_drc_init_coef(), initiliazing drc band %d", i);
185
186 ret = drc_init_pre_delay_buffers(&state->drc[i], (size_t)sample_bytes, (int)nch);
187 if (ret < 0) {
188 comp_cl_err(&comp_multiband_drc,
189 "multiband_drc_init_coef(), could not init pre delay buffers");
190 goto err;
191 }
192
193 ret = drc_set_pre_delay_time(&state->drc[i],
194 cd->config->drc_coef[i].pre_delay_time, rate);
195 if (ret < 0) {
196 comp_cl_err(&comp_multiband_drc,
197 "multiband_drc_init_coef(), could not set pre delay time");
198 goto err;
199 }
200 }
201
202 return 0;
203
204 err:
205 multiband_drc_reset_state(state);
206 return ret;
207 }
208
multiband_drc_setup(struct multiband_drc_comp_data * cd,int16_t channels,uint32_t rate)209 static int multiband_drc_setup(struct multiband_drc_comp_data *cd, int16_t channels, uint32_t rate)
210 {
211 int ret;
212
213 /* Reset any previous state */
214 multiband_drc_reset_state(&cd->state);
215
216 /* Setup Crossover, Emphasis EQ, Deemphasis EQ, and DRC */
217 ret = multiband_drc_init_coef(cd, channels, rate);
218 if (ret < 0)
219 return ret;
220
221 return 0;
222 }
223
224 /*
225 * End of Multiband DRC setup code. Next the standard component methods.
226 */
227
multiband_drc_new(const struct comp_driver * drv,struct comp_ipc_config * config,void * spec)228 static struct comp_dev *multiband_drc_new(const struct comp_driver *drv,
229 struct comp_ipc_config *config,
230 void *spec)
231 {
232 struct comp_dev *dev = NULL;
233 struct multiband_drc_comp_data *cd = NULL;
234 struct ipc_config_process *ipc_multiband_drc = spec;
235 size_t bs = ipc_multiband_drc->size;
236 int ret;
237
238 comp_cl_info(&comp_multiband_drc, "multiband_drc_new()");
239
240 /* Check first before proceeding with dev and cd that coefficients
241 * blob size is sane.
242 */
243 if (bs > SOF_MULTIBAND_DRC_MAX_BLOB_SIZE) {
244 comp_cl_err(&comp_multiband_drc,
245 "multiband_drc_new(), error: configuration blob size = %u > %d",
246 bs, SOF_MULTIBAND_DRC_MAX_BLOB_SIZE);
247 return NULL;
248 }
249
250 dev = comp_alloc(drv, sizeof(*dev));
251 if (!dev)
252 return NULL;
253 dev->ipc_config = *config;
254
255 cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd));
256 if (!cd)
257 goto fail;
258
259 comp_set_drvdata(dev, cd);
260
261 cd->process_enabled = false;
262 cd->multiband_drc_func = NULL;
263 cd->crossover_split = NULL;
264
265 /* Handler for configuration data */
266 cd->model_handler = comp_data_blob_handler_new(dev);
267 if (!cd->model_handler) {
268 comp_cl_err(&comp_multiband_drc,
269 "multiband_drc_new(): comp_data_blob_handler_new() failed.");
270 goto cd_fail;
271 }
272
273 /* Get configuration data and reset DRC state */
274 ret = comp_init_data_blob(cd->model_handler, bs, ipc_multiband_drc->data);
275 if (ret < 0) {
276 comp_cl_err(&comp_multiband_drc,
277 "multiband_drc_new(): comp_init_data_blob() failed.");
278 goto cd_fail;
279 }
280 multiband_drc_reset_state(&cd->state);
281
282 dev->state = COMP_STATE_READY;
283 return dev;
284
285 cd_fail:
286 comp_data_blob_handler_free(cd->model_handler);
287 rfree(cd);
288 fail:
289 rfree(dev);
290 return NULL;
291 }
292
multiband_drc_free(struct comp_dev * dev)293 static void multiband_drc_free(struct comp_dev *dev)
294 {
295 struct multiband_drc_comp_data *cd = comp_get_drvdata(dev);
296
297 comp_info(dev, "multiband_drc_free()");
298
299 comp_data_blob_handler_free(cd->model_handler);
300
301 rfree(cd);
302 rfree(dev);
303 }
304
multiband_drc_params(struct comp_dev * dev,struct sof_ipc_stream_params * params)305 static int multiband_drc_params(struct comp_dev *dev, struct sof_ipc_stream_params *params)
306 {
307 int ret;
308
309 comp_dbg(dev, "multiband_drc_params()");
310
311 comp_dbg(dev, "multiband_drc_verify_params()");
312 ret = comp_verify_params(dev, 0, params);
313 if (ret < 0) {
314 comp_err(dev, "multiband_drc_params(): comp_verify_params() failed.");
315 return -EINVAL;
316 }
317
318 /* All configuration work is postponed to prepare(). */
319 return 0;
320 }
321
multiband_drc_cmd_get_data(struct comp_dev * dev,struct sof_ipc_ctrl_data * cdata,int max_size)322 static int multiband_drc_cmd_get_data(struct comp_dev *dev,
323 struct sof_ipc_ctrl_data *cdata,
324 int max_size)
325 {
326 struct multiband_drc_comp_data *cd = comp_get_drvdata(dev);
327 int ret = 0;
328
329 switch (cdata->cmd) {
330 case SOF_CTRL_CMD_BINARY:
331 comp_dbg(dev, "multiband_drc_cmd_get_data(), SOF_CTRL_CMD_BINARY");
332 ret = comp_data_blob_get_cmd(cd->model_handler, cdata, max_size);
333 break;
334 default:
335 comp_err(dev, "multiband_drc_cmd_get_data() error: invalid cdata->cmd");
336 ret = -EINVAL;
337 break;
338 }
339 return ret;
340 }
341
multiband_drc_cmd_get_value(struct comp_dev * dev,struct sof_ipc_ctrl_data * cdata)342 static int multiband_drc_cmd_get_value(struct comp_dev *dev,
343 struct sof_ipc_ctrl_data *cdata)
344 {
345 struct multiband_drc_comp_data *cd = comp_get_drvdata(dev);
346 int j;
347
348 switch (cdata->cmd) {
349 case SOF_CTRL_CMD_SWITCH:
350 comp_dbg(dev, "multiband_drc_cmd_get_value(), SOF_CTRL_CMD_SWITCH");
351 for (j = 0; j < cdata->num_elems; j++)
352 cdata->chanv[j].value = cd->process_enabled;
353 if (cdata->num_elems == 1)
354 return 0;
355
356 comp_warn(dev, "multiband_drc_cmd_get_value() warn: num_elems should be 1, got %d",
357 cdata->num_elems);
358 return 0;
359 default:
360 comp_err(dev, "multiband_drc_cmd_get_value() error: invalid cdata->cmd");
361 return -EINVAL;
362 }
363 }
364
multiband_drc_cmd_set_data(struct comp_dev * dev,struct sof_ipc_ctrl_data * cdata)365 static int multiband_drc_cmd_set_data(struct comp_dev *dev,
366 struct sof_ipc_ctrl_data *cdata)
367 {
368 struct multiband_drc_comp_data *cd = comp_get_drvdata(dev);
369 int ret = 0;
370
371 switch (cdata->cmd) {
372 case SOF_CTRL_CMD_BINARY:
373 comp_dbg(dev, "multiband_drc_cmd_set_data(), SOF_CTRL_CMD_BINARY");
374 ret = comp_data_blob_set_cmd(cd->model_handler, cdata);
375 break;
376 default:
377 comp_err(dev, "multiband_drc_cmd_set_data() error: invalid cdata->cmd");
378 ret = -EINVAL;
379 break;
380 }
381
382 return ret;
383 }
384
multiband_drc_cmd_set_value(struct comp_dev * dev,struct sof_ipc_ctrl_data * cdata)385 static int multiband_drc_cmd_set_value(struct comp_dev *dev,
386 struct sof_ipc_ctrl_data *cdata)
387 {
388 struct multiband_drc_comp_data *cd = comp_get_drvdata(dev);
389
390 switch (cdata->cmd) {
391 case SOF_CTRL_CMD_SWITCH:
392 comp_dbg(dev, "multiband_drc_cmd_set_value(), SOF_CTRL_CMD_SWITCH");
393 if (cdata->num_elems == 1) {
394 cd->process_enabled = cdata->chanv[0].value;
395 comp_info(dev, "multiband_drc_cmd_set_value(), process_enabled = %d",
396 cd->process_enabled);
397 return 0;
398 }
399
400 comp_err(dev, "multiband_drc_cmd_set_value() error: num_elems should be 1, got %d",
401 cdata->num_elems);
402 return -EINVAL;
403 default:
404 comp_err(dev, "multiband_drc_cmd_set_value() error: invalid cdata->cmd");
405 return -EINVAL;
406 }
407 }
408
multiband_drc_cmd(struct comp_dev * dev,int cmd,void * data,int max_data_size)409 static int multiband_drc_cmd(struct comp_dev *dev, int cmd, void *data, int max_data_size)
410 {
411 struct sof_ipc_ctrl_data *cdata = ASSUME_ALIGNED(data, 4);
412 int ret = 0;
413
414 comp_dbg(dev, "multiband_drc_cmd()");
415
416 switch (cmd) {
417 case COMP_CMD_SET_DATA:
418 ret = multiband_drc_cmd_set_data(dev, cdata);
419 break;
420 case COMP_CMD_GET_DATA:
421 ret = multiband_drc_cmd_get_data(dev, cdata, max_data_size);
422 break;
423 case COMP_CMD_SET_VALUE:
424 ret = multiband_drc_cmd_set_value(dev, cdata);
425 break;
426 case COMP_CMD_GET_VALUE:
427 ret = multiband_drc_cmd_get_value(dev, cdata);
428 break;
429 default:
430 comp_err(dev, "multiband_drc_cmd(), invalid command");
431 ret = -EINVAL;
432 }
433
434 return ret;
435 }
436
multiband_drc_trigger(struct comp_dev * dev,int cmd)437 static int multiband_drc_trigger(struct comp_dev *dev, int cmd)
438 {
439 int ret;
440
441 comp_dbg(dev, "multiband_drc_trigger()");
442
443 ret = comp_set_state(dev, cmd);
444 if (ret == COMP_STATUS_STATE_ALREADY_SET)
445 ret = PPL_STATUS_PATH_STOP;
446
447 return ret;
448 }
449
multiband_drc_process(struct comp_dev * dev,struct comp_buffer * source,struct comp_buffer * sink,int frames,uint32_t source_bytes,uint32_t sink_bytes)450 static void multiband_drc_process(struct comp_dev *dev, struct comp_buffer *source,
451 struct comp_buffer *sink, int frames,
452 uint32_t source_bytes, uint32_t sink_bytes)
453 {
454 struct multiband_drc_comp_data *cd = comp_get_drvdata(dev);
455
456 buffer_invalidate(source, source_bytes);
457
458 cd->multiband_drc_func(dev, &source->stream, &sink->stream, frames);
459
460 buffer_writeback(sink, sink_bytes);
461
462 /* calc new free and available */
463 comp_update_buffer_consume(source, source_bytes);
464 comp_update_buffer_produce(sink, sink_bytes);
465 }
466
multiband_drc_copy(struct comp_dev * dev)467 static int multiband_drc_copy(struct comp_dev *dev)
468 {
469 struct comp_copy_limits cl;
470 struct multiband_drc_comp_data *cd = comp_get_drvdata(dev);
471 struct comp_buffer *sourceb;
472 struct comp_buffer *sinkb;
473 int ret;
474
475 comp_dbg(dev, "multiband_drc_copy()");
476
477 sourceb = list_first_item(&dev->bsource_list, struct comp_buffer,
478 sink_list);
479 sinkb = list_first_item(&dev->bsink_list, struct comp_buffer,
480 source_list);
481
482 /* Check for changed configuration */
483 if (comp_is_new_data_blob_available(cd->model_handler)) {
484 cd->config = comp_get_data_blob(cd->model_handler, NULL, NULL);
485 ret = multiband_drc_setup(cd, (int16_t)sourceb->stream.channels,
486 sourceb->stream.rate);
487 if (ret < 0) {
488 comp_err(dev, "multiband_drc_copy(), failed DRC setup");
489 return ret;
490 }
491 }
492
493 /* Get source, sink, number of frames etc. to process. */
494 comp_get_copy_limits_with_lock(sourceb, sinkb, &cl);
495
496 /* Run Multiband DRC function */
497 multiband_drc_process(dev, sourceb, sinkb, cl.frames, cl.source_bytes, cl.sink_bytes);
498
499 return 0;
500 }
501
multiband_drc_prepare(struct comp_dev * dev)502 static int multiband_drc_prepare(struct comp_dev *dev)
503 {
504 struct multiband_drc_comp_data *cd = comp_get_drvdata(dev);
505 struct comp_buffer *sourceb;
506 struct comp_buffer *sinkb;
507 uint32_t sink_period_bytes;
508 int ret;
509
510 comp_info(dev, "multiband_drc_prepare()");
511
512 ret = comp_set_state(dev, COMP_TRIGGER_PREPARE);
513 if (ret < 0)
514 return ret;
515
516 if (ret == COMP_STATUS_STATE_ALREADY_SET)
517 return PPL_STATUS_PATH_STOP;
518
519 /* DRC component will only ever have 1 source and 1 sink buffer */
520 sourceb = list_first_item(&dev->bsource_list,
521 struct comp_buffer, sink_list);
522 sinkb = list_first_item(&dev->bsink_list,
523 struct comp_buffer, source_list);
524
525 /* get source data format */
526 cd->source_format = sourceb->stream.frame_fmt;
527
528 /* Initialize DRC */
529 comp_dbg(dev, "multiband_drc_prepare(), source_format=%d, sink_format=%d",
530 cd->source_format, cd->source_format);
531 cd->config = comp_get_data_blob(cd->model_handler, NULL, NULL);
532 if (cd->config && cd->process_enabled) {
533 ret = multiband_drc_setup(cd, sourceb->stream.channels, sourceb->stream.rate);
534 if (ret < 0) {
535 comp_err(dev, "multiband_drc_prepare() error: multiband_drc_setup failed.");
536 goto err;
537 }
538
539 cd->multiband_drc_func = multiband_drc_find_proc_func(cd->source_format);
540 if (!cd->multiband_drc_func) {
541 comp_err(dev, "multiband_drc_prepare(), No proc func");
542 ret = -EINVAL;
543 goto err;
544 }
545
546 cd->crossover_split = crossover_find_split_func(cd->config->num_bands);
547 if (!cd->crossover_split) {
548 comp_err(dev, "multiband_drc_prepare(), No crossover_split for band num %i",
549 cd->config->num_bands);
550 ret = -EINVAL;
551 goto err;
552 }
553 } else {
554 comp_info(dev, "multiband_drc_prepare(), DRC is in passthrough mode");
555 cd->multiband_drc_func = multiband_drc_find_proc_func_pass(cd->source_format);
556 if (!cd->multiband_drc_func) {
557 comp_err(dev, "multiband_drc_prepare(), No proc func passthrough");
558 ret = -EINVAL;
559 goto err;
560 }
561 }
562
563 /* validate sink data format and period bytes */
564 if (cd->source_format != sinkb->stream.frame_fmt) {
565 comp_err(dev,
566 "multiband_drc_prepare(): Source fmt %d and sink fmt %d are different.",
567 cd->source_format, sinkb->stream.frame_fmt);
568 ret = -EINVAL;
569 goto err;
570 }
571
572 sink_period_bytes = audio_stream_period_bytes(&sinkb->stream,
573 dev->frames);
574
575 if (sinkb->stream.size < sink_period_bytes) {
576 comp_err(dev, "multiband_drc_prepare(), sink buffer size %d is insufficient",
577 sinkb->stream.size);
578 ret = -ENOMEM;
579 goto err;
580 }
581
582 return 0;
583
584 err:
585 comp_set_state(dev, COMP_TRIGGER_RESET);
586 return ret;
587 }
588
multiband_drc_reset(struct comp_dev * dev)589 static int multiband_drc_reset(struct comp_dev *dev)
590 {
591 struct multiband_drc_comp_data *cd = comp_get_drvdata(dev);
592
593 comp_info(dev, "multiband_drc_reset()");
594
595 multiband_drc_reset_state(&cd->state);
596
597 cd->source_format = 0;
598 cd->multiband_drc_func = NULL;
599 cd->crossover_split = NULL;
600
601 comp_set_state(dev, COMP_TRIGGER_RESET);
602 return 0;
603 }
604
605 static const struct comp_driver comp_multiband_drc = {
606 .uid = SOF_RT_UUID(multiband_drc_uuid),
607 .tctx = &multiband_drc_tr,
608 .ops = {
609 .create = multiband_drc_new,
610 .free = multiband_drc_free,
611 .params = multiband_drc_params,
612 .cmd = multiband_drc_cmd,
613 .trigger = multiband_drc_trigger,
614 .copy = multiband_drc_copy,
615 .prepare = multiband_drc_prepare,
616 .reset = multiband_drc_reset,
617 },
618 };
619
620 static SHARED_DATA struct comp_driver_info comp_multiband_drc_info = {
621 .drv = &comp_multiband_drc,
622 };
623
sys_comp_multiband_drc_init(void)624 UT_STATIC void sys_comp_multiband_drc_init(void)
625 {
626 comp_register(platform_shared_get(&comp_multiband_drc_info,
627 sizeof(comp_multiband_drc_info)));
628 }
629
630 DECLARE_MODULE(sys_comp_multiband_drc_init);
631