1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2020 Intel Corporation. All rights reserved.
4 //
5 // Author: Marcin Rajwa <marcin.rajwa@linux.intel.com>
6
7 /**
8 * \file
9 * \brief Module Adapter: Processing component aimed to work with external module libraries
10 * \author Marcin Rajwa <marcin.rajwa@linux.intel.com>
11 */
12
13 #include <sof/audio/buffer.h>
14 #include <sof/audio/component.h>
15 #include <sof/audio/ipc-config.h>
16 #include <sof/audio/module_adapter/module/generic.h>
17 #include <sof/audio/pipeline.h>
18 #include <sof/common.h>
19 #include <sof/platform.h>
20 #include <sof/ut.h>
21 #include <limits.h>
22 #include <stdint.h>
23
24 LOG_MODULE_REGISTER(module_adapter, CONFIG_SOF_LOG_LEVEL);
25
26 /*
27 * \brief Create a module adapter component.
28 * \param[in] drv - component driver pointer.
29 * \param[in] config - component ipc descriptor pointer.
30 *
31 * \return: a pointer to newly created module adapter component on success. NULL on error.
32 */
module_adapter_new(const struct comp_driver * drv,const struct comp_ipc_config * config,struct module_interface * interface,const void * spec)33 struct comp_dev *module_adapter_new(const struct comp_driver *drv,
34 const struct comp_ipc_config *config,
35 struct module_interface *interface, const void *spec)
36 {
37 int ret;
38 struct comp_dev *dev;
39 struct processing_module *mod;
40 struct module_config *dst;
41
42 comp_cl_dbg(drv, "module_adapter_new() start");
43
44 if (!config) {
45 comp_cl_err(drv, "module_adapter_new(), wrong input params! drv = %x config = %x",
46 (uint32_t)drv, (uint32_t)config);
47 return NULL;
48 }
49
50 dev = comp_alloc(drv, sizeof(*dev));
51 if (!dev) {
52 comp_cl_err(drv, "module_adapter_new(), failed to allocate memory for comp_dev");
53 return NULL;
54 }
55 dev->ipc_config = *config;
56 dev->drv = drv;
57
58 mod = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*mod));
59 if (!mod) {
60 comp_err(dev, "module_adapter_new(), failed to allocate memory for module");
61 rfree(dev);
62 return NULL;
63 }
64
65 /* align the allocation size to a cache line for the coherent API */
66 mod->source_info = coherent_init_thread(struct module_source_info, c);
67 if (!mod->source_info) {
68 rfree(dev);
69 rfree(mod);
70 return NULL;
71 }
72
73 dst = &mod->priv.cfg;
74 mod->dev = dev;
75
76 comp_set_drvdata(dev, mod);
77 list_init(&mod->sink_buffer_list);
78
79 #if CONFIG_IPC_MAJOR_3
80 const unsigned char *data;
81 uint32_t size;
82
83 switch (config->type) {
84 case SOF_COMP_VOLUME:
85 {
86 const struct ipc_config_volume *ipc_volume = spec;
87
88 size = sizeof(*ipc_volume);
89 data = spec;
90 break;
91 }
92 default:
93 {
94 const struct ipc_config_process *ipc_module_adapter = spec;
95
96 size = ipc_module_adapter->size;
97 data = ipc_module_adapter->data;
98 break;
99 }
100 }
101
102 /* Copy initial config */
103 if (size) {
104 ret = module_load_config(dev, data, size);
105 if (ret) {
106 comp_err(dev, "module_adapter_new() error %d: config loading has failed.",
107 ret);
108 goto err;
109 }
110 dst->init_data = dst->data;
111 }
112 #else
113 if (drv->type == SOF_COMP_MODULE_ADAPTER) {
114 const struct ipc_config_process *ipc_module_adapter = spec;
115
116 dst->init_data = ipc_module_adapter->data;
117 dst->size = ipc_module_adapter->size;
118
119 memcpy(&dst->base_cfg, ipc_module_adapter->data, sizeof(dst->base_cfg));
120 } else {
121 dst->init_data = spec;
122 }
123 #endif
124
125 /* Init processing module */
126 ret = module_init(mod, interface);
127 if (ret) {
128 comp_err(dev, "module_adapter_new() %d: module initialization failed",
129 ret);
130 goto err;
131 }
132
133 #if CONFIG_IPC_MAJOR_4
134 dst->init_data = NULL;
135 #endif
136 dev->state = COMP_STATE_READY;
137
138 comp_dbg(dev, "module_adapter_new() done");
139 return dev;
140 err:
141 coherent_free_thread(mod->source_info, c);
142 rfree(mod);
143 rfree(dev);
144 return NULL;
145 }
146
147 /*
148 * \brief Prepare the module
149 * \param[in] dev - component device pointer.
150 *
151 * \return integer representing either:
152 * 0 - success
153 * value < 0 - failure.
154 */
module_adapter_prepare(struct comp_dev * dev)155 int module_adapter_prepare(struct comp_dev *dev)
156 {
157 int ret;
158 struct processing_module *mod = comp_get_drvdata(dev);
159 struct module_data *md = &mod->priv;
160 struct comp_buffer __sparse_cache *buffer_c;
161 struct comp_buffer __sparse_cache *sink_c;
162 struct comp_buffer *sink;
163 struct list_item *blist, *_blist;
164 uint32_t buff_periods;
165 uint32_t buff_size; /* size of local buffer */
166 int i = 0;
167
168 comp_dbg(dev, "module_adapter_prepare() start");
169
170 /* Prepare module */
171 ret = module_prepare(mod);
172 if (ret) {
173 if (ret != PPL_STATUS_PATH_STOP)
174 comp_err(dev, "module_adapter_prepare() error %x: module prepare failed",
175 ret);
176 return ret;
177 }
178
179 /* Get period_bytes first on prepare(). At this point it is guaranteed that the stream
180 * parameter from sink buffer is settled, and still prior to all references to period_bytes.
181 */
182 sink = list_first_item(&dev->bsink_list, struct comp_buffer, source_list);
183 sink_c = buffer_acquire(sink);
184
185 mod->period_bytes = audio_stream_period_bytes(&sink_c->stream, dev->frames);
186 comp_dbg(dev, "module_adapter_prepare(): got period_bytes = %u", mod->period_bytes);
187
188 buffer_release(sink_c);
189
190 /*
191 * check if the component is already active. This could happen in the case of mixer when
192 * one of the sources is already active
193 */
194 if (dev->state == COMP_STATE_ACTIVE)
195 return PPL_STATUS_PATH_STOP;
196
197 /* Are we already prepared? */
198 ret = comp_set_state(dev, COMP_TRIGGER_PREPARE);
199 if (ret < 0)
200 return ret;
201
202 if (ret == COMP_STATUS_STATE_ALREADY_SET) {
203 comp_warn(dev, "module_adapter_prepare(): module has already been prepared");
204 return PPL_STATUS_PATH_STOP;
205 }
206
207 mod->deep_buff_bytes = 0;
208
209 /*
210 * compute number of input buffers and make the source_info shared if the module is on a
211 * different core than any of it's sources
212 */
213 list_for_item(blist, &dev->bsource_list) {
214 struct comp_buffer *buf;
215 struct comp_dev *source;
216
217 buf = buffer_from_list(blist, PPL_DIR_UPSTREAM);
218 source = buffer_get_comp(buf, PPL_DIR_UPSTREAM);
219
220 if (source->pipeline && source->pipeline->core != dev->pipeline->core)
221 coherent_shared_thread(mod->source_info, c);
222
223 mod->num_input_buffers++;
224 }
225
226 /* compute number of output buffers */
227 list_for_item(blist, &dev->bsink_list)
228 mod->num_output_buffers++;
229
230 if (!mod->num_input_buffers && !mod->num_output_buffers) {
231 comp_err(dev, "module_adapter_prepare(): no source and sink buffers connected!");
232 return -EINVAL;
233 }
234
235 if (mod->simple_copy && mod->num_input_buffers > 1 && mod->num_output_buffers > 1) {
236 comp_err(dev, "module_adapter_prepare(): Invalid use of simple_copy");
237 return -EINVAL;
238 }
239
240 /* allocate memory for input buffers */
241 if (mod->num_input_buffers) {
242 mod->input_buffers =
243 rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM,
244 sizeof(*mod->input_buffers) * mod->num_input_buffers);
245 if (!mod->input_buffers) {
246 comp_err(dev, "module_adapter_prepare(): failed to allocate input buffers");
247 return -ENOMEM;
248 }
249 } else {
250 mod->input_buffers = NULL;
251 }
252
253 /* allocate memory for output buffers */
254 if (mod->num_output_buffers) {
255 mod->output_buffers =
256 rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM,
257 sizeof(*mod->output_buffers) * mod->num_output_buffers);
258 if (!mod->output_buffers) {
259 comp_err(dev, "module_adapter_prepare(): failed to allocate output buffers");
260 ret = -ENOMEM;
261 goto in_out_free;
262 }
263 } else {
264 mod->output_buffers = NULL;
265 }
266
267 /*
268 * no need to allocate intermediate sink buffers if the module produces only period bytes
269 * every period and has only 1 input and 1 output buffer
270 */
271 if (mod->simple_copy)
272 return 0;
273
274 /* Module is prepared, now we need to configure processing settings.
275 * If module internal buffer is not equal to natural multiple of pipeline
276 * buffer we have a situation where module adapter have to deep buffer certain amount
277 * of samples on its start (typically few periods) in order to regularly
278 * generate output once started (same situation happens for compress streams
279 * as well).
280 */
281 if (md->mpd.in_buff_size > mod->period_bytes) {
282 buff_periods = (md->mpd.in_buff_size % mod->period_bytes) ?
283 (md->mpd.in_buff_size / mod->period_bytes) + 2 :
284 (md->mpd.in_buff_size / mod->period_bytes) + 1;
285 } else {
286 buff_periods = (mod->period_bytes % md->mpd.in_buff_size) ?
287 (mod->period_bytes / md->mpd.in_buff_size) + 2 :
288 (mod->period_bytes / md->mpd.in_buff_size) + 1;
289 }
290
291 /*
292 * deep_buffer_bytes is a measure of how many bytes we need to send to the DAI before
293 * the module starts producing samples. In a normal copy() walk it might be possible that
294 * the first period_bytes copied to input_buffer might not be enough for the processing
295 * to begin. So, in order to prevent the DAI from starving, it needs to be fed zeroes until
296 * the module starts processing and generating output samples.
297 */
298 if (md->mpd.in_buff_size != mod->period_bytes)
299 mod->deep_buff_bytes = MIN(mod->period_bytes, md->mpd.in_buff_size) * buff_periods;
300
301 if (md->mpd.out_buff_size > mod->period_bytes) {
302 buff_periods = (md->mpd.out_buff_size % mod->period_bytes) ?
303 (md->mpd.out_buff_size / mod->period_bytes) + 2 :
304 (md->mpd.out_buff_size / mod->period_bytes) + 1;
305 } else {
306 buff_periods = (mod->period_bytes % md->mpd.out_buff_size) ?
307 (mod->period_bytes / md->mpd.out_buff_size) + 2 :
308 (mod->period_bytes / md->mpd.out_buff_size) + 1;
309 }
310
311 /*
312 * It is possible that the module process() will produce more data than period_bytes but
313 * the DAI can consume only period_bytes every period. So, the local buffer needs to be
314 * large enough to save the produced output samples.
315 */
316 buff_size = MAX(mod->period_bytes, md->mpd.out_buff_size) * buff_periods;
317 mod->output_buffer_size = buff_size;
318
319 /* allocate memory for input buffer data */
320 list_for_item(blist, &dev->bsource_list) {
321 size_t size = MAX(mod->deep_buff_bytes, mod->period_bytes);
322
323 mod->input_buffers[i].data =
324 (__sparse_force void __sparse_cache *)rballoc(0, SOF_MEM_CAPS_RAM, size);
325 if (!mod->input_buffers[i].data) {
326 comp_err(mod->dev, "module_adapter_prepare(): Failed to alloc input buffer data");
327 ret = -ENOMEM;
328 goto in_data_free;
329 }
330 i++;
331 }
332
333 /* allocate memory for output buffer data */
334 i = 0;
335 list_for_item(blist, &dev->bsink_list) {
336 mod->output_buffers[i].data =
337 (__sparse_force void __sparse_cache *)rballoc(0, SOF_MEM_CAPS_RAM,
338 md->mpd.out_buff_size);
339 if (!mod->output_buffers[i].data) {
340 comp_err(mod->dev, "module_adapter_prepare(): Failed to alloc output buffer data");
341 ret = -ENOMEM;
342 goto out_data_free;
343 }
344 i++;
345 }
346
347 /* allocate buffer for all sinks */
348 if (list_is_empty(&mod->sink_buffer_list)) {
349 for (i = 0; i < mod->num_output_buffers; i++) {
350 struct comp_buffer *buffer = buffer_alloc(buff_size, SOF_MEM_CAPS_RAM,
351 PLATFORM_DCACHE_ALIGN);
352 if (!buffer) {
353 comp_err(dev, "module_adapter_prepare(): failed to allocate local buffer");
354 ret = -ENOMEM;
355 goto free;
356 }
357
358 buffer_attach(buffer, &mod->sink_buffer_list, PPL_DIR_UPSTREAM);
359
360 buffer_c = buffer_acquire(buffer);
361 buffer_set_params(buffer_c, mod->stream_params, BUFFER_UPDATE_FORCE);
362 buffer_reset_pos(buffer_c, NULL);
363 buffer_release(buffer_c);
364 }
365 } else {
366 list_for_item(blist, &mod->sink_buffer_list) {
367 struct comp_buffer *buffer = container_of(blist, struct comp_buffer,
368 sink_list);
369
370 buffer_c = buffer_acquire(buffer);
371 ret = buffer_set_size(buffer_c, buff_size);
372 if (ret < 0) {
373 buffer_release(buffer_c);
374 comp_err(dev, "module_adapter_prepare(): buffer_set_size() failed, buff_size = %u",
375 buff_size);
376 goto free;
377 }
378
379 buffer_set_params(buffer_c, mod->stream_params, BUFFER_UPDATE_FORCE);
380 buffer_reset_pos(buffer_c, NULL);
381 buffer_release(buffer_c);
382 }
383 }
384
385 comp_dbg(dev, "module_adapter_prepare() done");
386
387 return 0;
388
389 free:
390 list_for_item_safe(blist, _blist, &mod->sink_buffer_list) {
391 struct comp_buffer *buffer = container_of(blist, struct comp_buffer,
392 sink_list);
393
394 buffer_detach(buffer, &mod->sink_buffer_list, PPL_DIR_UPSTREAM);
395 buffer_free(buffer);
396 }
397
398 out_data_free:
399 for (i = 0; i < mod->num_output_buffers; i++)
400 rfree((__sparse_force void *)mod->output_buffers[i].data);
401
402 in_data_free:
403 for (i = 0; i < mod->num_input_buffers; i++)
404 rfree((__sparse_force void *)mod->input_buffers[i].data);
405
406 in_out_free:
407 rfree(mod->output_buffers);
408 rfree(mod->input_buffers);
409 return ret;
410 }
411
module_adapter_params(struct comp_dev * dev,struct sof_ipc_stream_params * params)412 int module_adapter_params(struct comp_dev *dev, struct sof_ipc_stream_params *params)
413 {
414 int ret;
415 struct processing_module *mod = comp_get_drvdata(dev);
416
417 ret = comp_verify_params(dev, mod->verify_params_flags, params);
418 if (ret < 0) {
419 comp_err(dev, "module_adapter_params(): comp_verify_params() failed.");
420 return ret;
421 }
422
423 /* allocate stream_params each time */
424 if (mod->stream_params)
425 rfree(mod->stream_params);
426
427 mod->stream_params = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM,
428 sizeof(*mod->stream_params) + params->ext_data_length);
429 if (!mod->stream_params)
430 return -ENOMEM;
431
432 ret = memcpy_s(mod->stream_params, sizeof(struct sof_ipc_stream_params),
433 params, sizeof(struct sof_ipc_stream_params));
434 if (ret < 0)
435 return ret;
436
437 if (params->ext_data_length) {
438 ret = memcpy_s((uint8_t *)mod->stream_params->data,
439 params->ext_data_length,
440 (uint8_t *)params->data,
441 params->ext_data_length);
442 if (ret < 0)
443 return ret;
444 }
445
446 return 0;
447 }
448
449 /*
450 * Function to copy from source buffer to the module buffer
451 * @source: source audio buffer stream
452 * @buff: pointer to the module input buffer
453 * @buff_size: size of the module input buffer
454 * @bytes: number of bytes available in the source buffer
455 */
456 static void
ca_copy_from_source_to_module(const struct audio_stream __sparse_cache * source,void __sparse_cache * buff,uint32_t buff_size,size_t bytes)457 ca_copy_from_source_to_module(const struct audio_stream __sparse_cache *source,
458 void __sparse_cache *buff, uint32_t buff_size, size_t bytes)
459 {
460 /* head_size - available data until end of source buffer */
461 const int without_wrap = audio_stream_bytes_without_wrap(source, source->r_ptr);
462 uint32_t head_size = MIN(bytes, without_wrap);
463 /* tail_size - residual data to be copied starting from the beginning of the buffer */
464 uint32_t tail_size = bytes - head_size;
465
466 /* copy head_size to module buffer */
467 memcpy((__sparse_force void *)buff, source->r_ptr, MIN(buff_size, head_size));
468
469 /* copy residual samples after wrap */
470 if (tail_size)
471 memcpy((__sparse_force char *)buff + head_size,
472 audio_stream_wrap(source, (char *)source->r_ptr + head_size),
473 MIN(buff_size, tail_size));
474 }
475
476 /*
477 * Function to copy processed samples from the module buffer to sink buffer
478 * @sink: sink audio buffer stream
479 * @buff: pointer to the module output buffer
480 * @bytes: number of bytes available in the module output buffer
481 */
482 static void
ca_copy_from_module_to_sink(const struct audio_stream __sparse_cache * sink,void __sparse_cache * buff,size_t bytes)483 ca_copy_from_module_to_sink(const struct audio_stream __sparse_cache *sink,
484 void __sparse_cache *buff, size_t bytes)
485 {
486 /* head_size - free space until end of sink buffer */
487 const int without_wrap = audio_stream_bytes_without_wrap(sink, sink->w_ptr);
488 uint32_t head_size = MIN(bytes, without_wrap);
489 /* tail_size - rest of the bytes that needs to be written
490 * starting from the beginning of the buffer
491 */
492 uint32_t tail_size = bytes - head_size;
493
494 /* copy "head_size" samples to sink buffer */
495 memcpy(sink->w_ptr, (__sparse_force void *)buff, MIN(sink->size, head_size));
496
497 /* copy rest of the samples after buffer wrap */
498 if (tail_size)
499 memcpy(audio_stream_wrap(sink, (char *)sink->w_ptr + head_size),
500 (__sparse_force char *)buff + head_size, MIN(sink->size, tail_size));
501 }
502
503 /**
504 * \brief Generate zero samples of "bytes" size for the sink.
505 * \param[in] sink - a pointer to sink buffer.
506 * \param[in] bytes - number of zero bytes to produce.
507 *
508 * \return: none.
509 */
generate_zeroes(struct comp_buffer __sparse_cache * sink,uint32_t bytes)510 static void generate_zeroes(struct comp_buffer __sparse_cache *sink, uint32_t bytes)
511 {
512 uint32_t tmp, copy_bytes = bytes;
513 void *ptr;
514
515 while (copy_bytes) {
516 ptr = audio_stream_wrap(&sink->stream, sink->stream.w_ptr);
517 tmp = audio_stream_bytes_without_wrap(&sink->stream, ptr);
518 tmp = MIN(tmp, copy_bytes);
519 ptr = (char *)ptr + tmp;
520 copy_bytes -= tmp;
521 }
522 comp_update_buffer_produce(sink, bytes);
523 }
524
module_copy_samples(struct comp_dev * dev,struct comp_buffer __sparse_cache * src_buffer,struct comp_buffer __sparse_cache * sink_buffer,uint32_t produced)525 static void module_copy_samples(struct comp_dev *dev, struct comp_buffer __sparse_cache *src_buffer,
526 struct comp_buffer __sparse_cache *sink_buffer, uint32_t produced)
527 {
528 struct processing_module *mod = comp_get_drvdata(dev);
529 struct comp_copy_limits cl;
530 uint32_t copy_bytes;
531
532 if (mod->deep_buff_bytes) {
533 if (mod->deep_buff_bytes >= audio_stream_get_avail_bytes(&src_buffer->stream)) {
534 generate_zeroes(sink_buffer, mod->period_bytes);
535 return;
536 }
537
538 comp_dbg(dev, "module_copy_samples(): deep buffering has ended after gathering %d bytes of processed data",
539 audio_stream_get_avail_bytes(&src_buffer->stream));
540 mod->deep_buff_bytes = 0;
541 } else if (!produced) {
542 comp_dbg(dev, "module_copy_samples(): nothing processed in this call");
543 /*
544 * No data produced anything in this period but there still be data in the buffer
545 * to copy to sink
546 */
547 if (audio_stream_get_avail_bytes(&src_buffer->stream) < mod->period_bytes)
548 return;
549 }
550
551 comp_get_copy_limits(src_buffer, sink_buffer, &cl);
552 copy_bytes = cl.frames * cl.source_frame_bytes;
553 if (!copy_bytes)
554 return;
555 audio_stream_copy(&src_buffer->stream, 0, &sink_buffer->stream, 0,
556 copy_bytes / mod->stream_params->sample_container_bytes);
557 buffer_stream_writeback(sink_buffer, copy_bytes);
558
559 comp_update_buffer_produce(sink_buffer, copy_bytes);
560 comp_update_buffer_consume(src_buffer, copy_bytes);
561 }
562
module_adapter_process_output(struct comp_dev * dev)563 static void module_adapter_process_output(struct comp_dev *dev)
564 {
565 struct processing_module *mod = comp_get_drvdata(dev);
566 struct comp_buffer *sink;
567 struct comp_buffer __sparse_cache *sink_c;
568 struct list_item *blist;
569 int i = 0;
570
571 /*
572 * copy all produced output samples to output buffers. This loop will do nothing when
573 * there are no samples produced.
574 */
575 list_for_item(blist, &mod->sink_buffer_list) {
576 if (mod->output_buffers[i].size > 0) {
577 struct comp_buffer *buffer;
578 struct comp_buffer __sparse_cache *buffer_c;
579
580 buffer = container_of(blist, struct comp_buffer, sink_list);
581 buffer_c = buffer_acquire(buffer);
582
583 ca_copy_from_module_to_sink(&buffer_c->stream, mod->output_buffers[i].data,
584 mod->output_buffers[i].size);
585 audio_stream_produce(&buffer_c->stream, mod->output_buffers[i].size);
586 buffer_release(buffer_c);
587 }
588 i++;
589 }
590
591 /* copy from all output local buffers to sink buffers */
592 i = 0;
593 list_for_item(blist, &dev->bsink_list) {
594 struct list_item *_blist;
595 int j = 0;
596
597 list_for_item(_blist, &mod->sink_buffer_list) {
598 if (i == j) {
599 struct comp_buffer *source;
600 struct comp_buffer __sparse_cache *source_c;
601
602 sink = container_of(blist, struct comp_buffer, source_list);
603 source = container_of(_blist, struct comp_buffer, sink_list);
604
605 sink_c = buffer_acquire(sink);
606 source_c = buffer_acquire(source);
607 module_copy_samples(dev, source_c, sink_c,
608 mod->output_buffers[i].size);
609 buffer_release(source_c);
610 buffer_release(sink_c);
611
612 mod->output_buffers[i].size = 0;
613 break;
614 }
615 j++;
616 }
617 i++;
618 }
619 }
620
621 static uint32_t
module_single_sink_setup(struct comp_dev * dev,struct comp_buffer __sparse_cache ** source_c,struct comp_buffer __sparse_cache ** sinks_c)622 module_single_sink_setup(struct comp_dev *dev,
623 struct comp_buffer __sparse_cache **source_c,
624 struct comp_buffer __sparse_cache **sinks_c)
625 {
626 struct processing_module *mod = comp_get_drvdata(dev);
627 struct comp_copy_limits c;
628 struct list_item *blist;
629 uint32_t num_input_buffers;
630 int i = 0;
631
632 list_for_item(blist, &dev->bsource_list) {
633 comp_get_copy_limits_frame_aligned(source_c[i], sinks_c[0], &c);
634
635 if (!mod->skip_src_buffer_invalidate)
636 buffer_stream_invalidate(source_c[i], c.frames * c.source_frame_bytes);
637
638 /*
639 * note that the size is in number of frames not the number of
640 * bytes
641 */
642 mod->input_buffers[i].size = c.frames;
643 mod->input_buffers[i].consumed = 0;
644
645 mod->input_buffers[i].data = &source_c[i]->stream;
646 i++;
647 }
648
649 num_input_buffers = i;
650
651 mod->output_buffers[0].size = 0;
652 mod->output_buffers[0].data = &sinks_c[0]->stream;
653
654 return num_input_buffers;
655 }
656
657 static uint32_t
module_single_source_setup(struct comp_dev * dev,struct comp_buffer __sparse_cache ** source_c,struct comp_buffer __sparse_cache ** sinks_c)658 module_single_source_setup(struct comp_dev *dev,
659 struct comp_buffer __sparse_cache **source_c,
660 struct comp_buffer __sparse_cache **sinks_c)
661 {
662 struct processing_module *mod = comp_get_drvdata(dev);
663 struct comp_copy_limits c;
664 struct list_item *blist;
665 uint32_t min_frames = UINT32_MAX;
666 uint32_t num_output_buffers;
667 uint32_t source_frame_bytes = 0;
668 int i = 0;
669
670 if (list_is_empty(&dev->bsink_list)) {
671 min_frames = audio_stream_get_avail_frames(&source_c[0]->stream);
672 source_frame_bytes = audio_stream_frame_bytes(&source_c[0]->stream);
673 } else {
674 list_for_item(blist, &dev->bsink_list) {
675 comp_get_copy_limits_frame_aligned(source_c[0], sinks_c[i], &c);
676
677 min_frames = MIN(min_frames, c.frames);
678 source_frame_bytes = c.source_frame_bytes;
679
680 mod->output_buffers[i].size = 0;
681 mod->output_buffers[i].data = &sinks_c[i]->stream;
682 i++;
683 }
684 }
685
686 num_output_buffers = i;
687
688 if (!mod->skip_src_buffer_invalidate)
689 buffer_stream_invalidate(source_c[0], min_frames * source_frame_bytes);
690
691 /* note that the size is in number of frames not the number of bytes */
692 mod->input_buffers[0].size = min_frames;
693 mod->input_buffers[0].consumed = 0;
694 mod->input_buffers[0].data = &source_c[0]->stream;
695
696 return num_output_buffers;
697 }
698
module_adapter_simple_copy(struct comp_dev * dev)699 static int module_adapter_simple_copy(struct comp_dev *dev)
700 {
701 struct comp_buffer __sparse_cache *source_c[PLATFORM_MAX_STREAMS];
702 struct comp_buffer __sparse_cache *sinks_c[PLATFORM_MAX_STREAMS];
703 struct processing_module *mod = comp_get_drvdata(dev);
704 struct list_item *blist;
705 uint32_t num_input_buffers = 0;
706 uint32_t num_output_buffers = 0;
707 int ret, i = 0;
708
709 /* acquire all sink and source buffers */
710 list_for_item(blist, &dev->bsink_list) {
711 struct comp_buffer *sink;
712
713 sink = container_of(blist, struct comp_buffer, source_list);
714 sinks_c[i++] = buffer_acquire(sink);
715 }
716 i = 0;
717 list_for_item(blist, &dev->bsource_list) {
718 struct comp_buffer *source;
719
720 source = container_of(blist, struct comp_buffer, sink_list);
721 source_c[i++] = buffer_acquire(source);
722 }
723
724 /* setup active input/output buffers for processing */
725 if (mod->num_output_buffers == 1) {
726 num_input_buffers = module_single_sink_setup(dev, source_c, sinks_c);
727 if (sinks_c[0]->sink->state == dev->state)
728 num_output_buffers = 1;
729 } else {
730 num_output_buffers = module_single_source_setup(dev, source_c, sinks_c);
731 if (source_c[0]->source->state == dev->state)
732 num_input_buffers = 1;
733 }
734
735 ret = module_process(mod, mod->input_buffers, num_input_buffers,
736 mod->output_buffers, num_output_buffers);
737 if (ret) {
738 if (ret != -ENOSPC && ret != -ENODATA) {
739 comp_err(dev, "module_adapter_simple_copy() process failed with error: %x",
740 ret);
741 goto out;
742 }
743
744 ret = 0;
745 }
746
747 /* consume from all active input buffers */
748 for (i = 0; i < num_input_buffers; i++) {
749 struct comp_buffer __sparse_cache *src_c;
750
751 src_c = attr_container_of(mod->input_buffers[i].data,
752 struct comp_buffer __sparse_cache,
753 stream, __sparse_cache);
754 comp_update_buffer_consume(src_c, mod->input_buffers[i].consumed);
755 }
756
757 /* release all source buffers */
758 i = 0;
759 list_for_item(blist, &dev->bsource_list) {
760 buffer_release(source_c[i]);
761 mod->input_buffers[i].size = 0;
762 mod->input_buffers[i].consumed = 0;
763 i++;
764 }
765
766 /* produce data into all active output buffers */
767 for (i = 0; i < num_output_buffers; i++) {
768 struct comp_buffer __sparse_cache *sink_c;
769
770 sink_c = attr_container_of(mod->output_buffers[i].data,
771 struct comp_buffer __sparse_cache,
772 stream, __sparse_cache);
773
774 if (!mod->skip_sink_buffer_writeback)
775 buffer_stream_writeback(sink_c, mod->output_buffers[i].size);
776 comp_update_buffer_produce(sink_c, mod->output_buffers[i].size);
777 }
778
779 /* release all sink buffers */
780 i = 0;
781 list_for_item(blist, &dev->bsink_list) {
782 buffer_release(sinks_c[i]);
783 mod->output_buffers[i++].size = 0;
784 }
785
786 return 0;
787 out:
788 i = 0;
789 list_for_item(blist, &dev->bsink_list)
790 buffer_release(sinks_c[i++]);
791 i = 0;
792 list_for_item(blist, &dev->bsource_list)
793 buffer_release(source_c[i++]);
794
795 for (i = 0; i < mod->num_output_buffers; i++)
796 mod->output_buffers[i].size = 0;
797
798 for (i = 0; i < mod->num_input_buffers; i++) {
799 mod->input_buffers[i].size = 0;
800 mod->input_buffers[i].consumed = 0;
801 }
802
803 return ret;
804 }
805
module_adapter_copy(struct comp_dev * dev)806 int module_adapter_copy(struct comp_dev *dev)
807 {
808 struct processing_module *mod = comp_get_drvdata(dev);
809 struct module_data *md = &mod->priv;
810 struct comp_buffer *source, *sink;
811 struct comp_buffer __sparse_cache *sink_c = NULL;
812 struct list_item *blist;
813 size_t size = MAX(mod->deep_buff_bytes, mod->period_bytes);
814 uint32_t min_free_frames = UINT_MAX;
815 int ret, i = 0;
816
817 comp_dbg(dev, "module_adapter_copy(): start");
818
819 if (mod->simple_copy)
820 return module_adapter_simple_copy(dev);
821
822 list_for_item(blist, &mod->sink_buffer_list) {
823 sink = container_of(blist, struct comp_buffer, sink_list);
824
825 sink_c = buffer_acquire(sink);
826 min_free_frames = MIN(min_free_frames,
827 audio_stream_get_free_frames(&sink_c->stream));
828 buffer_release(sink_c);
829 }
830
831 /* copy source samples into input buffer */
832 list_for_item(blist, &dev->bsource_list) {
833 struct comp_buffer __sparse_cache *src_c;
834 uint32_t bytes_to_process;
835 int frames, source_frame_bytes;
836
837 source = container_of(blist, struct comp_buffer, sink_list);
838 src_c = buffer_acquire(source);
839
840 /* check if the source dev is in the same state as the dev */
841 if (!src_c->source || src_c->source->state != dev->state) {
842 buffer_release(src_c);
843 continue;
844 }
845
846 frames = MIN(min_free_frames,
847 audio_stream_get_avail_frames(&src_c->stream));
848 source_frame_bytes = audio_stream_frame_bytes(&src_c->stream);
849
850 bytes_to_process = MIN(frames * source_frame_bytes, md->mpd.in_buff_size);
851
852 buffer_stream_invalidate(src_c, bytes_to_process);
853 mod->input_buffers[i].size = bytes_to_process;
854 mod->input_buffers[i].consumed = 0;
855
856 ca_copy_from_source_to_module(&src_c->stream, mod->input_buffers[i].data,
857 md->mpd.in_buff_size, bytes_to_process);
858 buffer_release(src_c);
859
860 i++;
861 }
862
863 ret = module_process(mod, mod->input_buffers, mod->num_input_buffers,
864 mod->output_buffers, mod->num_output_buffers);
865 if (ret) {
866 if (ret != -ENOSPC && ret != -ENODATA) {
867 comp_err(dev, "module_adapter_copy() error %x: module processing failed",
868 ret);
869 goto out;
870 }
871
872 ret = 0;
873 }
874
875 i = 0;
876 /* consume from all input buffers */
877 list_for_item(blist, &dev->bsource_list) {
878 struct comp_buffer __sparse_cache *src_c;
879
880 source = container_of(blist, struct comp_buffer, sink_list);
881 src_c = buffer_acquire(source);
882
883 comp_update_buffer_consume(src_c, mod->input_buffers[i].consumed);
884 buffer_release(src_c);
885
886 bzero((__sparse_force void *)mod->input_buffers[i].data, size);
887 mod->input_buffers[i].size = 0;
888 mod->input_buffers[i].consumed = 0;
889 i++;
890 }
891 module_adapter_process_output(dev);
892
893 return 0;
894
895 out:
896 for (i = 0; i < mod->num_output_buffers; i++)
897 mod->output_buffers[i].size = 0;
898
899 for (i = 0; i < mod->num_input_buffers; i++) {
900 bzero((__sparse_force void *)mod->input_buffers[i].data, size);
901 mod->input_buffers[i].size = 0;
902 mod->input_buffers[i].consumed = 0;
903 }
904
905 return ret;
906 }
907
module_adapter_get_set_params(struct comp_dev * dev,struct sof_ipc_ctrl_data * cdata,bool set)908 static int module_adapter_get_set_params(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata,
909 bool set)
910 {
911 struct processing_module *mod = comp_get_drvdata(dev);
912 struct module_data *md = &mod->priv;
913 enum module_cfg_fragment_position pos;
914 uint32_t data_offset_size;
915 static uint32_t size;
916
917 comp_dbg(dev, "module_adapter_set_params(): num_of_elem %d, elem remain %d msg_index %u",
918 cdata->num_elems, cdata->elems_remaining, cdata->msg_index);
919
920 /* set the fragment position, data offset and config data size */
921 if (!cdata->msg_index) {
922 size = cdata->num_elems + cdata->elems_remaining;
923 data_offset_size = size;
924 if (cdata->elems_remaining)
925 pos = MODULE_CFG_FRAGMENT_FIRST;
926 else
927 pos = MODULE_CFG_FRAGMENT_SINGLE;
928 } else {
929 data_offset_size = size - (cdata->num_elems + cdata->elems_remaining);
930 if (cdata->elems_remaining)
931 pos = MODULE_CFG_FRAGMENT_MIDDLE;
932 else
933 pos = MODULE_CFG_FRAGMENT_LAST;
934 }
935
936 /*
937 * The type member in struct sof_abi_hdr is used for component's specific blob type
938 * for IPC3, just like it is used for component's specific blob param_id for IPC4.
939 */
940 if (set && md->ops->set_configuration)
941 return md->ops->set_configuration(mod, cdata->data[0].type, pos, data_offset_size,
942 (const uint8_t *)cdata, cdata->num_elems,
943 NULL, 0);
944 else if (!set && md->ops->get_configuration)
945 return md->ops->get_configuration(mod, pos, &data_offset_size,
946 (uint8_t *)cdata, cdata->num_elems);
947
948 comp_warn(dev, "module_adapter_get_set_params(): no configuration op set for %d",
949 dev_comp_id(dev));
950 return 0;
951 }
952
module_adapter_ctrl_get_set_data(struct comp_dev * dev,struct sof_ipc_ctrl_data * cdata,bool set)953 static int module_adapter_ctrl_get_set_data(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata,
954 bool set)
955 {
956 int ret;
957 struct processing_module *mod = comp_get_drvdata(dev);
958
959 comp_dbg(dev, "module_adapter_ctrl_set_data() start, state %d, cmd %d",
960 mod->priv.state, cdata->cmd);
961
962 /* Check version from ABI header */
963 if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) {
964 comp_err(dev, "module_adapter_ctrl_set_data(): ABI mismatch!");
965 return -EINVAL;
966 }
967
968 switch (cdata->cmd) {
969 case SOF_CTRL_CMD_ENUM:
970 comp_err(dev, "module_adapter_ctrl_set_data(): set enum is not implemented");
971 ret = -EIO;
972 break;
973 case SOF_CTRL_CMD_BINARY:
974 ret = module_adapter_get_set_params(dev, cdata, set);
975 break;
976 default:
977 comp_err(dev, "module_adapter_ctrl_set_data error: unknown set data command");
978 ret = -EINVAL;
979 break;
980 }
981
982 return ret;
983 }
984
985 /* Used to pass standard and bespoke commands (with data) to component */
module_adapter_cmd(struct comp_dev * dev,int cmd,void * data,int max_data_size)986 int module_adapter_cmd(struct comp_dev *dev, int cmd, void *data, int max_data_size)
987 {
988 struct sof_ipc_ctrl_data *cdata = ASSUME_ALIGNED(data, 4);
989 struct processing_module *mod = comp_get_drvdata(dev);
990 struct module_data *md = &mod->priv;
991 int ret = 0;
992
993 comp_dbg(dev, "module_adapter_cmd() %d start", cmd);
994
995 switch (cmd) {
996 case COMP_CMD_SET_DATA:
997 ret = module_adapter_ctrl_get_set_data(dev, cdata, true);
998 break;
999 case COMP_CMD_GET_DATA:
1000 ret = module_adapter_ctrl_get_set_data(dev, cdata, false);
1001 break;
1002 case COMP_CMD_SET_VALUE:
1003 /*
1004 * IPC3 does not use config_id, so pass 0 for config ID as it will be ignored
1005 * anyway. Also, pass the 0 as the fragment size as it is not relevant for the
1006 * SET_VALUE command.
1007 */
1008 if (md->ops->set_configuration)
1009 ret = md->ops->set_configuration(mod, 0, MODULE_CFG_FRAGMENT_SINGLE, 0,
1010 (const uint8_t *)cdata, 0, NULL, 0);
1011 break;
1012 case COMP_CMD_GET_VALUE:
1013 /*
1014 * IPC3 does not use config_id, so pass 0 for config ID as it will be ignored
1015 * anyway. Also, pass the 0 as the fragment size and data offset as they are not
1016 * relevant for the GET_VALUE command.
1017 */
1018 if (md->ops->get_configuration)
1019 ret = md->ops->get_configuration(mod, 0, 0, (uint8_t *)cdata, 0);
1020 break;
1021 default:
1022 comp_err(dev, "module_adapter_cmd() error: unknown command");
1023 ret = -EINVAL;
1024 break;
1025 }
1026
1027 comp_dbg(dev, "module_adapter_cmd() done");
1028 return ret;
1029 }
1030
1031 #if CONFIG_IPC_MAJOR_3
module_source_status_count(struct comp_dev * dev,uint32_t status)1032 static int module_source_status_count(struct comp_dev *dev, uint32_t status)
1033 {
1034 struct list_item *blist;
1035 int count = 0;
1036
1037 /* count source with state == status */
1038 list_for_item(blist, &dev->bsource_list) {
1039 /*
1040 * FIXME: this is racy, state can be changed by another core.
1041 * This is implicitly protected by serialised IPCs. Even when
1042 * IPCs are processed in the pipeline thread, the next IPC will
1043 * not be sent until the thread has processed and replied to the
1044 * current one.
1045 */
1046 struct comp_buffer *source = container_of(blist, struct comp_buffer,
1047 sink_list);
1048 struct comp_buffer __sparse_cache *source_c = buffer_acquire(source);
1049
1050 if (source_c->source && source_c->source->state == status)
1051 count++;
1052 buffer_release(source_c);
1053 }
1054
1055 return count;
1056 }
1057 #endif
1058
module_adapter_trigger(struct comp_dev * dev,int cmd)1059 int module_adapter_trigger(struct comp_dev *dev, int cmd)
1060 {
1061 struct processing_module *mod = comp_get_drvdata(dev);
1062
1063 comp_dbg(dev, "module_adapter_trigger(): cmd %d", cmd);
1064
1065 /*
1066 * If the module doesn't support pause, keep it active along with the rest of the
1067 * downstream modules
1068 */
1069 if (cmd == COMP_TRIGGER_PAUSE && mod->no_pause) {
1070 dev->state = COMP_STATE_ACTIVE;
1071 return PPL_STATUS_PATH_STOP;
1072 }
1073
1074 #if CONFIG_IPC_MAJOR_3
1075 if (mod->num_input_buffers > 1) {
1076 bool sources_active;
1077 int ret;
1078
1079 sources_active = module_source_status_count(dev, COMP_STATE_ACTIVE) ||
1080 module_source_status_count(dev, COMP_STATE_PAUSED);
1081
1082 /* don't stop/start module if one of the sources is active/paused */
1083 if ((cmd == COMP_TRIGGER_STOP || cmd == COMP_TRIGGER_PRE_START) && sources_active) {
1084 dev->state = COMP_STATE_ACTIVE;
1085 return PPL_STATUS_PATH_STOP;
1086 }
1087
1088 ret = comp_set_state(dev, cmd);
1089 if (ret == COMP_STATUS_STATE_ALREADY_SET)
1090 return PPL_STATUS_PATH_STOP;
1091
1092 return ret;
1093 }
1094 #endif
1095 return comp_set_state(dev, cmd);
1096 }
1097
module_adapter_reset(struct comp_dev * dev)1098 int module_adapter_reset(struct comp_dev *dev)
1099 {
1100 int ret, i;
1101 struct processing_module *mod = comp_get_drvdata(dev);
1102 struct list_item *blist;
1103
1104 comp_dbg(dev, "module_adapter_reset(): resetting");
1105
1106 ret = module_reset(mod);
1107 if (ret) {
1108 if (ret != PPL_STATUS_PATH_STOP)
1109 comp_err(dev, "module_adapter_reset(): failed with error: %d", ret);
1110 return ret;
1111 }
1112
1113 if (!mod->simple_copy)
1114 for (i = 0; i < mod->num_output_buffers; i++)
1115 rfree((__sparse_force void *)mod->output_buffers[i].data);
1116
1117 rfree(mod->output_buffers);
1118
1119 if (!mod->simple_copy)
1120 for (i = 0; i < mod->num_input_buffers; i++)
1121 rfree((__sparse_force void *)mod->input_buffers[i].data);
1122
1123 rfree(mod->input_buffers);
1124
1125 mod->num_input_buffers = 0;
1126 mod->num_output_buffers = 0;
1127
1128 list_for_item(blist, &mod->sink_buffer_list) {
1129 struct comp_buffer *buffer = container_of(blist, struct comp_buffer,
1130 sink_list);
1131 struct comp_buffer __sparse_cache *buffer_c = buffer_acquire(buffer);
1132
1133 buffer_zero(buffer_c);
1134 buffer_release(buffer_c);
1135 }
1136
1137 rfree(mod->stream_params);
1138 mod->stream_params = NULL;
1139
1140 comp_dbg(dev, "module_adapter_reset(): done");
1141
1142 return comp_set_state(dev, COMP_TRIGGER_RESET);
1143 }
1144
module_adapter_free(struct comp_dev * dev)1145 void module_adapter_free(struct comp_dev *dev)
1146 {
1147 int ret;
1148 struct processing_module *mod = comp_get_drvdata(dev);
1149 struct list_item *blist, *_blist;
1150
1151 comp_dbg(dev, "module_adapter_free(): start");
1152
1153 ret = module_free(mod);
1154 if (ret)
1155 comp_err(dev, "module_adapter_free(): failed with error: %d", ret);
1156
1157 list_for_item_safe(blist, _blist, &mod->sink_buffer_list) {
1158 struct comp_buffer *buffer = container_of(blist, struct comp_buffer,
1159 sink_list);
1160
1161 buffer_detach(buffer, &mod->sink_buffer_list, PPL_DIR_UPSTREAM);
1162 buffer_free(buffer);
1163 }
1164
1165 coherent_free_thread(mod->source_info, c);
1166 rfree(mod);
1167 rfree(dev);
1168 }
1169
1170 #if CONFIG_IPC_MAJOR_4
module_set_large_config(struct comp_dev * dev,uint32_t param_id,bool first_block,bool last_block,uint32_t data_offset_size,const char * data)1171 int module_set_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block,
1172 bool last_block, uint32_t data_offset_size, const char *data)
1173 {
1174 struct processing_module *mod = comp_get_drvdata(dev);
1175 struct module_data *md = &mod->priv;
1176 enum module_cfg_fragment_position pos;
1177 size_t fragment_size;
1178
1179 /* set fragment position */
1180 pos = first_last_block_to_frag_pos(first_block, last_block);
1181
1182 switch (pos) {
1183 case MODULE_CFG_FRAGMENT_SINGLE:
1184 fragment_size = data_offset_size;
1185 break;
1186 case MODULE_CFG_FRAGMENT_MIDDLE:
1187 fragment_size = MAILBOX_DSPBOX_SIZE;
1188 break;
1189 case MODULE_CFG_FRAGMENT_FIRST:
1190 md->new_cfg_size = data_offset_size;
1191 fragment_size = MAILBOX_DSPBOX_SIZE;
1192 break;
1193 case MODULE_CFG_FRAGMENT_LAST:
1194 fragment_size = md->new_cfg_size - data_offset_size;
1195 break;
1196 default:
1197 comp_err(dev, "module_set_large_config(): invalid fragment position");
1198 return -EINVAL;
1199 }
1200
1201 if (md->ops->set_configuration)
1202 return md->ops->set_configuration(mod, param_id, pos, data_offset_size,
1203 (const uint8_t *)data,
1204 fragment_size, NULL, 0);
1205 return 0;
1206 }
1207
module_get_large_config(struct comp_dev * dev,uint32_t param_id,bool first_block,bool last_block,uint32_t * data_offset_size,char * data)1208 int module_get_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block,
1209 bool last_block, uint32_t *data_offset_size, char *data)
1210 {
1211 struct processing_module *mod = comp_get_drvdata(dev);
1212 struct module_data *md = &mod->priv;
1213 size_t fragment_size;
1214
1215 /* set fragment size */
1216 if (first_block) {
1217 if (last_block)
1218 fragment_size = md->cfg.size;
1219 else
1220 fragment_size = SOF_IPC_MSG_MAX_SIZE;
1221 } else {
1222 if (!last_block)
1223 fragment_size = SOF_IPC_MSG_MAX_SIZE;
1224 else
1225 fragment_size = md->cfg.size - *data_offset_size;
1226 }
1227
1228 if (md->ops->get_configuration)
1229 return md->ops->get_configuration(mod, param_id, data_offset_size,
1230 (uint8_t *)data, fragment_size);
1231 return 0;
1232 }
1233
module_adapter_get_attribute(struct comp_dev * dev,uint32_t type,void * value)1234 int module_adapter_get_attribute(struct comp_dev *dev, uint32_t type, void *value)
1235 {
1236 struct processing_module *mod = comp_get_drvdata(dev);
1237
1238 switch (type) {
1239 case COMP_ATTR_BASE_CONFIG:
1240 memcpy_s(value, sizeof(struct ipc4_base_module_cfg),
1241 &mod->priv.cfg.base_cfg, sizeof(mod->priv.cfg.base_cfg));
1242 break;
1243 default:
1244 return -EINVAL;
1245 }
1246
1247 return 0;
1248 }
1249
module_adapter_bind(struct comp_dev * dev,void * data)1250 int module_adapter_bind(struct comp_dev *dev, void *data)
1251 {
1252 struct module_source_info __sparse_cache *mod_source_info;
1253 struct processing_module *mod = comp_get_drvdata(dev);
1254 struct ipc4_module_bind_unbind *bu;
1255 struct comp_dev *source_dev;
1256 int source_index;
1257 int src_id;
1258
1259 bu = (struct ipc4_module_bind_unbind *)data;
1260 src_id = IPC4_COMP_ID(bu->primary.r.module_id, bu->primary.r.instance_id);
1261
1262 /* nothing to do if this module is the source during bind */
1263 if (dev->ipc_config.id == src_id)
1264 return 0;
1265
1266 source_dev = ipc4_get_comp_dev(src_id);
1267 if (!source_dev) {
1268 comp_err(dev, "module_adapter_bind: no source with ID %d found", src_id);
1269 return -EINVAL;
1270 }
1271
1272 mod_source_info = module_source_info_acquire(mod->source_info);
1273
1274 source_index = find_module_source_index(mod_source_info, source_dev);
1275 /*
1276 * this should never happen as source_info should have been already cleared in
1277 * module_adapter_unbind()
1278 */
1279 if (source_index >= 0)
1280 mod_source_info->sources[source_index] = NULL;
1281
1282 /* find an empty slot in the source_info array */
1283 source_index = find_module_source_index(mod_source_info, NULL);
1284 if (source_index < 0) {
1285 /* no free slot in module source_info array */
1286 comp_err(dev, "Too many inputs!");
1287 module_source_info_release(mod_source_info);
1288 return -ENOMEM;
1289 }
1290
1291 /* set the source dev pointer */
1292 mod_source_info->sources[source_index] = source_dev;
1293
1294 module_source_info_release(mod_source_info);
1295
1296 return 0;
1297 }
1298
module_adapter_unbind(struct comp_dev * dev,void * data)1299 int module_adapter_unbind(struct comp_dev *dev, void *data)
1300 {
1301 struct module_source_info __sparse_cache *mod_source_info;
1302 struct processing_module *mod = comp_get_drvdata(dev);
1303 struct ipc4_module_bind_unbind *bu;
1304 struct comp_dev *source_dev;
1305 int source_index;
1306 int src_id;
1307
1308 bu = (struct ipc4_module_bind_unbind *)data;
1309 src_id = IPC4_COMP_ID(bu->primary.r.module_id, bu->primary.r.instance_id);
1310
1311 /* nothing to do if this module is the source during unbind */
1312 if (dev->ipc_config.id == src_id)
1313 return 0;
1314
1315 source_dev = ipc4_get_comp_dev(src_id);
1316 if (!source_dev) {
1317 comp_err(dev, "module_adapter_bind: no source with ID %d found", src_id);
1318 return -EINVAL;
1319 }
1320
1321 mod_source_info = module_source_info_acquire(mod->source_info);
1322
1323 /* find the index of the source in the sources array and clear it */
1324 source_index = find_module_source_index(mod_source_info, source_dev);
1325 if (source_index >= 0)
1326 mod_source_info->sources[source_index] = NULL;
1327
1328 module_source_info_release(mod_source_info);
1329
1330 return 0;
1331 }
1332 #else
module_adapter_get_attribute(struct comp_dev * dev,uint32_t type,void * value)1333 int module_adapter_get_attribute(struct comp_dev *dev, uint32_t type, void *value)
1334 {
1335 return -EINVAL;
1336 }
module_set_large_config(struct comp_dev * dev,uint32_t param_id,bool first_block,bool last_block,uint32_t data_offset,const char * data)1337 int module_set_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block,
1338 bool last_block, uint32_t data_offset, const char *data)
1339 {
1340 return 0;
1341 }
1342
module_get_large_config(struct comp_dev * dev,uint32_t param_id,bool first_block,bool last_block,uint32_t * data_offset,char * data)1343 int module_get_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block,
1344 bool last_block, uint32_t *data_offset, char *data)
1345 {
1346 return 0;
1347 }
1348
module_adapter_bind(struct comp_dev * dev,void * data)1349 int module_adapter_bind(struct comp_dev *dev, void *data)
1350 {
1351 return 0;
1352 }
1353
module_adapter_unbind(struct comp_dev * dev,void * data)1354 int module_adapter_unbind(struct comp_dev *dev, void *data)
1355 {
1356 return 0;
1357 }
1358 #endif
1359