forked from thesofproject/sof
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgeneric.h
More file actions
410 lines (365 loc) · 14.4 KB
/
generic.h
File metadata and controls
410 lines (365 loc) · 14.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
/* SPDX-License-Identifier: BSD-3-Clause */
/*
* Copyright(c) 2020 - 2023 Intel Corporation. All rights reserved.
*
*
* \file generic.h
* \brief Generic Module API header file
* \author Marcin Rajwa <marcin.rajwa@linux.intel.com>
* \author Adrian Warecki <adrian.warecki@intel.com>
*
*/
#ifndef __SOF_AUDIO_MODULE_GENERIC__
#define __SOF_AUDIO_MODULE_GENERIC__
#include <sof/audio/component.h>
#include <sof/ut.h>
#include <sof/audio/sink_api.h>
#include <sof/audio/source_api.h>
#include "module_interface.h"
/* The __ZEPHYR__ condition is to keep cmocka tests working */
#if CONFIG_MODULE_MEMORY_API_DEBUG && defined(__ZEPHYR__)
#include <zephyr/kernel/thread.h>
#endif
/*
* helpers to determine processing type
* Needed till all the modules use PROCESSING_MODE_SINK_SOURCE
*/
#define IS_PROCESSING_MODE_AUDIO_STREAM(mod) ((mod)->proc_type == MODULE_PROCESS_TYPE_STREAM)
#define IS_PROCESSING_MODE_RAW_DATA(mod) ((mod)->proc_type == MODULE_PROCESS_TYPE_RAW)
#define IS_PROCESSING_MODE_SINK_SOURCE(mod) ((mod)->proc_type == MODULE_PROCESS_TYPE_SOURCE_SINK)
#if CONFIG_IPC_MAJOR_4
#define IPC_MOD_CMD(v)
#elif CONFIG_IPC_MAJOR_3
#define IPC_MOD_CMD(v) .cmd = v,
#endif
/*
* \brief Macro to declare a module adapter component.
* \param adapter - name of the module.
* \param uuid - UUID of the module.
* \param tr - trace context for the module.
*
* This macro declares a module component with the specified name, UUID, and trace context.
* It initializes the component module structure with the appropriate type, UID, and
* struct module_interface operations.
*/
#define DECLARE_MODULE_ADAPTER(adapter, uuid, tr) \
static const struct comp_driver comp_##adapter##_module = { \
.type = SOF_COMP_MODULE_ADAPTER, \
.uid = SOF_RT_UUID(uuid), \
.tctx = &(tr), \
.ops = { \
.create = module_adapter_new, \
.prepare = module_adapter_prepare, \
.params = module_adapter_params, \
.copy = module_adapter_copy, \
IPC_MOD_CMD(module_adapter_cmd) \
.trigger = module_adapter_trigger, \
.reset = module_adapter_reset, \
.free = module_adapter_free, \
.set_large_config = module_set_large_config,\
.get_large_config = module_get_large_config,\
.get_attribute = module_adapter_get_attribute,\
.set_attribute = module_adapter_set_attribute,\
.bind = module_adapter_bind,\
.unbind = module_adapter_unbind,\
.get_total_data_processed = module_adapter_get_total_data_processed,\
.dai_get_hw_params = module_adapter_get_hw_params,\
.position = module_adapter_position,\
.dai_ts_config = module_adapter_ts_config_op,\
.dai_ts_start = module_adapter_ts_start_op,\
.dai_ts_stop = module_adapter_ts_stop_op,\
.dai_ts_get = module_adapter_ts_get_op,\
}, \
.adapter_ops = &(adapter), \
}; \
\
static SHARED_DATA struct comp_driver_info comp_module_##adapter##_info = { \
.drv = &comp_##adapter##_module, \
}; \
\
UT_STATIC void sys_comp_module_##adapter##_init(void) \
{ \
comp_register(platform_shared_get(&comp_module_##adapter##_info, \
sizeof(comp_module_##adapter##_info))); \
} \
\
DECLARE_MODULE(sys_comp_module_##adapter##_init)
/**
* \enum module_state
* \brief Module-specific states
*/
enum module_state {
MODULE_DISABLED, /**< Module isn't initialized yet or has been freed.*/
MODULE_INITIALIZED, /**< Module initialized or reset. */
MODULE_IDLE, /**< Module is idle now. */
MODULE_PROCESSING, /**< Module is processing samples now. */
};
/**
* \struct module_param
* \brief Module TLV parameters container - used for both config types.
* For example if one want to set the sample_rate to 16 [kHz] and this
* parameter was assigned to id 0x01, its max size is four bytes then the
* configuration filed should look like this (note little-endian format):
* 0x01 0x00 0x00 0x00, 0x0C 0x00 0x00 0x00, 0x10 0x00 0x00 0x00.
*/
struct module_param {
/**
* Specifies the unique id of a parameter. For example the parameter
* sample_rate may have an id of 0x01.
*/
uint32_t id;
uint32_t size; /**< The size of whole parameter - id + size + data */
int32_t data[]; /**< A pointer to memory where config is stored.*/
};
/**
* \struct module_resources
* \brief module resources block - used for module allocation records
* The allocations are recorded so that they can be automatically freed
* when the module unloads.
*/
struct module_resources {
struct list_item res_list; /**< Allocad resource containers */
struct list_item free_cont_list; /**< Unused memory containers */
struct list_item cont_chunk_list; /**< Memory container chunks */
size_t heap_usage;
size_t heap_high_water_mark;
#if CONFIG_MODULE_MEMORY_API_DEBUG && defined(__ZEPHYR__)
k_tid_t rsrc_mngr;
#endif
};
enum mod_resource_type {
MOD_RES_UNINITIALIZED = 0,
MOD_RES_HEAP,
MOD_RES_BLOB_HANDLER,
MOD_RES_FAST_GET,
};
/**
* \struct module_resource
* \brief module memory container - used for every memory allocated by module
*/
struct module_resource {
union {
void *ptr; /**< Pointer to heap allocated memory */
struct comp_data_blob_handler *bhp; /**< Blob handler ptr */
const void *sram_ptr; /**< SRAM ptr from fast_get() */
};
struct list_item list; /**< list element */
size_t size; /**< Size of allocated heap memory, 0 if not from heap */
enum mod_resource_type type; /**< Resource type */
};
/**
* \struct module_processing_data
* \brief Processing data shared between particular module & module_adapter
*/
struct module_processing_data {
uint32_t in_buff_size; /**< Specifies the size of module input buffer. */
uint32_t out_buff_size; /**< Specifies the size of module output buffer.*/
uint32_t avail; /**< Specifies how much data is available for module to process.*/
uint32_t produced; /**< Specifies how much data the module produced in its last task.*/
uint32_t consumed; /**< Specified how much data the module consumed in its last task */
uint32_t init_done; /**< Specifies if the module initialization is finished */
void *in_buff; /**< A pointer to module input buffer. */
void *out_buff; /**< A pointer to module output buffer. */
};
/*
* Definition used to extend structure definitions to include fields for exclusive use by SOF.
* This is a temporary solution used until work on separating a common interface for loadable
* modules is completed.
*/
#define SOF_MODULE_API_PRIVATE
#include <module/module/base.h>
/*****************************************************************************/
/* Module generic interfaces */
/*****************************************************************************/
int module_load_config(struct comp_dev *dev, const void *cfg, size_t size);
int module_init(struct processing_module *mod);
void *mod_balloc_align(struct processing_module *mod, size_t size, size_t alignment);
static inline void *mod_balloc(struct processing_module *mod, size_t size)
{
return mod_balloc_align(mod, size, 0);
}
void *mod_alloc_align(struct processing_module *mod, size_t size, size_t alignment);
static inline void *mod_alloc(struct processing_module *mod, size_t size)
{
return mod_alloc_align(mod, size, 0);
}
static inline void *mod_zalloc(struct processing_module *mod, size_t size)
{
void *ret = mod_alloc(mod, size);
if (ret)
memset(ret, 0, size);
return ret;
}
int mod_free(struct processing_module *mod, const void *ptr);
#if CONFIG_COMP_BLOB
struct comp_data_blob_handler *mod_data_blob_handler_new(struct processing_module *mod);
void mod_data_blob_handler_free(struct processing_module *mod, struct comp_data_blob_handler *dbh);
#endif
#if CONFIG_FAST_GET
const void *mod_fast_get(struct processing_module *mod, const void * const dram_ptr, size_t size);
void mod_fast_put(struct processing_module *mod, const void *sram_ptr);
#endif
void mod_free_all(struct processing_module *mod);
int module_prepare(struct processing_module *mod,
struct sof_source **sources, int num_of_sources,
struct sof_sink **sinks, int num_of_sinks);
static inline
bool generic_module_is_ready_to_process(struct processing_module *mod,
struct sof_source **sources,
int num_of_sources,
struct sof_sink **sinks,
int num_of_sinks)
{
int i;
for (i = 0; i < num_of_sources; i++)
if (source_get_data_available(sources[i]) < source_get_min_available(sources[i]))
return false;
for (i = 0; i < num_of_sinks; i++)
if (sink_get_free_size(sinks[i]) < sink_get_min_free_space(sinks[i]))
return false;
return true;
}
static inline
bool module_is_ready_to_process(struct processing_module *mod,
struct sof_source **sources,
int num_of_sources,
struct sof_sink **sinks,
int num_of_sinks)
{
const struct module_interface *const ops = mod->dev->drv->adapter_ops;
/* LL module has to be always ready for processing */
if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_LL)
return true;
if (ops->is_ready_to_process)
return ops->is_ready_to_process(mod, sources, num_of_sources, sinks, num_of_sinks);
/* default action - the module is ready if there's enough data for processing and enough
* space to store result. IBS/OBS as declared in init_instance
*/
return generic_module_is_ready_to_process(mod, sources, num_of_sources, sinks,
num_of_sinks);
}
int module_process_sink_src(struct processing_module *mod,
struct sof_source **sources, int num_of_sources,
struct sof_sink **sinks, int num_of_sinks);
int module_process_legacy(struct processing_module *mod,
struct input_stream_buffer *input_buffers, int num_input_buffers,
struct output_stream_buffer *output_buffers,
int num_output_buffers);
int module_reset(struct processing_module *mod);
int module_free(struct processing_module *mod);
int module_set_configuration(struct processing_module *mod,
uint32_t config_id,
enum module_cfg_fragment_position pos, size_t data_offset_size,
const uint8_t *fragment, size_t fragment_size, uint8_t *response,
size_t response_size);
int module_bind(struct processing_module *mod, struct bind_info *bind_data);
int module_unbind(struct processing_module *mod, struct bind_info *unbind_data);
struct comp_dev *module_adapter_new(const struct comp_driver *drv,
const struct comp_ipc_config *config, const void *spec);
struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv,
const struct comp_ipc_config *config, const void *spec,
void *mod_priv);
int module_adapter_prepare(struct comp_dev *dev);
int module_adapter_params(struct comp_dev *dev, struct sof_ipc_stream_params *params);
int module_adapter_copy(struct comp_dev *dev);
int module_adapter_cmd(struct comp_dev *dev, int cmd, void *data, int max_data_size);
int module_adapter_trigger(struct comp_dev *dev, int cmd);
void module_adapter_free(struct comp_dev *dev);
int module_adapter_reset(struct comp_dev *dev);
size_t module_adapter_heap_usage(struct processing_module *mod, size_t *hwm);
#if CONFIG_IPC_MAJOR_3
static inline
int module_adapter_get_attribute(struct comp_dev *dev, uint32_t type, void *value)
{
return -EINVAL;
}
static inline
int module_adapter_set_attribute(struct comp_dev *dev, uint32_t type, void *value)
{
return -EINVAL;
}
static inline
int module_set_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block,
bool last_block, uint32_t data_offset, const char *data)
{
return 0;
}
static inline
int module_get_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block,
bool last_block, uint32_t *data_offset, char *data)
{
return 0;
}
static inline
int module_adapter_bind(struct comp_dev *dev, struct bind_info *bind_data)
{
return 0;
}
static inline
int module_adapter_unbind(struct comp_dev *dev, struct bind_info *unbind_data)
{
return 0;
}
static inline
uint64_t module_adapter_get_total_data_processed(struct comp_dev *dev,
uint32_t stream_no, bool input)
{
return 0;
}
static inline int module_process_endpoint(struct processing_module *mod,
struct input_stream_buffer *input_buffers,
int num_input_buffers,
struct output_stream_buffer *output_buffers,
int num_output_buffers)
{
return module_process_legacy(mod, input_buffers, num_input_buffers,
output_buffers, num_output_buffers);
}
#else
int module_set_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block,
bool last_block, uint32_t data_offset, const char *data);
int module_get_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block,
bool last_block, uint32_t *data_offset, char *data);
int module_adapter_get_attribute(struct comp_dev *dev, uint32_t type, void *value);
int module_adapter_set_attribute(struct comp_dev *dev, uint32_t type, void *value);
int module_adapter_bind(struct comp_dev *dev, struct bind_info *bind_data);
int module_adapter_unbind(struct comp_dev *dev, struct bind_info *unbind_data);
uint64_t module_adapter_get_total_data_processed(struct comp_dev *dev,
uint32_t stream_no, bool input);
static inline int module_process_endpoint(struct processing_module *mod,
struct input_stream_buffer *input_buffers,
int num_input_buffers,
struct output_stream_buffer *output_buffers,
int num_output_buffers)
{
const struct module_interface *const ops = mod->dev->drv->adapter_ops;
return ops->process_audio_stream(mod, input_buffers, num_input_buffers,
output_buffers, num_output_buffers);
}
#endif
int module_adapter_get_hw_params(struct comp_dev *dev, struct sof_ipc_stream_params *params,
int dir);
int module_adapter_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn);
int module_adapter_ts_config_op(struct comp_dev *dev);
int module_adapter_ts_start_op(struct comp_dev *dev);
int module_adapter_ts_stop_op(struct comp_dev *dev);
#if CONFIG_ZEPHYR_NATIVE_DRIVERS
int module_adapter_ts_get_op(struct comp_dev *dev, struct dai_ts_data *tsd);
#else
int module_adapter_ts_get_op(struct comp_dev *dev, struct timestamp_data *tsd);
#endif
void module_update_buffer_position(struct input_stream_buffer *input_buffers,
struct output_stream_buffer *output_buffers,
uint32_t frames);
int module_adapter_init_data(struct comp_dev *dev,
struct module_config *dst,
const struct comp_ipc_config *config,
const void *spec);
void module_adapter_reset_data(struct module_config *dst);
void module_adapter_check_data(struct processing_module *mod, struct comp_dev *dev,
struct comp_buffer *sink);
void module_adapter_set_params(struct processing_module *mod, struct sof_ipc_stream_params *params);
int module_adapter_set_state(struct processing_module *mod, struct comp_dev *dev,
int cmd);
int module_adapter_sink_src_prepare(struct comp_dev *dev);
#endif /* __SOF_AUDIO_MODULE_GENERIC__ */