1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2019 Intel Corporation. All rights reserved.
4  *
5  * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com>
6  */
7 
8 /**
9  * \file audio/pcm_converter.h
10  * \brief PCM converter header file
11  * \authors Tomasz Lauda <tomasz.lauda@linux.intel.com>
12  */
13 
14 #ifndef __SOF_AUDIO_PCM_CONVERTER_H__
15 #define __SOF_AUDIO_PCM_CONVERTER_H__
16 
17 #include <ipc/stream.h>
18 #include <ipc4/gateway.h>
19 
20 #include <sof/compiler_attributes.h>
21 
22 #include <stddef.h>
23 #include <stdint.h>
24 
25 struct audio_stream;
26 
27 #if __XCC__
28 #include <xtensa/config/core-isa.h>
29 #endif
30 
31 #ifndef UNIT_TEST
32 #if __XCC__ && XCHAL_HAVE_HIFI3 && CONFIG_FORMAT_CONVERT_HIFI3
33 #define PCM_CONVERTER_HIFI3
34 #else
35 #define PCM_CONVERTER_GENERIC
36 #endif
37 #endif /* UNIT_TEST */
38 
39 /**
40  * \brief PCM conversion function interface for data in circular buffer
41  * \param source buffer with samples to process, read pointer is not modified
42  * \param ioffset offset to first sample in source stream
43  * \param sink output buffer, write pointer is not modified
44  * \param ooffset offset to first sample in sink stream
45  * \param samples number of samples to convert
46  * \return error code or number of processed samples.
47  */
48 typedef int (*pcm_converter_func)(const struct audio_stream __sparse_cache *source,
49 				  uint32_t ioffset, struct audio_stream __sparse_cache *sink,
50 				  uint32_t ooffset, uint32_t samples);
51 
52 /**
53  * \brief PCM conversion function interface for data in linear buffer
54  * \param psrc linear memory region with samples to process
55  * \param pdst linear memory region for output
56  * \param samples number of samples to convert
57  */
58 typedef void (*pcm_converter_lin_func)(const void *psrc, void *pdst,
59 				       uint32_t samples);
60 
61 /** \brief PCM conversion functions map. */
62 struct pcm_func_map {
63 	enum sof_ipc_frame source;	/**< source frame format */
64 	enum sof_ipc_frame sink;	/**< sink frame format */
65 	pcm_converter_func func; /**< PCM conversion function */
66 };
67 
68 /** \brief Map of formats with dedicated conversion functions. */
69 extern const struct pcm_func_map pcm_func_map[];
70 
71 /** \brief Number of conversion functions. */
72 extern const size_t pcm_func_count;
73 
74 /**
75  * \brief Retrieves PCM conversion function.
76  * \param[in] in Source frame format.
77  * \param[in] out Sink frame format.
78  */
79 static inline pcm_converter_func
pcm_get_conversion_function(enum sof_ipc_frame in,enum sof_ipc_frame out)80 pcm_get_conversion_function(enum sof_ipc_frame in,
81 			    enum sof_ipc_frame out)
82 {
83 	uint32_t i;
84 
85 	for (i = 0; i < pcm_func_count; i++) {
86 		if (in != pcm_func_map[i].source)
87 			continue;
88 		if (out != pcm_func_map[i].sink)
89 			continue;
90 
91 		return pcm_func_map[i].func;
92 	}
93 
94 	return NULL;
95 }
96 
97 /** \brief PCM conversion functions mapfor different size of valid bit and container. */
98 struct pcm_func_vc_map {
99 	enum sof_ipc_frame source;	/**< source frame container format */
100 	enum sof_ipc_frame valid_src_bits;	/**< source frame format */
101 	enum sof_ipc_frame sink;	/**< sink frame container format */
102 	enum sof_ipc_frame valid_sink_bits;	/**< sink frame format */
103 	uint32_t type;	/**< gateway type */
104 	enum ipc4_direction_type direction;	/**< support playback, capture or both */
105 	pcm_converter_func func; /**< PCM conversion function */
106 };
107 
108 /** \brief Map of formats with dedicated conversion functions. */
109 extern const struct pcm_func_vc_map pcm_func_vc_map[];
110 
111 /** \brief Number of conversion functions. */
112 extern const size_t pcm_func_vc_count;
113 
114 /**
115  * \brief Retrieves PCM conversion function for different container size.
116  * \param in_bits is source container format.
117  * \param valid_in_bits is source valid sample format.
118  * \param out_bits is sink container format.
119  * \param valid_out_bits is sink valid sample format.
120  * \param type is gateway type
121  * \param dir is playback or capture
122  */
123 static inline pcm_converter_func
pcm_get_conversion_vc_function(enum sof_ipc_frame in_bits,enum sof_ipc_frame valid_in_bits,enum sof_ipc_frame out_bits,enum sof_ipc_frame valid_out_bits,enum ipc4_gateway_type type,enum ipc4_direction_type dir)124 pcm_get_conversion_vc_function(enum sof_ipc_frame in_bits,
125 			       enum sof_ipc_frame valid_in_bits,
126 			       enum sof_ipc_frame out_bits,
127 			       enum sof_ipc_frame valid_out_bits,
128 			       enum ipc4_gateway_type type,
129 			       enum ipc4_direction_type dir)
130 {
131 	uint32_t i;
132 
133 	for (i = 0; i < pcm_func_vc_count; i++) {
134 		if (in_bits != pcm_func_vc_map[i].source)
135 			continue;
136 		if (valid_in_bits != pcm_func_vc_map[i].valid_src_bits)
137 			continue;
138 		if (out_bits != pcm_func_vc_map[i].sink)
139 			continue;
140 		if (valid_out_bits != pcm_func_vc_map[i].valid_sink_bits)
141 			continue;
142 
143 		if (!(type & pcm_func_vc_map[i].type))
144 			continue;
145 
146 		if (!(dir & pcm_func_vc_map[i].direction))
147 			continue;
148 
149 		return pcm_func_vc_map[i].func;
150 	}
151 
152 	return NULL;
153 }
154 
155 /**
156  * \brief Convert data from circular buffer using converter working on linear
157  *	  memory space
158  * \param source buffer with samples to process, read pointer is not modified
159  * \param ioffset offset to first sample in source stream
160  * \param sink output buffer, write pointer is not modified
161  * \param ooffset offset to first sample in sink stream
162  * \param samples number of samples to convert
163  * \param converter core conversion function working on linear memory regions
164  * \return error code or number of processed samples
165  */
166 int pcm_convert_as_linear(const struct audio_stream __sparse_cache *source, uint32_t ioffset,
167 			  struct audio_stream __sparse_cache *sink, uint32_t ooffset,
168 			  uint32_t samples, pcm_converter_lin_func converter);
169 
170 #endif /* __SOF_AUDIO_PCM_CONVERTER_H__ */
171