1 /* SPDX-License-Identifier: BSD-3-Clause
2 *
3 * Copyright(c) 2020 Intel Corporation. All rights reserved.
4 *
5 *
6 * \file generic.h
7 * \brief Generic Module API header file
8 * \author Marcin Rajwa <marcin.rajwa@linux.intel.com>
9 *
10 */
11
12 #ifndef __SOF_AUDIO_MODULE_GENERIC__
13 #define __SOF_AUDIO_MODULE_GENERIC__
14
15 #include <sof/audio/component.h>
16 #include <sof/ut.h>
17 #include <sof/lib/memory.h>
18 #include "module_interface.h"
19
20 #if CONFIG_INTEL_MODULES
21 #include "iadk_modules.h"
22 #endif
23
24 #define module_get_private_data(mod) (mod->priv.private)
25 #define MAX_BLOB_SIZE 8192
26 #define MODULE_MAX_SOURCES 8
27
28 #define API_CALL(cd, cmd, sub_cmd, value, ret) \
29 do { \
30 ret = (cd)->api((cd)->self, \
31 (cmd), \
32 (sub_cmd), \
33 (value)); \
34 } while (0)
35
36 #define DECLARE_MODULE_ADAPTER(adapter, uuid, tr) \
37 static struct comp_dev *module_##adapter##_shim_new(const struct comp_driver *drv, \
38 const struct comp_ipc_config *config, \
39 const void *spec) \
40 { \
41 return module_adapter_new(drv, config, &(adapter), spec);\
42 } \
43 \
44 static const struct comp_driver comp_##adapter##_module = { \
45 .type = SOF_COMP_MODULE_ADAPTER, \
46 .uid = SOF_RT_UUID(uuid), \
47 .tctx = &(tr), \
48 .ops = { \
49 .create = module_##adapter##_shim_new, \
50 .prepare = module_adapter_prepare, \
51 .params = module_adapter_params, \
52 .copy = module_adapter_copy, \
53 .cmd = module_adapter_cmd, \
54 .trigger = module_adapter_trigger, \
55 .reset = module_adapter_reset, \
56 .free = module_adapter_free, \
57 .set_large_config = module_set_large_config,\
58 .get_large_config = module_get_large_config,\
59 .get_attribute = module_adapter_get_attribute,\
60 .bind = module_adapter_bind,\
61 .unbind = module_adapter_unbind,\
62 }, \
63 }; \
64 \
65 static SHARED_DATA struct comp_driver_info comp_module_##adapter##_info = { \
66 .drv = &comp_##adapter##_module, \
67 }; \
68 \
69 UT_STATIC void sys_comp_module_##adapter##_init(void) \
70 { \
71 comp_register(platform_shared_get(&comp_module_##adapter##_info, \
72 sizeof(comp_module_##adapter##_info))); \
73 } \
74 \
75 DECLARE_MODULE(sys_comp_module_##adapter##_init)
76
77 /**
78 * \enum module_state
79 * \brief Module-specific states
80 */
81 enum module_state {
82 MODULE_DISABLED, /**< Module isn't initialized yet or has been freed.*/
83 MODULE_INITIALIZED, /**< Module initialized or reset. */
84 MODULE_IDLE, /**< Module is idle now. */
85 MODULE_PROCESSING, /**< Module is processing samples now. */
86 };
87
88 /**
89 * \struct module_param
90 * \brief Module TLV parameters container - used for both config types.
91 * For example if one want to set the sample_rate to 16 [kHz] and this
92 * parameter was assigned to id 0x01, its max size is four bytes then the
93 * configuration filed should look like this (note little-endian format):
94 * 0x01 0x00 0x00 0x00, 0x0C 0x00 0x00 0x00, 0x10 0x00 0x00 0x00.
95 */
96 struct module_param {
97 /**
98 * Specifies the unique id of a parameter. For example the parameter
99 * sample_rate may have an id of 0x01.
100 */
101 uint32_t id;
102 uint32_t size; /**< The size of whole parameter - id + size + data */
103 int32_t data[]; /**< A pointer to memory where config is stored.*/
104 };
105
106 /**
107 * \struct module_config
108 * \brief Module config container, used for both config types.
109 */
110 struct module_config {
111 size_t size; /**< Specifies the size of whole config */
112 bool avail; /**< Marks config as available to use.*/
113 void *data; /**< tlv config, a pointer to memory where config is stored. */
114 const void *init_data; /**< Initial IPC configuration. */
115 #if CONFIG_IPC_MAJOR_4
116 struct ipc4_base_module_cfg base_cfg;
117 #endif
118 };
119
120 /**
121 * \struct module_memory
122 * \brief module memory block - used for every memory allocated by module
123 */
124 struct module_memory {
125 void *ptr; /**< A pointr to particular memory block */
126 struct list_item mem_list; /**< list of memory allocated by module */
127 };
128
129 /**
130 * \struct module_processing_data
131 * \brief Processing data shared between particular module & module_adapter
132 */
133 struct module_processing_data {
134 uint32_t in_buff_size; /**< Specifies the size of module input buffer. */
135 uint32_t out_buff_size; /**< Specifies the size of module output buffer.*/
136 uint32_t avail; /**< Specifies how much data is available for module to process.*/
137 uint32_t produced; /**< Specifies how much data the module produced in its last task.*/
138 uint32_t consumed; /**< Specified how much data the module consumed in its last task */
139 uint32_t init_done; /**< Specifies if the module initialization is finished */
140 void *in_buff; /**< A pointer to module input buffer. */
141 void *out_buff; /**< A pointer to module output buffer. */
142 };
143
144 /** private, runtime module data */
145 struct module_data {
146 enum module_state state;
147 size_t new_cfg_size; /**< size of new module config data */
148 void *private; /**< self object, memory tables etc here */
149 void *runtime_params;
150 struct module_config cfg; /**< module configuration data */
151 struct module_interface *ops; /**< module specific operations */
152 struct module_memory memory; /**< memory allocated by module */
153 struct module_processing_data mpd; /**< shared data comp <-> module */
154 void *module_adapter; /**<loadable module interface handle */
155 uint32_t module_entry_point; /**<loadable module entry point address */
156 };
157
158 /*
159 * Used by the module to keep track of the number of sources bound to it and can be accessed
160 * from different cores
161 */
162 struct module_source_info {
163 struct coherent c;
164 struct comp_dev *sources[MODULE_MAX_SOURCES];
165 void *private; /**< additional module-specific private info */
166 };
167
168 /* module_adapter private, runtime data */
169 struct processing_module {
170 struct module_data priv; /**< module private data */
171 struct sof_ipc_stream_params *stream_params;
172 struct list_item sink_buffer_list; /* list of sink buffers to save produced output */
173
174 /*
175 * This is a temporary change in order to support the trace messages in the modules. This
176 * will be removed once the trace API is updated.
177 */
178 struct comp_dev *dev;
179 uint32_t period_bytes; /** pipeline period bytes */
180 uint32_t deep_buff_bytes; /**< copy start threshold */
181 uint32_t output_buffer_size; /**< size of local buffer to save produced samples */
182 struct input_stream_buffer *input_buffers;
183 struct output_stream_buffer *output_buffers;
184 uint32_t num_input_buffers; /**< number of input buffers */
185 uint32_t num_output_buffers; /**< number of output buffers */
186 /*
187 * flag set by a module that produces period_bytes every copy. It can be used by modules
188 * that support 1:1, 1:N, N:1 sources:sinks configuration.
189 */
190 bool simple_copy;
191
192 /* module-specific flags for comp_verify_params() */
193 uint32_t verify_params_flags;
194
195 /* flag to indicate module does not pause */
196 bool no_pause;
197
198 /*
199 * flag to indicate that the sink buffer writeback should be skipped. It will be handled
200 * in the module's process callback
201 */
202 bool skip_sink_buffer_writeback;
203
204 /*
205 * flag to indicate that the source buffer invalidate should be skipped. It will be handled
206 * in the module's process callback
207 */
208 bool skip_src_buffer_invalidate;
209
210 /* table containing the list of connected sources */
211 struct module_source_info *source_info;
212 };
213
214 /*****************************************************************************/
215 /* Module generic interfaces */
216 /*****************************************************************************/
217 int module_load_config(struct comp_dev *dev, const void *cfg, size_t size);
218 int module_init(struct processing_module *mod, struct module_interface *interface);
219 void *module_allocate_memory(struct processing_module *mod, uint32_t size, uint32_t alignment);
220 int module_free_memory(struct processing_module *mod, void *ptr);
221 void module_free_all_memory(struct processing_module *mod);
222 int module_prepare(struct processing_module *mod);
223 int module_process(struct processing_module *mod, struct input_stream_buffer *input_buffers,
224 int num_input_buffers, struct output_stream_buffer *output_buffers,
225 int num_output_buffers);
226 int module_reset(struct processing_module *mod);
227 int module_free(struct processing_module *mod);
228 int module_set_configuration(struct processing_module *mod,
229 uint32_t config_id,
230 enum module_cfg_fragment_position pos, size_t data_offset_size,
231 const uint8_t *fragment, size_t fragment_size, uint8_t *response,
232 size_t response_size);
233
234 struct comp_dev *module_adapter_new(const struct comp_driver *drv,
235 const struct comp_ipc_config *config,
236 struct module_interface *interface, const void *spec);
237 int module_adapter_prepare(struct comp_dev *dev);
238 int module_adapter_params(struct comp_dev *dev, struct sof_ipc_stream_params *params);
239 int module_adapter_copy(struct comp_dev *dev);
240 int module_adapter_cmd(struct comp_dev *dev, int cmd, void *data, int max_data_size);
241 int module_adapter_trigger(struct comp_dev *dev, int cmd);
242 void module_adapter_free(struct comp_dev *dev);
243 int module_adapter_reset(struct comp_dev *dev);
244 int module_set_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block,
245 bool last_block, uint32_t data_offset, const char *data);
246 int module_get_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block,
247 bool last_block, uint32_t *data_offset, char *data);
248 int module_adapter_get_attribute(struct comp_dev *dev, uint32_t type, void *value);
249 int module_adapter_bind(struct comp_dev *dev, void *data);
250 int module_adapter_unbind(struct comp_dev *dev, void *data);
251
module_update_buffer_position(struct input_stream_buffer * input_buffers,struct output_stream_buffer * output_buffers,uint32_t frames)252 static inline void module_update_buffer_position(struct input_stream_buffer *input_buffers,
253 struct output_stream_buffer *output_buffers,
254 uint32_t frames)
255 {
256 struct audio_stream __sparse_cache *source = input_buffers->data;
257 struct audio_stream __sparse_cache *sink = output_buffers->data;
258
259 input_buffers->consumed += audio_stream_frame_bytes(source) * frames;
260 output_buffers->size += audio_stream_frame_bytes(sink) * frames;
261 }
262
263 __must_check static inline
module_source_info_acquire(struct module_source_info * msi)264 struct module_source_info __sparse_cache *module_source_info_acquire(struct module_source_info *msi)
265 {
266 struct coherent __sparse_cache *c;
267
268 c = coherent_acquire_thread(&msi->c, sizeof(*msi));
269
270 return attr_container_of(c, struct module_source_info __sparse_cache, c, __sparse_cache);
271 }
272
module_source_info_release(struct module_source_info __sparse_cache * msi)273 static inline void module_source_info_release(struct module_source_info __sparse_cache *msi)
274 {
275 coherent_release_thread(&msi->c, sizeof(*msi));
276 }
277
278 /* when source argument is NULL, this function returns the first unused entry */
279 static inline
find_module_source_index(struct module_source_info __sparse_cache * msi,const struct comp_dev * source)280 int find_module_source_index(struct module_source_info __sparse_cache *msi,
281 const struct comp_dev *source)
282 {
283 int i;
284
285 for (i = 0; i < MODULE_MAX_SOURCES; i++) {
286 if (msi->sources[i] == source)
287 return i;
288 }
289
290 return -EINVAL;
291 }
292
293 #endif /* __SOF_AUDIO_MODULE_GENERIC__ */
294