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