1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2020 Intel Corporation. All rights reserved.
4  *
5  * Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com>
6  */
7 
8 /**
9   * \file include/sof/audio/audio_stream.h
10   * \brief Audio Stream API definition
11   * \author Karol Trzcinski <karolx.trzcinski@linux.intel.com>
12   */
13 
14 #ifndef __SOF_AUDIO_AUDIO_STREAM_H__
15 #define __SOF_AUDIO_AUDIO_STREAM_H__
16 
17 #include <sof/audio/format.h>
18 #include <sof/compiler_attributes.h>
19 #include <rtos/panic.h>
20 #include <sof/math/numbers.h>
21 #include <rtos/alloc.h>
22 #include <rtos/cache.h>
23 #include <ipc/stream.h>
24 #include <ipc4/base-config.h>
25 
26 #include <stdbool.h>
27 #include <stdint.h>
28 
29 /** \addtogroup audio_stream_api Audio Stream API
30  *  @{
31  */
32 
33 /**
34  * Audio stream is a circular buffer aware of audio format of the data
35  * in the buffer so provides API for reading and writing not only bytes,
36  * but also samples and frames.
37  *
38  * Audio stream does not perform any memory allocations. A client (a component
39  * buffer or dma) must allocate the memory for the underlying data buffer and
40  * provide it to the initialization routine.
41  *
42  * Once the client is done with reading/writing the data, it must commit the
43  * consumption/production and update the buffer state by calling
44  * audio_stream_consume()/audio_stream_produce() (just a single call following
45  * series of reads/writes).
46  */
47 struct audio_stream {
48 	/* runtime data */
49 	uint32_t size;	/**< Runtime buffer size in bytes (period multiple) */
50 	uint32_t avail;	/**< Available bytes for reading */
51 	uint32_t free;	/**< Free bytes for writing */
52 	void *w_ptr;	/**< Buffer write pointer */
53 	void *r_ptr;	/**< Buffer read position */
54 	void *addr;	/**< Buffer base address */
55 	void *end_addr;	/**< Buffer end address */
56 
57 	/* runtime stream params */
58 	enum sof_ipc_frame frame_fmt;	/**< Sample data format */
59 	enum sof_ipc_frame valid_sample_fmt;
60 
61 	uint32_t rate;		/**< Number of data frames per second [Hz] */
62 	uint16_t channels;	/**< Number of samples in each frame */
63 
64 	/** alignment limit of stream copy, this value indicates how many
65 	 * integer frames which can meet both byte align and frame align
66 	 * requirement. it should be set in component prepare or param functions
67 	 */
68 	uint16_t frame_align;
69 
70 	/**
71 	 * alignment limit of stream copy, alignment is the frame_align_shift-th
72 	 * power of 2 bytes. it should be set in component prepare or param functions
73 	 */
74 	uint16_t frame_align_shift;
75 
76 	bool overrun_permitted; /**< indicates whether overrun is permitted */
77 	bool underrun_permitted; /**< indicates whether underrun is permitted */
78 };
79 
80 /**
81  * Retrieves readable address of a sample at specified index (see versions of
82  * this macro specialized for various sample types).
83  * @param buffer Buffer.
84  * @param idx Index of sample.
85  * @param size Size of sample in bytes.
86  * @return Pointer to the sample.
87  *
88  * Once the consumer finishes reading samples from the buffer, it should
89  * "commit" the operation and update the buffer state by calling
90  * audio_stream_consume().
91  *
92  * @note Components should call comp_update_buffer_consume().
93  *
94  * @see audio_stream_get_frag().
95  * @see audio_stream_consume().
96  * @see comp_update_buffer_consume().
97  */
98 #define audio_stream_read_frag(buffer, idx, size) \
99 	audio_stream_get_frag(buffer, (buffer)->r_ptr, idx, size)
100 
101 /**
102  * Retrieves readable address of a signed 16-bit sample at specified index.
103  * @param buffer Buffer.
104  * @param idx Index of sample.
105  * @return Pointer to the sample.
106  *
107  * @see audio_stream_get_frag().
108  */
109 #define audio_stream_read_frag_s16(buffer, idx) \
110 	audio_stream_get_frag(buffer, (buffer)->r_ptr, idx, sizeof(int16_t))
111 
112 /**
113  * Retrieves readable address of a signed 32-bit sample at specified index.
114  * @param buffer Buffer.
115  * @param idx Index of sample.
116  * @return Pointer to the sample.
117  *
118  * @see audio_stream_get_frag().
119  */
120 #define audio_stream_read_frag_s32(buffer, idx) \
121 	audio_stream_get_frag(buffer, (buffer)->r_ptr, idx, sizeof(int32_t))
122 
123 /**
124  * Retrieves writeable address of a sample at specified index (see versions of
125  * this macro specialized for various sample types).
126  * @param buffer Buffer.
127  * @param idx Index of sample.
128  * @param size Size of sample in bytes.
129  * @return Pointer to the space for sample.
130  *
131  * Once the producer finishes writing samples to the buffer, it should
132  * "commit" the operation and update the buffer state by calling
133  * audio_stream_produce().
134  *
135  * @note Components should call comp_update_buffer_produce().
136  *
137  * @see audio_stream_get_frag().
138  * @see audio_stream_produce().
139  * @see comp_update_buffer_produce().
140  */
141 #define audio_stream_write_frag(buffer, idx, size) \
142 	audio_stream_get_frag(buffer, (buffer)->w_ptr, idx, size)
143 
144 /**
145  * Retrieves writeable address of a signed 16-bit sample at specified index.
146  * @param buffer Buffer.
147  * @param idx Index of sample.
148  * @return Pointer to the space for sample.
149  *
150  * @see audio_stream_get_frag().
151  */
152 #define audio_stream_write_frag_s16(buffer, idx) \
153 	audio_stream_get_frag(buffer, (buffer)->w_ptr, idx, sizeof(int16_t))
154 
155 /**
156  * Retrieves writeable address of a signed 32-bit sample at specified index.
157  * @param buffer Buffer.
158  * @param idx Index of sample.
159  * @return Pointer to the space for sample.
160  *
161  * @see audio_stream_get_frag().
162  */
163 #define audio_stream_write_frag_s32(buffer, idx) \
164 	audio_stream_get_frag(buffer, (buffer)->w_ptr, idx, sizeof(int32_t))
165 
166 /**
167  * Retrieves address of sample (space for sample) at specified index within
168  * the buffer. Index is interpreted as an offset relative to the specified
169  * pointer, rollover is ensured.
170  * @param buffer Circular buffer.
171  * @param ptr Pointer to start from, it may be either read or write pointer.
172  * @param idx Index of the sample.
173  * @param sample_size Size of the sample in bytes.
174  * @return Pointer to the sample.
175  */
176 #define audio_stream_get_frag(buffer, ptr, idx, sample_size) \
177 	audio_stream_wrap(buffer, (char *)(ptr) + ((idx) * (sample_size)))
178 
179 /**
180  * Applies parameters to the buffer.
181  * @param buffer Buffer.
182  * @param params Parameters (frame format, rate, number of channels).
183  * @return 0 if succeeded, error code otherwise.
184  */
audio_stream_set_params(struct audio_stream __sparse_cache * buffer,struct sof_ipc_stream_params * params)185 static inline int audio_stream_set_params(struct audio_stream __sparse_cache *buffer,
186 					  struct sof_ipc_stream_params *params)
187 {
188 	if (!params)
189 		return -EINVAL;
190 
191 	buffer->frame_fmt = params->frame_fmt;
192 	buffer->rate = params->rate;
193 	buffer->channels = params->channels;
194 
195 	return 0;
196 }
197 
198 /**
199  * Calculates period size in bytes based on component stream's parameters.
200  * @param buf Component buffer.
201  * @return Period size in bytes.
202  */
audio_stream_frame_bytes(const struct audio_stream __sparse_cache * buf)203 static inline uint32_t audio_stream_frame_bytes(const struct audio_stream __sparse_cache *buf)
204 {
205 	return get_frame_bytes(buf->frame_fmt, buf->channels);
206 }
207 
208 /**
209  * Calculates sample size in bytes based on component stream's parameters.
210  * @param buf Component buffer.
211  * @return Size of sample in bytes.
212  */
audio_stream_sample_bytes(const struct audio_stream __sparse_cache * buf)213 static inline uint32_t audio_stream_sample_bytes(const struct audio_stream __sparse_cache *buf)
214 {
215 	return get_sample_bytes(buf->frame_fmt);
216 }
217 
218 /**
219  * Return the frames that meet the align requirement of both byte_align and
220  * frame_align_req.
221  * @param byte_align Processing byte alignment requirement.
222  * @param frame_align_req Processing frames alignment requirement.
223  * @param frame_size Size of the frame in bytes.
224  * @return frame number.
225  */
audio_stream_frame_align_get(const uint32_t byte_align,const uint32_t frame_align_req,uint32_t frame_size)226 static inline uint32_t audio_stream_frame_align_get(const uint32_t byte_align,
227 						    const uint32_t frame_align_req,
228 						    uint32_t frame_size)
229 {
230 	/* Figure out how many frames are needed to meet the byte_align alignment requirements */
231 	uint32_t frame_num = byte_align / gcd(byte_align, frame_size);
232 
233 	/** return the lcm of frame_num and frame_align_req*/
234 	return frame_align_req * frame_num / gcd(frame_num, frame_align_req);
235 }
236 
237 /**
238  * Set frame_align_shift and frame_align of stream according to byte_align and
239  * frame_align_req alignment requirement. Once the channel number,frame size
240  * are determined,the frame_align and frame_align_shift are determined too.
241  * these two feature will be used in audio_stream_get_avail_frames_aligned
242  * to calculate the available frames. it should be called in component prepare
243  * or param functions only once before stream copy. if someone forgets to call
244  * this first, there would be unexampled error such as nothing is copied at all.
245  * @param byte_align Processing byte alignment requirement.
246  * @param frame_align_req Processing frames alignment requirement.
247  * @param stream Sink or source stream structure which to be set.
248  */
audio_stream_init_alignment_constants(const uint32_t byte_align,const uint32_t frame_align_req,struct audio_stream __sparse_cache * stream)249 static inline void audio_stream_init_alignment_constants(const uint32_t byte_align,
250 							 const uint32_t frame_align_req,
251 							 struct audio_stream __sparse_cache *stream)
252 {
253 	uint32_t process_size;
254 	uint32_t frame_size = audio_stream_frame_bytes(stream);
255 
256 	stream->frame_align = audio_stream_frame_align_get(byte_align, frame_align_req, frame_size);
257 	process_size = stream->frame_align * frame_size;
258 	stream->frame_align_shift = (is_power_of_2(process_size) ? 31 : 32) - clz(process_size);
259 }
260 
261 /**
262  * Calculates period size in bytes based on component stream's parameters.
263  * @param buf Component buffer.
264  * @param frames Number of processing frames.
265  * @return Period size in bytes.
266  */
audio_stream_period_bytes(const struct audio_stream __sparse_cache * buf,uint32_t frames)267 static inline uint32_t audio_stream_period_bytes(const struct audio_stream __sparse_cache *buf,
268 						 uint32_t frames)
269 {
270 	return frames * audio_stream_frame_bytes(buf);
271 }
272 
273 /**
274  * Verifies the pointer and performs rollover when reached the end of
275  * the buffer.
276  * @param buffer Buffer accessed by the pointer.
277  * @param ptr Pointer
278  * @return Pointer, adjusted if necessary.
279  */
audio_stream_wrap(const struct audio_stream __sparse_cache * buffer,void * ptr)280 static inline void *audio_stream_wrap(const struct audio_stream __sparse_cache *buffer,
281 				      void *ptr)
282 {
283 	if (ptr >= buffer->end_addr)
284 		ptr = (char *)buffer->addr +
285 			((char *)ptr - (char *)buffer->end_addr);
286 
287 	assert((intptr_t)ptr <= (intptr_t)buffer->end_addr);
288 
289 	return ptr;
290 }
291 
292 /**
293  * Verifies the pointer and performs rollover when reached the end of
294  * the buffer.
295  * @param buffer Buffer accessed by the pointer.
296  * @param ptr Pointer
297  * @return Pointer, adjusted if necessary.
298  */
audio_stream_rewind_wrap(const struct audio_stream __sparse_cache * buffer,void * ptr)299 static inline void *audio_stream_rewind_wrap(const struct audio_stream __sparse_cache *buffer,
300 					     void *ptr)
301 {
302 	if (ptr < buffer->addr)
303 		ptr = (char *)buffer->end_addr - ((char *)buffer->addr - (char *)ptr);
304 
305 	assert((intptr_t)ptr >= (intptr_t)buffer->addr);
306 
307 	return ptr;
308 }
309 
310 /**
311  * Calculates available data in bytes, handling underrun_permitted behaviour
312  * @param stream Stream pointer
313  * @return amount of data available for processing in bytes
314  */
315 static inline uint32_t
audio_stream_get_avail_bytes(const struct audio_stream __sparse_cache * stream)316 audio_stream_get_avail_bytes(const struct audio_stream __sparse_cache *stream)
317 {
318 	/*
319 	 * In case of underrun-permitted stream, report buffer full instead of
320 	 * empty. This way, any data present in such stream is processed at
321 	 * regular pace, but buffer will never be seen as completely empty by
322 	 * clients, and in turn will not cause underrun/XRUN.
323 	 */
324 	if (stream->underrun_permitted)
325 		return stream->avail != 0 ? stream->avail : stream->size;
326 
327 	return stream->avail;
328 }
329 
330 /**
331  * Calculates available data in samples, handling underrun_permitted behaviour
332  * @param stream Stream pointer
333  * @return amount of data available for processing in samples
334  */
335 static inline uint32_t
audio_stream_get_avail_samples(const struct audio_stream __sparse_cache * stream)336 audio_stream_get_avail_samples(const struct audio_stream __sparse_cache *stream)
337 {
338 	return audio_stream_get_avail_bytes(stream) /
339 		audio_stream_sample_bytes(stream);
340 }
341 
342 /**
343  * Calculates available data in frames, handling underrun_permitted behaviour
344  * @param stream Stream pointer
345  * @return amount of data available for processing in frames
346  */
347 static inline uint32_t
audio_stream_get_avail_frames(const struct audio_stream __sparse_cache * stream)348 audio_stream_get_avail_frames(const struct audio_stream __sparse_cache *stream)
349 {
350 	return audio_stream_get_avail_bytes(stream) /
351 		audio_stream_frame_bytes(stream);
352 }
353 
354 /**
355  * Calculates free space in bytes, handling overrun_permitted behaviour
356  * @param stream Stream pointer
357  * @return amount of space free in bytes
358  */
359 static inline uint32_t
audio_stream_get_free_bytes(const struct audio_stream __sparse_cache * stream)360 audio_stream_get_free_bytes(const struct audio_stream __sparse_cache *stream)
361 {
362 	/*
363 	 * In case of overrun-permitted stream, report buffer empty instead of
364 	 * full. This way, if there's any actual free space for data it is
365 	 * processed at regular pace, but buffer will never be seen as
366 	 * completely full by clients, and in turn will not cause overrun/XRUN.
367 	 */
368 	if (stream->overrun_permitted)
369 		return stream->free != 0 ? stream->free : stream->size;
370 
371 	return stream->free;
372 }
373 
374 /**
375  * Calculates free space in samples, handling overrun_permitted behaviour
376  * @param stream Stream pointer
377  * @return amount of space free in samples
378  */
379 static inline uint32_t
audio_stream_get_free_samples(const struct audio_stream __sparse_cache * stream)380 audio_stream_get_free_samples(const struct audio_stream __sparse_cache *stream)
381 {
382 	return audio_stream_get_free_bytes(stream) /
383 		audio_stream_sample_bytes(stream);
384 }
385 
386 /**
387  * Calculates free space in frames, handling overrun_permitted behaviour
388  * @param stream Stream pointer
389  * @return amount of space free in frames
390  */
391 static inline uint32_t
audio_stream_get_free_frames(const struct audio_stream __sparse_cache * stream)392 audio_stream_get_free_frames(const struct audio_stream __sparse_cache *stream)
393 {
394 	return audio_stream_get_free_bytes(stream) /
395 		audio_stream_frame_bytes(stream);
396 }
397 
398 /**
399  *  Verifies whether specified number of bytes can be copied from source buffer
400  *  to sink buffer.
401  *  @param source Source buffer.
402  *  @param sink Sink buffer.
403  *  @param bytes Number of bytes to copy.
404  *  @return 0 if there is enough data in source and enough free space in sink.
405  *  @return 1 if there is not enough free space in sink.
406  *  @return -1 if there is not enough data in source.
407  */
audio_stream_can_copy_bytes(const struct audio_stream __sparse_cache * source,const struct audio_stream __sparse_cache * sink,uint32_t bytes)408 static inline int audio_stream_can_copy_bytes(const struct audio_stream __sparse_cache *source,
409 					      const struct audio_stream __sparse_cache *sink,
410 					      uint32_t bytes)
411 {
412 	/* check for underrun */
413 	if (audio_stream_get_avail_bytes(source) < bytes)
414 		return -1;
415 
416 	/* check for overrun */
417 	if (audio_stream_get_free_bytes(sink) < bytes)
418 		return 1;
419 
420 	/* we are good to copy */
421 	return 0;
422 }
423 
424 /**
425  * Computes maximum number of bytes that can be copied from source buffer to
426  * sink buffer, verifying number of bytes available in source vs. free space
427  * available in sink.
428  * @param source Source buffer.
429  * @param sink Sink buffer.
430  * @return Number of bytes.
431  */
432 static inline uint32_t
audio_stream_get_copy_bytes(const struct audio_stream __sparse_cache * source,const struct audio_stream __sparse_cache * sink)433 audio_stream_get_copy_bytes(const struct audio_stream __sparse_cache *source,
434 			    const struct audio_stream __sparse_cache *sink)
435 {
436 	uint32_t avail = audio_stream_get_avail_bytes(source);
437 	uint32_t free = audio_stream_get_free_bytes(sink);
438 
439 	if (avail > free)
440 		return free;
441 	else
442 		return avail;
443 }
444 
445 /**
446  * Computes maximum number of frames that can be copied from source buffer
447  * to sink buffer, verifying number of available source frames vs. free
448  * space available in sink.
449  * @param source Source buffer.
450  * @param sink Sink buffer.
451  * @return Number of frames.
452  */
453 static inline uint32_t
audio_stream_avail_frames(const struct audio_stream __sparse_cache * source,const struct audio_stream __sparse_cache * sink)454 audio_stream_avail_frames(const struct audio_stream __sparse_cache *source,
455 			  const struct audio_stream __sparse_cache *sink)
456 {
457 	uint32_t src_frames = audio_stream_get_avail_frames(source);
458 	uint32_t sink_frames = audio_stream_get_free_frames(sink);
459 
460 	return MIN(src_frames, sink_frames);
461 }
462 
463 /**
464  * Computes maximum number of frames aligned that can be copied from
465  * source buffer to sink buffer, verifying number of available source
466  * frames vs. free space available in sink.
467  * @param source Buffer of source.
468  * @param sink Buffer of sink.
469  * @return Number of frames.
470  */
471 static inline uint32_t
audio_stream_avail_frames_aligned(const struct audio_stream __sparse_cache * source,const struct audio_stream __sparse_cache * sink)472 audio_stream_avail_frames_aligned(const struct audio_stream __sparse_cache *source,
473 				  const struct audio_stream __sparse_cache *sink)
474 {
475 	uint32_t src_frames = (audio_stream_get_avail_bytes(source) >> source->frame_align_shift)
476 		 * source->frame_align;
477 	uint32_t sink_frames = (audio_stream_get_free_bytes(sink) >> sink->frame_align_shift)
478 		 * sink->frame_align;
479 
480 	return MIN(src_frames, sink_frames);
481 }
482 
483 /**
484  * Updates the buffer state after writing to the buffer.
485  * @param buffer Buffer to update.
486  * @param bytes Number of written bytes.
487  */
audio_stream_produce(struct audio_stream __sparse_cache * buffer,uint32_t bytes)488 static inline void audio_stream_produce(struct audio_stream __sparse_cache *buffer,
489 					uint32_t bytes)
490 {
491 	buffer->w_ptr = audio_stream_wrap(buffer,
492 					  (char *)buffer->w_ptr + bytes);
493 
494 	/* "overwrite" old data in circular wrap case */
495 	if (bytes > audio_stream_get_free_bytes(buffer))
496 		buffer->r_ptr = buffer->w_ptr;
497 
498 	/* calculate available bytes */
499 	if (buffer->r_ptr < buffer->w_ptr)
500 		buffer->avail = (char *)buffer->w_ptr - (char *)buffer->r_ptr;
501 	else if (buffer->r_ptr == buffer->w_ptr)
502 		buffer->avail = buffer->size; /* full */
503 	else
504 		buffer->avail = buffer->size -
505 			((char *)buffer->r_ptr - (char *)buffer->w_ptr);
506 
507 	/* calculate free bytes */
508 	buffer->free = buffer->size - buffer->avail;
509 }
510 
511 /**
512  * Updates the buffer state after reading from the buffer.
513  * @param buffer Buffer to update.
514  * @param bytes Number of read bytes.
515  */
audio_stream_consume(struct audio_stream __sparse_cache * buffer,uint32_t bytes)516 static inline void audio_stream_consume(struct audio_stream __sparse_cache *buffer,
517 					uint32_t bytes)
518 {
519 	buffer->r_ptr = audio_stream_wrap(buffer,
520 					  (char *)buffer->r_ptr + bytes);
521 
522 	/* calculate available bytes */
523 	if (buffer->r_ptr < buffer->w_ptr)
524 		buffer->avail = (char *)buffer->w_ptr - (char *)buffer->r_ptr;
525 	else if (buffer->r_ptr == buffer->w_ptr)
526 		buffer->avail = 0; /* empty */
527 	else
528 		buffer->avail = buffer->size -
529 			((char *)buffer->r_ptr - (char *)buffer->w_ptr);
530 
531 	/* calculate free bytes */
532 	buffer->free = buffer->size - buffer->avail;
533 }
534 
535 /**
536  * Resets the buffer.
537  * @param buffer Buffer to reset.
538  */
audio_stream_reset(struct audio_stream __sparse_cache * buffer)539 static inline void audio_stream_reset(struct audio_stream __sparse_cache *buffer)
540 {
541 	/* reset read and write pointer to buffer bas */
542 	buffer->w_ptr = buffer->addr;
543 	buffer->r_ptr = buffer->addr;
544 
545 	/* free space is buffer size */
546 	buffer->free = buffer->size;
547 
548 	/* there are no avail samples at reset */
549 	buffer->avail = 0;
550 }
551 
552 /**
553  * Initializes the buffer with specified memory block and size.
554  * @param buffer Buffer to initialize.
555  * @param buff_addr Address of the memory block to assign.
556  * @param size Size of the memory block in bytes.
557  */
audio_stream_init(struct audio_stream __sparse_cache * buffer,void * buff_addr,uint32_t size)558 static inline void audio_stream_init(struct audio_stream __sparse_cache *buffer,
559 				     void *buff_addr, uint32_t size)
560 {
561 	buffer->size = size;
562 	buffer->addr = buff_addr;
563 	buffer->end_addr = (char *)buffer->addr + size;
564 	audio_stream_reset(buffer);
565 }
566 
567 /**
568  * Invalidates (in DSP d-cache) the buffer in range [r_ptr, r_ptr+bytes],
569  * with rollover if necessary.
570  * @param buffer Buffer.
571  * @param bytes Size of the fragment to invalidate.
572  */
audio_stream_invalidate(struct audio_stream __sparse_cache * buffer,uint32_t bytes)573 static inline void audio_stream_invalidate(struct audio_stream __sparse_cache *buffer,
574 					   uint32_t bytes)
575 {
576 	uint32_t head_size = bytes;
577 	uint32_t tail_size = 0;
578 
579 	/* check for potential wrap */
580 	if ((char *)buffer->r_ptr + bytes > (char *)buffer->end_addr) {
581 		head_size = (char *)buffer->end_addr - (char *)buffer->r_ptr;
582 		tail_size = bytes - head_size;
583 	}
584 
585 	dcache_invalidate_region((__sparse_force void __sparse_cache *)buffer->r_ptr, head_size);
586 	if (tail_size)
587 		dcache_invalidate_region((__sparse_force void __sparse_cache *)buffer->addr,
588 					 tail_size);
589 }
590 
591 /**
592  * Writes back (from DSP d-cache) the buffer in range [w_ptr, w_ptr+bytes],
593  * with rollover if necessary.
594  * @param buffer Buffer.
595  * @param bytes Size of the fragment to write back.
596  */
audio_stream_writeback(struct audio_stream __sparse_cache * buffer,uint32_t bytes)597 static inline void audio_stream_writeback(struct audio_stream __sparse_cache *buffer,
598 					  uint32_t bytes)
599 {
600 	uint32_t head_size = bytes;
601 	uint32_t tail_size = 0;
602 
603 	/* check for potential wrap */
604 	if ((char *)buffer->w_ptr + bytes > (char *)buffer->end_addr) {
605 		head_size = (char *)buffer->end_addr - (char *)buffer->w_ptr;
606 		tail_size = bytes - head_size;
607 	}
608 
609 	dcache_writeback_region((__sparse_force void __sparse_cache *)buffer->w_ptr, head_size);
610 	if (tail_size)
611 		dcache_writeback_region((__sparse_force void __sparse_cache *)buffer->addr,
612 					tail_size);
613 }
614 
615 /**
616  * @brief Calculates numbers of bytes to buffer wrap.
617  * @param source Stream to get information from.
618  * @param ptr Read or write pointer from source
619  * @return Number of data samples to buffer wrap.
620  */
621 static inline int
audio_stream_bytes_without_wrap(const struct audio_stream __sparse_cache * source,const void * ptr)622 audio_stream_bytes_without_wrap(const struct audio_stream __sparse_cache *source,
623 				const void *ptr)
624 {
625 	assert((intptr_t)source->end_addr >= (intptr_t)ptr);
626 	return (intptr_t)source->end_addr - (intptr_t)ptr;
627 }
628 
629 /**
630  * @brief Calculates numbers of bytes to buffer wrap when reading stream
631  *	  backwards from current sample pointed by ptr towards begin.
632  * @param source Stream to get information from.
633  * @param ptr Read or write pointer from source
634  * @return Number of bytes to buffer wrap. For number of samples calculate
635  *	   need to add size of sample to returned bytes count.
636  */
637 static inline int
audio_stream_rewind_bytes_without_wrap(const struct audio_stream __sparse_cache * source,const void * ptr)638 audio_stream_rewind_bytes_without_wrap(const struct audio_stream __sparse_cache *source,
639 				       const void *ptr)
640 {
641 	assert((intptr_t)ptr >= (intptr_t)source->addr);
642 	int to_begin = (intptr_t)ptr - (intptr_t)source->addr;
643 	return to_begin;
644 }
645 
646 /**
647  * @brief Calculates numbers of s16 samples to buffer wrap when buffer
648  * is read forward towards end address.
649  * @param source Stream to get information from.
650  * @param ptr Read or write pointer from source
651  * @return Number of data s16 samples until circular wrap need at end
652  */
653 static inline int
audio_stream_samples_without_wrap_s16(const struct audio_stream __sparse_cache * source,const void * ptr)654 audio_stream_samples_without_wrap_s16(const struct audio_stream __sparse_cache *source,
655 				      const void *ptr)
656 {
657 	int to_end = (int16_t *)source->end_addr - (int16_t *)ptr;
658 
659 	assert((intptr_t)source->end_addr >= (intptr_t)ptr);
660 	return to_end;
661 }
662 
663 /**
664  * @brief Calculates numbers of s24 samples to buffer wrap when buffer
665  * is read forward towards end address.
666  * @param source Stream to get information from.
667  * @param ptr Read or write pointer from source
668  * @return Number of data s24 samples until circular wrap need at end
669  */
670 static inline int
audio_stream_samples_without_wrap_s24(const struct audio_stream __sparse_cache * source,const void * ptr)671 audio_stream_samples_without_wrap_s24(const struct audio_stream __sparse_cache *source,
672 				      const void *ptr)
673 {
674 	int to_end = (int32_t *)source->end_addr - (int32_t *)ptr;
675 
676 	assert((intptr_t)source->end_addr >= (intptr_t)ptr);
677 	return to_end;
678 }
679 
680 /**
681  * @brief Calculates numbers of s32 samples to buffer wrap when buffer
682  * is read forward towards end address.
683  * @param source Stream to get information from.
684  * @param ptr Read or write pointer from source
685  * @return Number of data s32 samples until circular wrap need at end
686  */
687 static inline int
audio_stream_samples_without_wrap_s32(const struct audio_stream __sparse_cache * source,const void * ptr)688 audio_stream_samples_without_wrap_s32(const struct audio_stream __sparse_cache *source,
689 				      const void *ptr)
690 {
691 	int to_end = (int32_t *)source->end_addr - (int32_t *)ptr;
692 
693 	assert((intptr_t)source->end_addr >= (intptr_t)ptr);
694 	return to_end;
695 }
696 
697 /**
698  * @brief Calculates numbers of frames to buffer wrap and return
699  *	  minimum of calculated value.
700  * @param source Stream to get information from.
701  * @param ptr Read or write pointer from source
702  * @return Number of data frames to buffer wrap.
703  */
704 static inline uint32_t
audio_stream_frames_without_wrap(const struct audio_stream __sparse_cache * source,const void * ptr)705 audio_stream_frames_without_wrap(const struct audio_stream __sparse_cache *source,
706 				 const void *ptr)
707 {
708 	uint32_t bytes = audio_stream_bytes_without_wrap(source, ptr);
709 	uint32_t frame_bytes = audio_stream_frame_bytes(source);
710 
711 	return bytes / frame_bytes;
712 }
713 
714 /**
715  * Copies data from source buffer to sink buffer.
716  * @param source Source buffer.
717  * @param ioffset Offset (in samples) in source buffer to start reading from.
718  * @param sink Sink buffer.
719  * @param ooffset Offset (in samples) in sink buffer to start writing to.
720  * @param samples Number of samples to copy.
721  * @return number of processed samples.
722  */
723 int audio_stream_copy(const struct audio_stream __sparse_cache *source, uint32_t ioffset,
724 		      struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples);
725 
726 /**
727  * Copies data from linear source buffer to circular sink buffer.
728  * @param linear_source Source buffer.
729  * @param ioffset Offset (in samples) in source buffer to start reading from.
730  * @param sink Sink buffer.
731  * @param ooffset Offset (in samples) in sink buffer to start writing to.
732  * @param samples Number of samples to copy.
733  */
734 void audio_stream_copy_from_linear(const void *linear_source, int ioffset,
735 				   struct audio_stream __sparse_cache *sink, int ooffset,
736 				   unsigned int samples);
737 
738 /**
739  * Copies data from circular source buffer to linear sink buffer.
740  * @param source Source buffer.
741  * @param ioffset Offset (in samples) in source buffer to start reading from.
742  * @param linear_sink Sink buffer.
743  * @param ooffset Offset (in samples) in sink buffer to start writing to.
744  * @param samples Number of samples to copy.
745  */
746 void audio_stream_copy_to_linear(const struct audio_stream __sparse_cache *source, int ioffset,
747 				 void *linear_sink, int ooffset, unsigned int samples);
748 
749 /**
750  * Writes zeros in range [w_ptr, w_ptr+bytes], with rollover if necessary.
751  * @param buffer Buffer.
752  * @param bytes Size of the fragment to write zero.
753  * @return 0 if there is enough free space in buffer.
754  * @return 1 if there is not enough free space in buffer.
755  */
audio_stream_set_zero(struct audio_stream __sparse_cache * buffer,uint32_t bytes)756 static inline int audio_stream_set_zero(struct audio_stream __sparse_cache *buffer,
757 					uint32_t bytes)
758 {
759 	uint32_t head_size = bytes;
760 	uint32_t tail_size = 0;
761 
762 	/* check for overrun */
763 	if (audio_stream_get_free_bytes(buffer) < bytes)
764 		return 1;
765 
766 	/* check for potential wrap */
767 	if ((char *)buffer->w_ptr + bytes > (char *)buffer->end_addr) {
768 		head_size = (char *)buffer->end_addr - (char *)buffer->w_ptr;
769 		tail_size = bytes - head_size;
770 	}
771 
772 	memset(buffer->w_ptr, 0, head_size);
773 	if (tail_size)
774 		memset(buffer->addr, 0, tail_size);
775 
776 	return 0;
777 }
778 
audio_stream_fmt_conversion(enum ipc4_bit_depth depth,enum ipc4_bit_depth valid,enum sof_ipc_frame __sparse_cache * frame_fmt,enum sof_ipc_frame __sparse_cache * valid_fmt,enum ipc4_sample_type type)779 static inline void audio_stream_fmt_conversion(enum ipc4_bit_depth depth,
780 					       enum ipc4_bit_depth valid,
781 					       enum sof_ipc_frame __sparse_cache *frame_fmt,
782 					       enum sof_ipc_frame __sparse_cache *valid_fmt,
783 					       enum ipc4_sample_type type)
784 {
785 	/* IPC4_DEPTH_16BIT (16) <---> SOF_IPC_FRAME_S16_LE (0)
786 	 * IPC4_DEPTH_24BIT (24) <---> SOF_IPC_FRAME_S24_4LE (1)
787 	 * IPC4_DEPTH_32BIT (32) <---> SOF_IPC_FRAME_S32_LE (2)
788 	 */
789 	*frame_fmt = (depth >> 3) - 2;
790 	*valid_fmt = (valid >> 3) - 2;
791 
792 	/* really 24_3LE */
793 	if (valid == 24 && depth == 24) {
794 		*frame_fmt = SOF_IPC_FRAME_S24_3LE;
795 		*valid_fmt = SOF_IPC_FRAME_S24_3LE;
796 	}
797 
798 	if (type == IPC4_TYPE_FLOAT && depth == 32) {
799 		*frame_fmt = SOF_IPC_FRAME_FLOAT;
800 		*valid_fmt = SOF_IPC_FRAME_FLOAT;
801 	}
802 }
803 /** @}*/
804 
805 #endif /* __SOF_AUDIO_AUDIO_STREAM_H__ */
806