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