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