1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2022 Intel Corporation. All rights reserved.
4 //
5 // Author: Adrian Bonislawski <adrian.bonislawski@intel.com>
6 
7 #include <sof/audio/aria/aria.h>
8 #include <sof/audio/buffer.h>
9 #include <sof/audio/format.h>
10 #include <sof/audio/pipeline.h>
11 #include <rtos/panic.h>
12 #include <sof/ipc/msg.h>
13 #include <rtos/alloc.h>
14 #include <rtos/cache.h>
15 #include <rtos/init.h>
16 #include <sof/lib/memory.h>
17 #include <sof/lib/notifier.h>
18 #include <sof/lib/uuid.h>
19 #include <sof/list.h>
20 #include <rtos/string.h>
21 #include <sof/ut.h>
22 #include <sof/trace/trace.h>
23 #include <ipc4/aria.h>
24 #include <ipc4/fw_reg.h>
25 #include <ipc/dai.h>
26 #include <user/trace.h>
27 #include <errno.h>
28 #include <stddef.h>
29 #include <stdint.h>
30 
31 static const struct comp_driver comp_aria;
32 
33 LOG_MODULE_REGISTER(aria, CONFIG_SOF_LOG_LEVEL);
34 
35 /* these ids aligns windows driver requirement to support windows driver */
36 /* 99f7166d-372c-43ef-81f6-22007aa15f03 */
37 DECLARE_SOF_RT_UUID("aria", aria_comp_uuid, 0x99f7166d, 0x372c, 0x43ef,
38 		    0x81, 0xf6, 0x22, 0x00, 0x7a, 0xa1, 0x5f, 0x03);
39 
40 DECLARE_TR_CTX(aria_comp_tr, SOF_UUID(aria_comp_uuid), LOG_LEVEL_INFO);
41 
get_required_emory(size_t chan_cnt,size_t smpl_group_cnt)42 static size_t get_required_emory(size_t chan_cnt, size_t smpl_group_cnt)
43 {
44 	/* Current implementation is able to apply 1 ms transition */
45 	/* internal circular buffer aligned to 8 bytes */
46 	const size_t num_of_ms = 1;
47 
48 	return ALIGN_UP(num_of_ms * chan_cnt * smpl_group_cnt, 2) * sizeof(int32_t);
49 }
50 
aria_algo_init(struct comp_dev * dev,void * buffer_desc,void * buf_in,void * buf_out,size_t att,size_t chan_cnt,size_t smpl_group_cnt)51 static int aria_algo_init(struct comp_dev *dev, void *buffer_desc, void *buf_in,
52 			  void *buf_out, size_t att, size_t chan_cnt, size_t smpl_group_cnt)
53 {
54 	struct aria_data *cd = comp_get_drvdata(dev);
55 	size_t idx;
56 
57 	cd->chan_cnt = chan_cnt;
58 	cd->smpl_group_cnt = smpl_group_cnt;
59 	/* ensures buffer size is aligned to 8 bytes */
60 	cd->buff_size = ALIGN_UP(cd->chan_cnt * cd->smpl_group_cnt, 2);
61 	cd->offset = (cd->chan_cnt * cd->smpl_group_cnt) % 2;
62 	cd->att = att;
63 	cd->data = buffer_desc;
64 	cd->buf_in = buf_in;
65 	cd->buf_out = buf_out;
66 	cd->buff_pos = 0;
67 
68 	for (idx = 0; idx < ARIA_MAX_GAIN_STATES; ++idx)
69 		cd->gains[idx] = (1ULL << (32 - cd->att - 1)) - 1;
70 
71 	memset((void *)cd->data, 0, sizeof(int32_t) * cd->buff_size);
72 	memset((void *)cd->buf_in, 0, sizeof(int32_t) * cd->buff_size);
73 	memset((void *)cd->buf_out, 0, sizeof(int32_t) * cd->buff_size);
74 	cd->gain_state = 0;
75 
76 	return 0;
77 }
78 
aria_algo_buffer_data(struct comp_dev * dev,int32_t * __restrict data,size_t size)79 int aria_algo_buffer_data(struct comp_dev *dev, int32_t *__restrict data, size_t size)
80 {
81 	struct aria_data *cd = comp_get_drvdata(dev);
82 	size_t min_buff = MIN(cd->buff_size - cd->buff_pos - cd->offset, size);
83 	int ret;
84 
85 	ret = memcpy_s(&cd->data[cd->buff_pos], cd->buff_size * sizeof(int32_t),
86 		       data, min_buff * sizeof(int32_t));
87 	if (ret < 0)
88 		return ret;
89 	ret = memcpy_s(cd->data, cd->buff_size * sizeof(int32_t),
90 		       &data[min_buff], (size - min_buff) * sizeof(int32_t));
91 	if (ret < 0)
92 		return ret;
93 	cd->buff_pos = (cd->buff_pos + size) % cd->buff_size;
94 
95 	return 0;
96 }
97 
aria_process_data(struct comp_dev * dev,int32_t * __restrict dst,size_t dst_size,int32_t * __restrict src,size_t src_size)98 int aria_process_data(struct comp_dev *dev,
99 		      int32_t *__restrict dst, size_t dst_size,
100 		      int32_t *__restrict src, size_t src_size)
101 {
102 	struct aria_data *cd = comp_get_drvdata(dev);
103 	size_t min_buff;
104 	int ret;
105 
106 	if (cd->att) {
107 		aria_algo_calc_gain(dev, (cd->gain_state + 1) % ARIA_MAX_GAIN_STATES,
108 				    src, src_size);
109 		aria_algo_get_data(dev, dst, dst_size);
110 	} else {
111 		/* bypass processing gets unprocessed data from buffer */
112 		min_buff = MIN(cd->buff_size - cd->buff_pos - cd->offset, dst_size);
113 		ret = memcpy_s(dst, cd->buff_size * sizeof(int32_t),
114 			       &cd->data[cd->buff_pos + cd->offset],
115 			       min_buff * sizeof(int32_t));
116 		if (ret < 0)
117 			return ret;
118 		ret = memcpy_s(&dst[min_buff], cd->buff_size * sizeof(int32_t),
119 			       cd->data, (dst_size - min_buff) * sizeof(int32_t));
120 		if (ret < 0)
121 			return ret;
122 	}
123 	return aria_algo_buffer_data(dev, src, src_size);
124 }
125 
init_aria(struct comp_dev * dev,const struct comp_ipc_config * config,const void * spec)126 static int init_aria(struct comp_dev *dev, const struct comp_ipc_config *config,
127 		     const void *spec)
128 {
129 	const struct ipc4_aria_module_cfg *aria = spec;
130 	struct aria_data *cd;
131 	size_t ibs, chc, sgs, sgc, req_mem, att;
132 	void *buf, *buf_in, *buf_out;
133 	int ret;
134 
135 	dev->ipc_config = *config;
136 	list_init(&dev->bsource_list);
137 	list_init(&dev->bsink_list);
138 
139 	dcache_invalidate_region((__sparse_force void __sparse_cache *)spec, sizeof(*aria));
140 	cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd));
141 	if (!cd) {
142 		comp_free(dev);
143 		return -ENOMEM;
144 	}
145 
146 	/* Copy received data format to local structures */
147 	ret = memcpy_s(&cd->base, sizeof(struct ipc4_base_module_cfg),
148 		       &aria->base_cfg, sizeof(struct ipc4_base_module_cfg));
149 	if (ret < 0)
150 		return ret;
151 
152 	ibs = cd->base.ibs;
153 	chc = cd->base.audio_fmt.channels_count;
154 	sgs = (cd->base.audio_fmt.depth >> 3) * chc;
155 	sgc = ibs / sgs;
156 	req_mem = get_required_emory(chc, sgc);
157 	att = aria->attenuation;
158 
159 	if (aria->attenuation > ARIA_MAX_ATT) {
160 		comp_warn(dev, "init_aria(): Attenuation value %d must not be greater than %d",
161 			  att, ARIA_MAX_ATT);
162 		att = ARIA_MAX_ATT;
163 	}
164 
165 	comp_set_drvdata(dev, cd);
166 
167 	buf = rballoc(0, SOF_MEM_CAPS_RAM, req_mem);
168 	buf_in = rballoc(0, SOF_MEM_CAPS_RAM, req_mem);
169 	buf_out = rballoc(0, SOF_MEM_CAPS_RAM, req_mem);
170 
171 	if (!buf || !buf_in || !buf_out) {
172 		rfree(buf);
173 		rfree(buf_in);
174 		rfree(buf_out);
175 		rfree(cd);
176 		comp_free(dev);
177 		comp_err(dev, "init_aria(): allocation failed for size %d", req_mem);
178 		return -ENOMEM;
179 	}
180 
181 	return aria_algo_init(dev, buf, buf_in, buf_out, att, chc, sgc);
182 }
183 
aria_new(const struct comp_driver * drv,const struct comp_ipc_config * config,const void * spec)184 static struct comp_dev *aria_new(const struct comp_driver *drv,
185 				 const struct comp_ipc_config *config,
186 				 const void *spec)
187 {
188 	struct comp_dev *dev;
189 	int ret;
190 
191 	comp_cl_info(&comp_aria, "aria_new()");
192 
193 	dev = comp_alloc(drv, sizeof(*dev));
194 	if (!dev)
195 		return NULL;
196 
197 	ret = init_aria(dev, config, spec);
198 	if (ret < 0) {
199 		comp_free(dev);
200 		return NULL;
201 	}
202 	dev->state = COMP_STATE_READY;
203 
204 	return dev;
205 }
206 
aria_free(struct comp_dev * dev)207 static void aria_free(struct comp_dev *dev)
208 {
209 	struct aria_data *cd = comp_get_drvdata(dev);
210 
211 	rfree(cd->data);
212 	rfree(cd->buf_in);
213 	rfree(cd->buf_out);
214 	rfree(cd);
215 	rfree(dev);
216 }
217 
aria_set_stream_params(struct comp_buffer * buffer,struct aria_data * cd)218 static void aria_set_stream_params(struct comp_buffer *buffer, struct aria_data *cd)
219 {
220 	struct comp_buffer __sparse_cache *buffer_c;
221 
222 	buffer_c = buffer_acquire(buffer);
223 	buffer_c->stream.channels = cd->chan_cnt;
224 	buffer_c->stream.rate = cd->base.audio_fmt.sampling_frequency;
225 	buffer_c->buffer_fmt = cd->base.audio_fmt.interleaving_style;
226 	audio_stream_fmt_conversion(cd->base.audio_fmt.depth,
227 				    cd->base.audio_fmt.valid_bit_depth,
228 				    &buffer_c->stream.frame_fmt,
229 				    &buffer_c->stream.valid_sample_fmt,
230 				    cd->base.audio_fmt.s_type);
231 	buffer_release(buffer_c);
232 }
233 
aria_prepare(struct comp_dev * dev)234 static int aria_prepare(struct comp_dev *dev)
235 {
236 	int ret;
237 	struct comp_buffer *source, *sink;
238 	struct aria_data *cd = comp_get_drvdata(dev);
239 
240 	comp_info(dev, "aria_prepare()");
241 
242 	source = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list);
243 	aria_set_stream_params(source, cd);
244 
245 	sink = list_first_item(&dev->bsink_list, struct comp_buffer, source_list);
246 	aria_set_stream_params(sink, cd);
247 
248 	if (dev->state == COMP_STATE_ACTIVE) {
249 		comp_info(dev, "aria_prepare(): Component is in active state.");
250 		return 0;
251 	}
252 
253 	ret = comp_set_state(dev, COMP_TRIGGER_PREPARE);
254 	if (ret < 0)
255 		return ret;
256 
257 	if (ret == COMP_STATUS_STATE_ALREADY_SET)
258 		return PPL_STATUS_PATH_STOP;
259 
260 	return 0;
261 }
262 
aria_reset(struct comp_dev * dev)263 static int aria_reset(struct comp_dev *dev)
264 {
265 	struct aria_data *cd = comp_get_drvdata(dev);
266 	int idx;
267 
268 	comp_info(dev, "aria_reset()");
269 
270 	if (dev->state == COMP_STATE_ACTIVE) {
271 		comp_info(dev, "aria module is in active state. Ignore resetting");
272 		return 0;
273 	}
274 
275 	for (idx = 0; idx < ARIA_MAX_GAIN_STATES; ++idx)
276 		cd->gains[idx] = (1ULL << (32 - cd->att - 1)) - 1;
277 
278 	memset(cd->data, 0, sizeof(int32_t) * cd->buff_size);
279 	memset(cd->buf_in, 0, sizeof(int32_t) * cd->buff_size);
280 	memset(cd->buf_out, 0, sizeof(int32_t) * cd->buff_size);
281 	cd->gain_state = 0;
282 
283 	comp_set_state(dev, COMP_TRIGGER_RESET);
284 
285 	return 0;
286 }
287 
aria_trigger(struct comp_dev * dev,int cmd)288 static int aria_trigger(struct comp_dev *dev, int cmd)
289 {
290 	comp_info(dev, "aria_trigger()");
291 
292 	return comp_set_state(dev, cmd);
293 }
294 
aria_copy(struct comp_dev * dev)295 static int aria_copy(struct comp_dev *dev)
296 {
297 	struct comp_copy_limits c;
298 	struct comp_buffer *source, *sink;
299 	struct comp_buffer __sparse_cache *source_c, *sink_c;
300 	struct aria_data *cd;
301 	uint32_t source_bytes;
302 	uint32_t sink_bytes;
303 	uint32_t frag = 0;
304 	int32_t *destp;
305 	int32_t i, channel;
306 
307 	cd = comp_get_drvdata(dev);
308 
309 	comp_dbg(dev, "aria_copy()");
310 
311 	source = list_first_item(&dev->bsource_list, struct comp_buffer,
312 				 sink_list);
313 	sink = list_first_item(&dev->bsink_list, struct comp_buffer,
314 			       source_list);
315 
316 	source_c = buffer_acquire(source);
317 	sink_c = buffer_acquire(sink);
318 
319 	comp_get_copy_limits(source_c, sink_c, &c);
320 	source_bytes = c.frames * c.source_frame_bytes;
321 	sink_bytes = c.frames * c.sink_frame_bytes;
322 
323 	if (source_bytes == 0)
324 		goto out;
325 
326 	buffer_stream_invalidate(source_c, source_bytes);
327 
328 	for (i = 0; i < c.frames; i++) {
329 		for (channel = 0; channel < sink_c->stream.channels; channel++) {
330 			cd->buf_in[frag] = *(int32_t *)audio_stream_read_frag_s32(&source_c->stream,
331 										  frag);
332 
333 			frag++;
334 		}
335 	}
336 	dcache_writeback_region((__sparse_force void __sparse_cache *)cd->buf_in,
337 				c.frames * sink_c->stream.channels * sizeof(int32_t));
338 
339 	aria_process_data(dev, cd->buf_out, sink_bytes / sizeof(uint32_t),
340 			  cd->buf_in, source_bytes / sizeof(uint32_t));
341 
342 	dcache_writeback_region((__sparse_force void __sparse_cache *)cd->buf_out,
343 				c.frames * sink_c->stream.channels * sizeof(int32_t));
344 	frag = 0;
345 	for (i = 0; i < c.frames; i++) {
346 		for (channel = 0; channel < sink_c->stream.channels; channel++) {
347 			destp = audio_stream_write_frag_s32(&sink_c->stream, frag);
348 			*destp = cd->buf_out[frag];
349 
350 			frag++;
351 		}
352 	}
353 
354 	buffer_stream_writeback(sink_c, sink_bytes);
355 
356 	comp_update_buffer_produce(sink_c, sink_bytes);
357 	comp_update_buffer_consume(source_c, source_bytes);
358 
359 out:
360 	buffer_release(sink_c);
361 	buffer_release(source_c);
362 
363 	return 0;
364 }
365 
aria_get_attribute(struct comp_dev * dev,uint32_t type,void * value)366 static int aria_get_attribute(struct comp_dev *dev, uint32_t type, void *value)
367 {
368 	struct aria_data *cd = comp_get_drvdata(dev);
369 
370 	switch (type) {
371 	case COMP_ATTR_BASE_CONFIG:
372 		*(struct ipc4_base_module_cfg *)value = cd->base;
373 		break;
374 	default:
375 		return -EINVAL;
376 	}
377 
378 	return 0;
379 }
380 
381 static const struct comp_driver comp_aria = {
382 	.uid	= SOF_RT_UUID(aria_comp_uuid),
383 	.tctx	= &aria_comp_tr,
384 	.ops	= {
385 		.create			= aria_new,
386 		.free			= aria_free,
387 		.trigger		= aria_trigger,
388 		.copy			= aria_copy,
389 		.prepare		= aria_prepare,
390 		.reset			= aria_reset,
391 		.get_attribute		= aria_get_attribute,
392 	},
393 };
394 
395 static SHARED_DATA struct comp_driver_info comp_aria_info = {
396 	.drv = &comp_aria,
397 };
398 
sys_comp_aria_init(void)399 UT_STATIC void sys_comp_aria_init(void)
400 {
401 	comp_register(platform_shared_get(&comp_aria_info,
402 					  sizeof(comp_aria_info)));
403 }
404 
405 DECLARE_MODULE(sys_comp_aria_init);
406 SOF_MODULE_INIT(aria, sys_comp_aria_init);
407