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