diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4caeabf27c54..29d1ad54a8bb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,6 +6,8 @@ add_subdirectory(ipc) add_subdirectory(audio) add_subdirectory(lib) add_subdirectory(math) +add_subdirectory(module) + if(CONFIG_SAMPLES) add_subdirectory(samples) endif() diff --git a/src/audio/sink_api_helper.c b/src/audio/sink_api_helper.c index 9961ee61dcb8..5d25474ac6b8 100644 --- a/src/audio/sink_api_helper.c +++ b/src/audio/sink_api_helper.c @@ -1,12 +1,13 @@ // SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2023 Intel Corporation. All rights reserved. -// +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ #include -#include #include +/* This file contains private sink API functions intended for use only by the sof. */ + void sink_init(struct sof_sink *sink, const struct sink_ops *ops, struct sof_audio_stream_params *audio_stream_params) { @@ -14,48 +15,6 @@ void sink_init(struct sof_sink *sink, const struct sink_ops *ops, sink->audio_stream_params = audio_stream_params; } -size_t sink_get_free_size(struct sof_sink *sink) -{ - return sink->ops->get_free_size(sink); -} - -int sink_get_buffer(struct sof_sink *sink, size_t req_size, - void **data_ptr, void **buffer_start, size_t *buffer_size) -{ - int ret; - - if (sink->requested_write_frag_size) - return -EBUSY; - - ret = sink->ops->get_buffer(sink, req_size, data_ptr, - buffer_start, buffer_size); - - if (!ret) - sink->requested_write_frag_size = req_size; - return ret; -} - -int sink_commit_buffer(struct sof_sink *sink, size_t commit_size) -{ - int ret; - - /* check if there was a buffer obtained for writing by sink_get_buffer */ - if (!sink->requested_write_frag_size) - return -ENODATA; - - /* limit size of data to be committed to previously obtained size */ - if (commit_size > sink->requested_write_frag_size) - commit_size = sink->requested_write_frag_size; - - ret = sink->ops->commit_buffer(sink, commit_size); - - if (!ret) - sink->requested_write_frag_size = 0; - - sink->num_of_bytes_processed += commit_size; - return ret; -} - size_t sink_get_num_of_processed_bytes(struct sof_sink *sink) { return sink->num_of_bytes_processed; @@ -66,128 +25,12 @@ void sink_reset_num_of_processed_bytes(struct sof_sink *sink) sink->num_of_bytes_processed = 0; } -enum sof_ipc_frame sink_get_frm_fmt(struct sof_sink *sink) -{ - return sink->audio_stream_params->frame_fmt; -} - -enum sof_ipc_frame sink_get_valid_fmt(struct sof_sink *sink) -{ - return sink->audio_stream_params->valid_sample_fmt; -} - -uint32_t sink_get_rate(struct sof_sink *sink) -{ - return sink->audio_stream_params->rate; -} - -uint32_t sink_get_channels(struct sof_sink *sink) -{ - return sink->audio_stream_params->channels; -} - -uint32_t sink_get_buffer_fmt(struct sof_sink *sink) -{ - return sink->audio_stream_params->buffer_fmt; -} - bool sink_get_overrun(struct sof_sink *sink) { return sink->audio_stream_params->overrun_permitted; } -int sink_set_frm_fmt(struct sof_sink *sink, enum sof_ipc_frame frame_fmt) -{ - sink->audio_stream_params->frame_fmt = frame_fmt; - - /* notify the implementation */ - if (sink->ops->on_audio_format_set) - return sink->ops->on_audio_format_set(sink); - return 0; -} - -int sink_set_valid_fmt(struct sof_sink *sink, - enum sof_ipc_frame valid_sample_fmt) -{ - sink->audio_stream_params->valid_sample_fmt = valid_sample_fmt; - if (sink->ops->on_audio_format_set) - return sink->ops->on_audio_format_set(sink); - return 0; -} - -int sink_set_rate(struct sof_sink *sink, unsigned int rate) -{ - sink->audio_stream_params->rate = rate; - if (sink->ops->on_audio_format_set) - return sink->ops->on_audio_format_set(sink); - return 0; -} - -int sink_set_channels(struct sof_sink *sink, unsigned int channels) -{ - sink->audio_stream_params->channels = channels; - if (sink->ops->on_audio_format_set) - return sink->ops->on_audio_format_set(sink); - return 0; -} - -int sink_set_buffer_fmt(struct sof_sink *sink, uint32_t buffer_fmt) -{ - sink->audio_stream_params->buffer_fmt = buffer_fmt; - if (sink->ops->on_audio_format_set) - return sink->ops->on_audio_format_set(sink); - return 0; -} - -int sink_set_overrun(struct sof_sink *sink, bool overrun_permitted) -{ - sink->audio_stream_params->overrun_permitted = overrun_permitted; - if (sink->ops->on_audio_format_set) - return sink->ops->on_audio_format_set(sink); - return 0; -} - -size_t sink_get_frame_bytes(struct sof_sink *sink) -{ - return get_frame_bytes(sink_get_frm_fmt(sink), - sink_get_channels(sink)); -} - -size_t sink_get_free_frames(struct sof_sink *sink) -{ - return sink_get_free_size(sink) / - sink_get_frame_bytes(sink); -} - -int sink_set_params(struct sof_sink *sink, - struct sof_ipc_stream_params *params, bool force_update) -{ - if (sink->ops->audio_set_ipc_params) - return sink->ops->audio_set_ipc_params(sink, params, force_update); - return 0; -} - -int sink_set_alignment_constants(struct sof_sink *sink, - const uint32_t byte_align, - const uint32_t frame_align_req) -{ - if (sink->ops->set_alignment_constants) - return sink->ops->set_alignment_constants(sink, byte_align, frame_align_req); - return 0; -} - void sink_set_min_free_space(struct sof_sink *sink, size_t min_free_space) { sink->min_free_space = min_free_space; } - -size_t sink_get_min_free_space(struct sof_sink *sink) -{ - return sink->min_free_space; -} - -uint32_t sink_get_id(struct sof_sink *sink) -{ - return sink->audio_stream_params->id; -} - diff --git a/src/audio/source_api_helper.c b/src/audio/source_api_helper.c index f1aec4924f9b..c7ca28c71720 100644 --- a/src/audio/source_api_helper.c +++ b/src/audio/source_api_helper.c @@ -1,12 +1,13 @@ // SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2023 Intel Corporation. All rights reserved. -// +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ #include -#include #include +/* This file contains private source API functions intended for use only by the sof. */ + void source_init(struct sof_source *source, const struct source_ops *ops, struct sof_audio_stream_params *audio_stream_params) { @@ -15,47 +16,6 @@ void source_init(struct sof_source *source, const struct source_ops *ops, source->audio_stream_params = audio_stream_params; } -size_t source_get_data_available(struct sof_source *source) -{ - return source->ops->get_data_available(source); -} - -int source_get_data(struct sof_source *source, size_t req_size, - void const **data_ptr, void const **buffer_start, size_t *buffer_size) -{ - int ret; - - if (source->requested_read_frag_size) - return -EBUSY; - - ret = source->ops->get_data(source, req_size, data_ptr, buffer_start, buffer_size); - - if (!ret) - source->requested_read_frag_size = req_size; - return ret; -} - -int source_release_data(struct sof_source *source, size_t free_size) -{ - int ret; - - /* Check if anything was obtained before for reading by source_get_data */ - if (!source->requested_read_frag_size) - return -ENODATA; - - /* limit size of data to be freed to previously obtained size */ - if (free_size > source->requested_read_frag_size) - free_size = source->requested_read_frag_size; - - ret = source->ops->release_data(source, free_size); - - if (!ret) - source->requested_read_frag_size = 0; - - source->num_of_bytes_processed += free_size; - return ret; -} - size_t source_get_num_of_processed_bytes(struct sof_source *source) { return source->num_of_bytes_processed; @@ -66,31 +26,6 @@ void source_reset_num_of_processed_bytes(struct sof_source *source) source->num_of_bytes_processed = 0; } -enum sof_ipc_frame source_get_frm_fmt(struct sof_source *source) -{ - return source->audio_stream_params->frame_fmt; -} - -enum sof_ipc_frame source_get_valid_fmt(struct sof_source *source) -{ - return source->audio_stream_params->valid_sample_fmt; -} - -unsigned int source_get_rate(struct sof_source *source) -{ - return source->audio_stream_params->rate; -} - -unsigned int source_get_channels(struct sof_source *source) -{ - return source->audio_stream_params->channels; -} - -uint32_t source_get_buffer_fmt(struct sof_source *source) -{ - return source->audio_stream_params->buffer_fmt; -} - bool source_get_underrun(struct sof_source *source) { return source->audio_stream_params->underrun_permitted; @@ -145,18 +80,6 @@ int source_set_underrun(struct sof_source *source, bool underrun_permitted) return 0; } -size_t source_get_frame_bytes(struct sof_source *source) -{ - return get_frame_bytes(source_get_frm_fmt(source), - source_get_channels(source)); -} - -size_t source_get_data_frames_available(struct sof_source *source) -{ - return source_get_data_available(source) / - source_get_frame_bytes(source); -} - int source_set_params(struct sof_source *source, struct sof_ipc_stream_params *params, bool force_update) { @@ -178,13 +101,3 @@ void source_set_min_available(struct sof_source *source, size_t min_available) { source->min_available = min_available; } - -size_t source_get_min_available(struct sof_source *source) -{ - return source->min_available; -} - -uint32_t source_get_id(struct sof_source *source) -{ - return source->audio_stream_params->id; -} diff --git a/src/include/module/audio/sink_api.h b/src/include/module/audio/sink_api.h new file mode 100644 index 000000000000..d5fd0118b3bf --- /dev/null +++ b/src/include/module/audio/sink_api.h @@ -0,0 +1,251 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + */ + +#ifndef __MODULE_AUDIO_SINK_API_H__ +#define __MODULE_AUDIO_SINK_API_H__ + +#include +#include +#include +#include + +#include "audio_stream.h" +#include "format.h" + +/** + * this is a definition of API to sink of audio data + * + * THE SINK is any component that can store data somehow and provide a buffer to be filled + * with data at request. The sink API does not define how the data will be processed/used + * + * The user - a module - sees this API as a destination it must send data to + * The IMPLEMENTATION - audio_stream, DP Queue - sees this as a producer that + * PROVIDES data for processing + * + * Examples of components that should expose SINK api + * - /dev/null + * all the data stored in sink buffer are just simply discarded + * - I2S sender + * Data stored in sink buffer will be sent to the external world + * - a memory ring buffer + * data stored in the buffer will be sent to another module (usually using source API, but it + * does not matter in fact). + * + * The main advantage of using sink API instead of just taking pointers to the buffers is that + * the buffer may be prepared at the moment the data producer is requesting it. i.e. + * - cache may be written back/invalidated if necessary + * - data may be moved to make linear space + * - part of the buffer may be locked to prevent reading + * etc.etc. it depends on implementation of the data sink + * + * NOTE: the module should get a complete portion of space it needs for processing, fill it + * than release. The reason is - the depending on the implementation, the calls may be + * expensive - may involve some data moving in memory, cache writebacks, etc. + * + */ + +/* forward def */ +struct sof_sink; +struct sof_audio_stream_params; +struct sof_ipc_stream_params; + +/** + * this is a definition of internals of sink API + * + * The clients of stream API should use access functions provided below! + * + */ + +struct sink_ops { + /** + * see comment of sink_get_free_size() + */ + size_t (*get_free_size)(struct sof_sink *sink); + + /** + * see comment of sink_get_buffer() + */ + int (*get_buffer)(struct sof_sink *sink, size_t req_size, + void **data_ptr, void **buffer_start, size_t *buffer_size); + + /** + * see comment of sink_commit_buffer() + */ + int (*commit_buffer)(struct sof_sink *sink, size_t commit_size); + + /** + * OPTIONAL: Notification to the sink implementation about changes in audio format + * + * Once any of *audio_stream_params elements changes, the implementation of + * sink may need to perform some extra operations. + * This callback will be called immediately after any change + * + * @retval 0 if success, negative if new parameters are not supported + */ + int (*on_audio_format_set)(struct sof_sink *sink); + + /** + * OPTIONAL + * see sink_set_params comments + */ + int (*audio_set_ipc_params)(struct sof_sink *sink, + struct sof_ipc_stream_params *params, bool force_update); + + /** + * OPTIONAL + * see comment for sink_set_alignment_constants + */ + int (*set_alignment_constants)(struct sof_sink *sink, + const uint32_t byte_align, + const uint32_t frame_align_req); +}; + +/** internals of sink API. NOT TO BE MODIFIED OUTSIDE OF sink_api.c */ +struct sof_sink { + const struct sink_ops *ops; /** operations interface */ + size_t requested_write_frag_size; /** keeps number of bytes requested by get_buffer() */ + size_t num_of_bytes_processed; /** processed bytes counter */ + size_t min_free_space; /** minimum buffer space required by the module using sink + * it is module's OBS as declared in module bind IPC + */ + struct sof_audio_stream_params *audio_stream_params; /** pointer to audio params */ +}; + +/** + * + * Public functions + * + */ + +/** + * Retrieves size of free space available in sink (in bytes) + * return number of free bytes in buffer available to immediate filling + */ +static inline size_t sink_get_free_size(struct sof_sink *sink) +{ + return sink->ops->get_free_size(sink); +} + +static inline enum sof_ipc_frame sink_get_frm_fmt(struct sof_sink *sink) +{ + return sink->audio_stream_params->frame_fmt; +} + +static inline uint32_t sink_get_channels(struct sof_sink *sink) +{ + return sink->audio_stream_params->channels; +} + +/** get size of a single audio frame (in bytes) */ +size_t sink_get_frame_bytes(struct sof_sink *sink); + +/** + * Retrieves size of free space available in sink (in frames) + * return number of free frames in buffer available to immediate filling + */ +size_t sink_get_free_frames(struct sof_sink *sink); + +/** + * Get a circular buffer to operate on (to write). + * + * Retrieves a fragment of circular data to be used by the caller + * After calling get_buffer, the space for data is guaranteed to be available + * for exclusive use on the caller core through provided pointer + * if the provided pointers are cached, it is guaranteed that the caller may safely use it without + * any additional cache operations + * The caller MUST take care of data circularity based on provided pointers + * + * @param sink a handler to sink + * @param [in] req_size requested size of space + * @param [out] data_ptr a pointer to the space will be provided there + * @param [out] buffer_start pointer to circular buffer start + * @param [out] buffer_size size of circular buffer + * + * @retval -ENODATA if req_size is bigger than free space + * + */ +int sink_get_buffer(struct sof_sink *sink, size_t req_size, void **data_ptr, void **buffer_start, + size_t *buffer_size); + +/** + * Commits that the buffer previously obtained by get_buffer is filled with data + * and ready to be used + * + * @param sink a handler to sink + * @param commit_size amount of data that the caller declares as valid + * if commit_size is bigger than the amount of data obtained before by get_buffer(), only + * the amount obtained before will be committed. That means - if somebody obtained a buffer, + * filled it with data and wants to commit it in whole, it may simple call + * commit_buffer with commit_size==MAXINT + * @return proper error code (0 on success) + */ +int sink_commit_buffer(struct sof_sink *sink, size_t commit_size); + +/** set of functions for retrieve audio parameters */ +int sink_set_frm_fmt(struct sof_sink *sink, enum sof_ipc_frame frame_fmt); + +static inline enum sof_ipc_frame sink_get_valid_fmt(struct sof_sink *sink) +{ + return sink->audio_stream_params->valid_sample_fmt; +} + +static inline uint32_t sink_get_rate(struct sof_sink *sink) +{ + return sink->audio_stream_params->rate; +} + +static inline uint32_t sink_get_buffer_fmt(struct sof_sink *sink) +{ + return sink->audio_stream_params->buffer_fmt; +} + +/** + * initial set of audio parameters, provided in sof_ipc_stream_params + * + * @param sink a handler to sink + * @param params the set of parameters + * @param force_update tells the implementation that the params should override actual settings + * @return 0 if success + */ +int sink_set_params(struct sof_sink *sink, struct sof_ipc_stream_params *params, bool force_update); + +/** + * Set frame_align_shift and frame_align of stream according to byte_align and + * frame_align_req alignment requirement. Once the channel number,frame size + * are determined, the frame_align and frame_align_shift are determined too. + * these two feature will be used in audio_stream_get_avail_frames_aligned + * to calculate the available frames. it should be called in component prepare + * or param functions only once before stream copy. if someone forgets to call + * this first, there would be unexampled error such as nothing is copied at all. + * + * @param sink a handler to sink + * @param byte_align Processing byte alignment requirement. + * @param frame_align_req Processing frames alignment requirement. + * + * @return 0 if success + */ +int sink_set_alignment_constants(struct sof_sink *sink, + const uint32_t byte_align, + const uint32_t frame_align_req); + +int sink_set_valid_fmt(struct sof_sink *sink, enum sof_ipc_frame valid_sample_fmt); +int sink_set_rate(struct sof_sink *sink, unsigned int rate); +int sink_set_channels(struct sof_sink *sink, unsigned int channels); +int sink_set_buffer_fmt(struct sof_sink *sink, uint32_t buffer_fmt); +int sink_set_overrun(struct sof_sink *sink, bool overrun_permitted); +int sink_set_params(struct sof_sink *sink, struct sof_ipc_stream_params *params, bool force_update); + +static inline size_t sink_get_min_free_space(struct sof_sink *sink) +{ + return sink->min_free_space; +} + +static inline uint32_t sink_get_id(struct sof_sink *sink) +{ + return sink->audio_stream_params->id; +} + +#endif /* __MODULE_AUDIO_SINK_API_H__ */ diff --git a/src/include/module/audio/source_api.h b/src/include/module/audio/source_api.h new file mode 100644 index 000000000000..e4b522bdb7f0 --- /dev/null +++ b/src/include/module/audio/source_api.h @@ -0,0 +1,229 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + */ + +#ifndef __MODULE_AUDIO_SOURCE_API_H__ +#define __MODULE_AUDIO_SOURCE_API_H__ + +#include +#include +#include +#include + +#include "audio_stream.h" +#include "format.h" + +/** + * this is a definition of API to source of audio data + * + * THE SOURCE is any component in the system that have data stored somehow and can give the + * data outside at request. The source API does not define who and how has produced the data + * + * The user - a module - sees this as a producer that PROVIDES data for processing + * The IMPLEMENTATION - audio_stream, DP Queue - sees this API as a destination it must send data to + * * + * Examples of components that should expose source API: + * - DMIC + * Data are coming from the outside world, stores in tmp buffer and can be presented + * to the rest of the system using source_api + * - a memory ring buffer + * Data are coming from other module (usually using sink_api, but it does not matter in fact) + * + * The main advantage of using source API instead of just taking pointers to the data is that + * the data may be prepared at the moment the data receiver is requesting it. i.e. + * - cache may be written back/invalidated if necessary + * - data may be moved from circular to linear space + * - part of the buffer may be locked to prevent writing + * etc.etc. it depends on implementation of the data source + * + * Data in general are provided as a circular buffer and the data receiver should be able to + * deal with it. Of course if needed an implementation of source providing linear data can be + * implemented and used as a mid-layer for modules needing it. + * + * NOTE: the module should get a complete portion of data it needs for processing, process it + * than release. The reason is - the depending on the implementation, the calls may be + * expensive - may involve some data moving in memory, cache writebacks, etc. + */ + + /* forward def */ +struct sof_source; +struct sof_audio_stream_params; +struct sof_ipc_stream_params; + +/** + * this is a definition of internals of source API + * + * The clients of stream API should use access functions provided below! + * + */ + +struct source_ops { + /** + * see comment of source_get_data_available() + */ + size_t (*get_data_available)(struct sof_source *source); + + /** + * see comment of source_get_data_available() + */ + int (*get_data)(struct sof_source *source, size_t req_size, + void const **data_ptr, void const **buffer_start, size_t *buffer_size); + + /** + * see comment of source_release_data() + */ + int (*release_data)(struct sof_source *source, size_t free_size); + + /** + * OPTIONAL: Notification to the source implementation about changes in audio format + * + * Once any of *audio_stream_params elements changes, the implementation of + * source may need to perform some extra operations. + * This callback will be called immediately after any change + * + * @retval 0 if success, negative if new parameteres are not supported + */ + int (*on_audio_format_set)(struct sof_source *source); + + /** + * OPTIONAL + * see source_set_params comments + */ + int (*audio_set_ipc_params)(struct sof_source *source, + struct sof_ipc_stream_params *params, bool force_update); + + /** + * OPTIONAL + * see comment for source_set_alignment_constants + */ + int (*set_alignment_constants)(struct sof_source *source, + const uint32_t byte_align, + const uint32_t frame_align_req); +}; + +/** internals of source API. NOT TO BE MODIFIED OUTSIDE OF source_api.c */ +struct sof_source { + const struct source_ops *ops; + size_t requested_read_frag_size; /* keeps size of data obtained by get_data() */ + size_t num_of_bytes_processed; /* processed bytes counter */ + size_t min_available; /* minimum data available required by the module using + * source + * it is module's IBS as declared in module bind IPC + */ + + struct sof_audio_stream_params *audio_stream_params; +}; + +/** + * + * Public functions + * + */ + +/** + * Retrieves size of available data (in bytes) + * return number of bytes that are available for immediate use + */ +static inline size_t source_get_data_available(struct sof_source *source) +{ + return source->ops->get_data_available(source); +} + +static inline enum sof_ipc_frame source_get_frm_fmt(struct sof_source *source) +{ + return source->audio_stream_params->frame_fmt; +} + +static inline unsigned int source_get_channels(struct sof_source *source) +{ + return source->audio_stream_params->channels; +} + +/** get size of a single audio frame (in bytes) */ +size_t source_get_frame_bytes(struct sof_source *source); + +/** + * Retrieves size of available data (in frames) + * return number of frames that are available for immediate use + */ +size_t source_get_data_frames_available(struct sof_source *source); + +/** + * Retrieves a fragment of circular data to be used by the caller (to read) + * After calling get_data, the data are guaranteed to be available + * for exclusive use (read only) + * if the provided pointers are cached, it is guaranteed that the caller may safely use it without + * any additional cache operations + * + * The caller MUST take care of data circularity based on provided pointers + * + * Depending on implementation - there may be a way to have several receivers of the same + * data, as long as the receiver respects that data are read-only and won'do anything + * fancy with cache handling itself + * + * some implementation data may be stored in linear buffer + * in that case: + * data_ptr = buffer_start + * buffer_end = data_ptr + req_size + * buffer_size = req_size + * + * and the data receiver may use it as usual, rollover will simple never occur + * NOTE! the caller MUST NOT assume that pointers to start/end of the circular buffer + * are constant. They may change between calls + * + * @param source a handler to source + * @param [in] req_size requested size of data. + * @param [out] data_ptr a pointer to data will be provided there + * @param [out] buffer_start pointer to circular buffer start + * @param [out] buffer_size size of circular buffer + * + * @retval -ENODATA if req_size is bigger than available data + */ +int source_get_data(struct sof_source *source, size_t req_size, void const **data_ptr, + void const **buffer_start, size_t *buffer_size); + +/** + * Releases fragment previously obtained by source_get_data() + * Once called, the data are no longer available for the caller + * + * @param source a handler to source + * @param free_size amount of data that the caller declares as "never needed again" + * if free_size == 0 the source implementation MUST keep all data in memory and make them + * available again at next get_data() call + * if free_size is bigger than the amount of data obtained before by get_data(), only + * the amount obtained before will be freed. That means - if somebody obtained some data, + * processed it and won't need it again, it may simple call put_data with free_size==MAXINT + * + * @return proper error code (0 on success) + */ +int source_release_data(struct sof_source *source, size_t free_size); + +/** set of functions for retrieve audio parameters */ +static inline enum sof_ipc_frame source_get_valid_fmt(struct sof_source *source) +{ + return source->audio_stream_params->valid_sample_fmt; +} + +static inline unsigned int source_get_rate(struct sof_source *source) +{ + return source->audio_stream_params->rate; +} + +static inline uint32_t source_get_buffer_fmt(struct sof_source *source) +{ + return source->audio_stream_params->buffer_fmt; +} + +static inline size_t source_get_min_available(struct sof_source *source) +{ + return source->min_available; +} + +static inline uint32_t source_get_id(struct sof_source *source) +{ + return source->audio_stream_params->id; +} + +#endif /* __MODULE_AUDIO_SOURCE_API_H__ */ diff --git a/src/include/sof/audio/audio_stream.h b/src/include/sof/audio/audio_stream.h index 9e6424d80a37..09bfb68a038d 100644 --- a/src/include/sof/audio/audio_stream.h +++ b/src/include/sof/audio/audio_stream.h @@ -16,9 +16,7 @@ #include #include -#include #include -#include #include #include #include diff --git a/src/include/sof/audio/dp_queue.h b/src/include/sof/audio/dp_queue.h index 1c699f11e273..877613d141f9 100644 --- a/src/include/sof/audio/dp_queue.h +++ b/src/include/sof/audio/dp_queue.h @@ -9,8 +9,6 @@ #include #include -#include -#include #include #include #include diff --git a/src/include/sof/audio/sink_api.h b/src/include/sof/audio/sink_api.h index e9c1fa7e2d80..11ffc6e08c3d 100644 --- a/src/include/sof/audio/sink_api.h +++ b/src/include/sof/audio/sink_api.h @@ -7,96 +7,20 @@ #ifndef __SOF_SINK_API_H__ #define __SOF_SINK_API_H__ -#include -#include -#include -#include +#include /** - * this is a definition of API to sink of audio data + * Init of the API, must be called before any operation * - * THE SINK is any component that can store data somehow and provide a buffer to be filled - * with data at request. The sink API does not define how the data will be processed/used - * - * The user - a module - sees this API as a destination it must send data to - * The IMPLEMENTATION - audio_stream, DP Queue - sees this as a producer that - * PROVIDES data for processing - * - * Examples of components that should expose SINK api - * - /dev/null - * all the data stored in sink buffer are just simply discarded - * - I2S sender - * Data stored in sink buffer will be sent to the external world - * - a memory ring buffer - * data stored in the buffer will be sent to another module (usually using source API, but it - * does not matter in fact). - * - * The main advantage of using sink API instead of just taking pointers to the buffers is that - * the buffer may be prepared at the moment the data producer is requesting it. i.e. - * - cache may be written back/invalidated if necessary - * - data may be moved to make linear space - * - part of the buffer may be locked to prevent reading - * etc.etc. it depends on implementation of the data sink - * - * NOTE: the module should get a complete portion of space it needs for processing, fill it - * than release. The reason is - the depending on the implementation, the calls may be - * expensive - may involve some data moving in memory, cache writebacks, etc. - * - */ - -/** definition of obfsfucated handler of sink API */ -struct sof_sink; - -/* forward def */ -struct sof_ipc_stream_params; - -/** - * Retrieves size of free space available in sink (in bytes) - * return number of free bytes in buffer available to immediate filling - */ -size_t sink_get_free_size(struct sof_sink *sink); - -/** - * Retrieves size of free space available in sink (in frames) - * return number of free bytes in buffer available to immediate filling - */ -size_t sink_get_free_frames(struct sof_sink *sink); - -/** - * Get a circular buffer to operate on (to write). - * - * Retrieves a fragment of circular data to be used by the caller - * After calling get_buffer, the space for data is guaranteed to be available - * for exclusive use on the caller core through provided pointer - * if the provided pointers are cached, it is guaranteed that the caller may safely use it without - * any additional cache operations - * The caller MUST take care of data circularity based on provided pointers - * - * @param sink a handler to sink - * @param [in] req_size requested size of space - * @param [out] data_ptr a pointer to the space will be provided there - * @param [out] buffer_start pointer to circular buffer start - * @param [out] buffer_size size of circular buffer - * - * @retval -ENODATA if req_size is bigger than free space - * - */ -int sink_get_buffer(struct sof_sink *sink, size_t req_size, - void **data_ptr, void **buffer_start, size_t *buffer_size); - -/** - * Commits that the buffer previously obtained by get_buffer is filled with data - * and ready to be used - * - * @param sink a handler to sink - * @param commit_size amount of data that the caller declares as valid - * if commit_size is bigger than the amount of data obtained before by get_buffer(), only - * the amount obtained before will be committed. That means - if somebody obtained a buffer, - * filled it with data and wants to commit it in whole, it may simple call - * commit_buffer with commit_size==MAXINT - * @return proper error code (0 on success) + * @param sink pointer to the structure + * @param ops pointer to API operations + * @param audio_stream_params pointer to structure with audio parameters + * note that the audio_stream_params must be accessible by the caller core + * the implementation must ensure coherent access to the parameteres + * in case of i.e. cross core shared queue, it must be located in non-cached memory */ -int sink_commit_buffer(struct sof_sink *sink, size_t commit_size); +void sink_init(struct sof_sink *sink, const struct sink_ops *ops, + struct sof_audio_stream_params *audio_stream_params); /** * Get total number of bytes processed by the sink (meaning - committed by sink_commit_buffer()) @@ -111,56 +35,10 @@ size_t sink_get_num_of_processed_bytes(struct sof_sink *sink); */ void sink_reset_num_of_processed_bytes(struct sof_sink *sink); -/** get size of a single audio frame (in bytes) */ -size_t sink_get_frame_bytes(struct sof_sink *sink); - /** set of functions for retrieve audio parameters */ -enum sof_ipc_frame sink_get_frm_fmt(struct sof_sink *sink); -enum sof_ipc_frame sink_get_valid_fmt(struct sof_sink *sink); -uint32_t sink_get_rate(struct sof_sink *sink); -uint32_t sink_get_channels(struct sof_sink *sink); -uint32_t sink_get_buffer_fmt(struct sof_sink *sink); bool sink_get_overrun(struct sof_sink *sink); /** set of functions for setting audio parameters */ -int sink_set_frm_fmt(struct sof_sink *sink, enum sof_ipc_frame frame_fmt); -int sink_set_valid_fmt(struct sof_sink *sink, enum sof_ipc_frame valid_sample_fmt); -int sink_set_rate(struct sof_sink *sink, unsigned int rate); -int sink_set_channels(struct sof_sink *sink, unsigned int channels); -int sink_set_overrun(struct sof_sink *sink, bool overrun_permitted); -int sink_set_buffer_fmt(struct sof_sink *sink, uint32_t buffer_fmt); void sink_set_min_free_space(struct sof_sink *sink, size_t min_free_space); -size_t sink_get_min_free_space(struct sof_sink *sink); -uint32_t sink_get_id(struct sof_sink *sink); - -/** - * initial set of audio parameters, provided in sof_ipc_stream_params - * - * @param sink a handler to sink - * @param params the set of parameters - * @param force_update tells the implementation that the params should override actual settings - * @return 0 if success - */ -int sink_set_params(struct sof_sink *sink, - struct sof_ipc_stream_params *params, bool force_update); - -/** - * Set frame_align_shift and frame_align of stream according to byte_align and - * frame_align_req alignment requirement. Once the channel number,frame size - * are determined, the frame_align and frame_align_shift are determined too. - * these two feature will be used in audio_stream_get_avail_frames_aligned - * to calculate the available frames. it should be called in component prepare - * or param functions only once before stream copy. if someone forgets to call - * this first, there would be unexampled error such as nothing is copied at all. - * - * @param sink a handler to sink - * @param byte_align Processing byte alignment requirement. - * @param frame_align_req Processing frames alignment requirement. - * - * @return 0 if success - */ -int sink_set_alignment_constants(struct sof_sink *sink, - const uint32_t byte_align, - const uint32_t frame_align_req); #endif /* __SOF_SINK_API_H__ */ diff --git a/src/include/sof/audio/sink_api_implementation.h b/src/include/sof/audio/sink_api_implementation.h deleted file mode 100644 index 23cec8dbb30e..000000000000 --- a/src/include/sof/audio/sink_api_implementation.h +++ /dev/null @@ -1,94 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2023 Intel Corporation. All rights reserved. - * - */ - -#ifndef __SOF_SINK_API_IMPLEMENTATION_H__ -#define __SOF_SINK_API_IMPLEMENTATION_H__ - -#include -#include -#include - -/* forward def */ -struct sof_audio_stream_params; - -/** - * this is a definition of internals of sink API - * - * this file should be included by the implementations of sink API - * - * The clients of stream API should use functions provided in sink_api.h ONLY - * - */ - -struct sink_ops { - /** - * see comment of sink_get_free_size() - */ - size_t (*get_free_size)(struct sof_sink *sink); - - /** - * see comment of sink_get_buffer() - */ - int (*get_buffer)(struct sof_sink *sink, size_t req_size, - void **data_ptr, void **buffer_start, size_t *buffer_size); - - /** - * see comment of sink_commit_buffer() - */ - int (*commit_buffer)(struct sof_sink *sink, size_t commit_size); - - /** - * OPTIONAL: Notification to the sink implementation about changes in audio format - * - * Once any of *audio_stream_params elements changes, the implementation of - * sink may need to perform some extra operations. - * This callback will be called immediately after any change - * - * @retval 0 if success, negative if new parameters are not supported - */ - int (*on_audio_format_set)(struct sof_sink *sink); - - /** - * OPTIONAL - * see sink_set_params comments - */ - int (*audio_set_ipc_params)(struct sof_sink *sink, - struct sof_ipc_stream_params *params, bool force_update); - - /** - * OPTIONAL - * see comment for sink_set_alignment_constants - */ - int (*set_alignment_constants)(struct sof_sink *sink, - const uint32_t byte_align, - const uint32_t frame_align_req); -}; - -/** internals of sink API. NOT TO BE MODIFIED OUTSIDE OF sink_api_helper.h */ -struct sof_sink { - const struct sink_ops *ops; /** operations interface */ - size_t requested_write_frag_size; /** keeps number of bytes requested by get_buffer() */ - size_t num_of_bytes_processed; /** processed bytes counter */ - size_t min_free_space; /** minimum buffer space required by the module using sink - * it is module's OBS as declared in module bind IPC - */ - struct sof_audio_stream_params *audio_stream_params; /** pointer to audio params */ -}; - -/** - * Init of the API, must be called before any operation - * - * @param sink pointer to the structure - * @param ops pointer to API operations - * @param audio_stream_params pointer to structure with audio parameters - * note that the audio_stream_params must be accessible by the caller core - * the implementation must ensure coherent access to the parameteres - * in case of i.e. cross core shared queue, it must be located in non-cached memory - */ -void sink_init(struct sof_sink *sink, const struct sink_ops *ops, - struct sof_audio_stream_params *audio_stream_params); - -#endif /* __SOF_SINK_API_IMPLEMENTATION_H__ */ diff --git a/src/include/sof/audio/source_api.h b/src/include/sof/audio/source_api.h index de224f4bc51a..2f84e1948ebe 100644 --- a/src/include/sof/audio/source_api.h +++ b/src/include/sof/audio/source_api.h @@ -7,110 +7,20 @@ #ifndef __SOF_SOURCE_API_H__ #define __SOF_SOURCE_API_H__ -#include -#include -#include -#include +#include /** - * this is a definition of API to source of audio data - * - * THE SOURCE is any component in the system that have data stored somehow and can give the - * data outside at request. The source API does not define who and how has produced the data - * - * The user - a module - sees this as a producer that PROVIDES data for processing - * The IMPLEMENTATION - audio_stream, DP Queue - sees this API as a destination it must send data to - * * - * Examples of components that should expose source API: - * - DMIC - * Data are coming from the outside world, stores in tmp buffer and can be presented - * to the rest of the system using source_api - * - a memory ring buffer - * Data are coming from other module (usually using sink_api, but it does not matter in fact) - * - * The main advantage of using source API instead of just taking pointers to the data is that - * the data may be prepared at the moment the data receiver is requesting it. i.e. - * - cache may be written back/invalidated if necessary - * - data may be moved from circular to linear space - * - part of the buffer may be locked to prevent writing - * etc.etc. it depends on implementation of the data source - * - * Data in general are provided as a circular buffer and the data receiver should be able to - * deal with it. Of course if needed an implementation of source providing linear data can be - * implemented and used as a mid-layer for modules needing it. - * - * NOTE: the module should get a complete portion of data it needs for processing, process it - * than release. The reason is - the depending on the implementation, the calls may be - * expensive - may involve some data moving in memory, cache writebacks, etc. - */ - -/** definition of obfsfucated handler of source API */ -struct sof_source; - -/* forward def */ -struct sof_ipc_stream_params; - -/** - * Retrieves size of available data (in bytes) - * return number of bytes that are available for immediate use - */ -size_t source_get_data_available(struct sof_source *source); - -/** - * Retrieves size of available data (in frames) - * return number of bytes that are available for immediate use - */ -size_t source_get_data_frames_available(struct sof_source *source); - -/** - * Retrieves a fragment of circular data to be used by the caller (to read) - * After calling get_data, the data are guaranteed to be available - * for exclusive use (read only) - * if the provided pointers are cached, it is guaranteed that the caller may safely use it without - * any additional cache operations - * - * The caller MUST take care of data circularity based on provided pointers - * - * Depending on implementation - there may be a way to have several receivers of the same - * data, as long as the receiver respects that data are read-only and won'do anything - * fancy with cache handling itself - * - * some implementation data may be stored in linear buffer - * in that case: - * data_ptr = buffer_start - * buffer_end = data_ptr + req_size - * buffer_size = req_size - * - * and the data receiver may use it as usual, rollover will simple never occur - * NOTE! the caller MUST NOT assume that pointers to start/end of the circular buffer - * are constant. They may change between calls - * - * @param source a handler to source - * @param [in] req_size requested size of data. - * @param [out] data_ptr a pointer to data will be provided there - * @param [out] buffer_start pointer to circular buffer start - * @param [out] buffer_size size of circular buffer - * - * @retval -ENODATA if req_size is bigger than available data + * Init of the API, must be called before any operation + * + * @param source pointer to the structure + * @param ops pointer to API operations + * @param audio_stream_params pointer to structure with audio parameters + * note that the audio_stream_params must be accessible by the caller core + * the implementation must ensure coherent access to the parameteres + * in case of i.e. cross core shared queue, it must be located in non-cached memory */ -int source_get_data(struct sof_source *source, size_t req_size, - void const **data_ptr, void const **buffer_start, size_t *buffer_size); - -/** - * Releases fragment previously obtained by source_get_data() - * Once called, the data are no longer available for the caller - * - * @param source a handler to source - * @param free_size amount of data that the caller declares as "never needed again" - * if free_size == 0 the source implementation MUST keep all data in memory and make them - * available again at next get_data() call - * if free_size is bigger than the amount of data obtained before by get_data(), only - * the amount obtained before will be freed. That means - if somebody obtained some data, - * processed it and won't need it again, it may simple call put_data with free_size==MAXINT - * - * @return proper error code (0 on success) - */ -int source_release_data(struct sof_source *source, size_t free_size); +void source_init(struct sof_source *source, const struct source_ops *ops, + struct sof_audio_stream_params *audio_stream_params); /** * Get total number of bytes processed by the source (meaning - freed by source_release_data()) @@ -122,15 +32,7 @@ size_t source_get_num_of_processed_bytes(struct sof_source *source); */ void source_reset_num_of_processed_bytes(struct sof_source *source); -/** get size of a single audio frame (in bytes) */ -size_t source_get_frame_bytes(struct sof_source *source); - /** set of functions for retrieve audio parameters */ -enum sof_ipc_frame source_get_frm_fmt(struct sof_source *source); -enum sof_ipc_frame source_get_valid_fmt(struct sof_source *source); -unsigned int source_get_rate(struct sof_source *source); -unsigned int source_get_channels(struct sof_source *source); -uint32_t source_get_buffer_fmt(struct sof_source *source); bool source_get_underrun(struct sof_source *source); uint32_t source_get_id(struct sof_source *source); @@ -143,7 +45,6 @@ int source_set_channels(struct sof_source *source, unsigned int channels); int source_set_underrun(struct sof_source *source, bool underrun_permitted); int source_set_buffer_fmt(struct sof_source *source, uint32_t buffer_fmt); void source_set_min_available(struct sof_source *source, size_t min_available); -size_t source_get_min_available(struct sof_source *source); /** * initial set of audio parameters, provided in sof_ipc_stream_params diff --git a/src/include/sof/audio/source_api_implementation.h b/src/include/sof/audio/source_api_implementation.h deleted file mode 100644 index 606141c92dfb..000000000000 --- a/src/include/sof/audio/source_api_implementation.h +++ /dev/null @@ -1,96 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2023 Intel Corporation. All rights reserved. - * - */ - -#ifndef __SOF_SOURCE_API_IMPLEMENTATION_H__ -#define __SOF_SOURCE_API_IMPLEMENTATION_H__ - -#include -#include -#include - -/* forward def */ -struct sof_audio_stream_params; - -/** - * this is a definition of internals of source API - * - * this file should be included by the implementations of source API - * - * The clients of stream API should use functions provided in source_api.h ONLY - * - */ - -struct source_ops { - /** - * see comment of source_get_data_available() - */ - size_t (*get_data_available)(struct sof_source *source); - - /** - * see comment of source_get_data_available() - */ - int (*get_data)(struct sof_source *source, size_t req_size, - void const **data_ptr, void const **buffer_start, size_t *buffer_size); - - /** - * see comment of source_release_data() - */ - int (*release_data)(struct sof_source *source, size_t free_size); - - /** - * OPTIONAL: Notification to the source implementation about changes in audio format - * - * Once any of *audio_stream_params elements changes, the implementation of - * source may need to perform some extra operations. - * This callback will be called immediately after any change - * - * @retval 0 if success, negative if new parameteres are not supported - */ - int (*on_audio_format_set)(struct sof_source *source); - - /** - * OPTIONAL - * see source_set_params comments - */ - int (*audio_set_ipc_params)(struct sof_source *source, - struct sof_ipc_stream_params *params, bool force_update); - - /** - * OPTIONAL - * see comment for source_set_alignment_constants - */ - int (*set_alignment_constants)(struct sof_source *source, - const uint32_t byte_align, - const uint32_t frame_align_req); -}; - -/** internals of source API. NOT TO BE MODIFIED OUTSIDE OF source_api_helper.h */ -struct sof_source { - const struct source_ops *ops; - size_t requested_read_frag_size; /** keeps size of data obtained by get_data() */ - size_t num_of_bytes_processed; /** processed bytes counter */ - size_t min_available; /** minimum data available required by the module using - * source - * it is module's IBS as declared in module bind IPC - */ - - struct sof_audio_stream_params *audio_stream_params; -}; - -/** - * Init of the API, must be called before any operation - * - * @param source pointer to the structure - * @param ops pointer to API operations - * @param audio_stream_params pointer to structure with audio parameters - * note that the audio_stream_params must be accessible by the caller core - * the implementation must ensure coherent access to the parameteres - * in case of i.e. cross core shared queue, it must be located in non-cached memory - */ -void source_init(struct sof_source *source, const struct source_ops *ops, - struct sof_audio_stream_params *audio_stream_params); - -#endif /* __SOF_SOURCE_API_IMPLEMENTATION_H__ */ diff --git a/src/module/CMakeLists.txt b/src/module/CMakeLists.txt new file mode 100644 index 000000000000..1cdd0d2137a9 --- /dev/null +++ b/src/module/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_subdirectory(audio) diff --git a/src/module/audio/CMakeLists.txt b/src/module/audio/CMakeLists.txt new file mode 100644 index 000000000000..2d805aa68929 --- /dev/null +++ b/src/module/audio/CMakeLists.txt @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: BSD-3-Clause + +is_zephyr(it_is) +if(it_is) ### Zephyr ### + zephyr_library_sources( + source_api.c + sink_api.c + ) +else() ### Not Zephyr ### + add_local_sources(sof + source_api.c + sink_api.c + ) +endif() # Zephyr diff --git a/src/module/audio/sink_api.c b/src/module/audio/sink_api.c new file mode 100644 index 000000000000..cb40405974dc --- /dev/null +++ b/src/module/audio/sink_api.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#include +#include + +/* This file contains public sink API functions that were too large to mark is as inline. */ + +int sink_get_buffer(struct sof_sink *sink, size_t req_size, + void **data_ptr, void **buffer_start, size_t *buffer_size) +{ + int ret; + + if (sink->requested_write_frag_size) + return -EBUSY; + + ret = sink->ops->get_buffer(sink, req_size, data_ptr, + buffer_start, buffer_size); + + if (!ret) + sink->requested_write_frag_size = req_size; + return ret; +} + +int sink_commit_buffer(struct sof_sink *sink, size_t commit_size) +{ + int ret; + + /* check if there was a buffer obtained for writing by sink_get_buffer */ + if (!sink->requested_write_frag_size) + return -ENODATA; + + /* limit size of data to be committed to previously obtained size */ + if (commit_size > sink->requested_write_frag_size) + commit_size = sink->requested_write_frag_size; + + ret = sink->ops->commit_buffer(sink, commit_size); + + if (!ret) + sink->requested_write_frag_size = 0; + + sink->num_of_bytes_processed += commit_size; + return ret; +} + +int sink_set_frm_fmt(struct sof_sink *sink, enum sof_ipc_frame frame_fmt) +{ + sink->audio_stream_params->frame_fmt = frame_fmt; + + /* notify the implementation */ + if (sink->ops->on_audio_format_set) + return sink->ops->on_audio_format_set(sink); + return 0; +} + +size_t sink_get_frame_bytes(struct sof_sink *sink) +{ + return get_frame_bytes(sink_get_frm_fmt(sink), sink_get_channels(sink)); +} + +size_t sink_get_free_frames(struct sof_sink *sink) +{ + return sink_get_free_size(sink) / sink_get_frame_bytes(sink); +} + +int sink_set_valid_fmt(struct sof_sink *sink, enum sof_ipc_frame valid_sample_fmt) +{ + sink->audio_stream_params->valid_sample_fmt = valid_sample_fmt; + if (sink->ops->on_audio_format_set) + return sink->ops->on_audio_format_set(sink); + return 0; +} + +int sink_set_rate(struct sof_sink *sink, unsigned int rate) +{ + sink->audio_stream_params->rate = rate; + if (sink->ops->on_audio_format_set) + return sink->ops->on_audio_format_set(sink); + return 0; +} + +int sink_set_channels(struct sof_sink *sink, unsigned int channels) +{ + sink->audio_stream_params->channels = channels; + if (sink->ops->on_audio_format_set) + return sink->ops->on_audio_format_set(sink); + return 0; +} + +int sink_set_buffer_fmt(struct sof_sink *sink, uint32_t buffer_fmt) +{ + sink->audio_stream_params->buffer_fmt = buffer_fmt; + if (sink->ops->on_audio_format_set) + return sink->ops->on_audio_format_set(sink); + return 0; +} + +int sink_set_overrun(struct sof_sink *sink, bool overrun_permitted) +{ + sink->audio_stream_params->overrun_permitted = overrun_permitted; + if (sink->ops->on_audio_format_set) + return sink->ops->on_audio_format_set(sink); + return 0; +} + +int sink_set_params(struct sof_sink *sink, struct sof_ipc_stream_params *params, bool force_update) +{ + if (sink->ops->audio_set_ipc_params) + return sink->ops->audio_set_ipc_params(sink, params, force_update); + return 0; +} + +int sink_set_alignment_constants(struct sof_sink *sink, const uint32_t byte_align, + const uint32_t frame_align_req) +{ + if (sink->ops->set_alignment_constants) + return sink->ops->set_alignment_constants(sink, byte_align, frame_align_req); + return 0; +} diff --git a/src/module/audio/source_api.c b/src/module/audio/source_api.c new file mode 100644 index 000000000000..2f589524621f --- /dev/null +++ b/src/module/audio/source_api.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + + +#include +#include + +/* This file contains public source API functions that were too large to mark is as inline. */ + +int source_get_data(struct sof_source *source, size_t req_size, + void const **data_ptr, void const **buffer_start, size_t *buffer_size) +{ + int ret; + + if (source->requested_read_frag_size) + return -EBUSY; + + ret = source->ops->get_data(source, req_size, data_ptr, buffer_start, buffer_size); + + if (!ret) + source->requested_read_frag_size = req_size; + return ret; +} + +int source_release_data(struct sof_source *source, size_t free_size) +{ + int ret; + + /* Check if anything was obtained before for reading by source_get_data */ + if (!source->requested_read_frag_size) + return -ENODATA; + + /* limit size of data to be freed to previously obtained size */ + if (free_size > source->requested_read_frag_size) + free_size = source->requested_read_frag_size; + + ret = source->ops->release_data(source, free_size); + + if (!ret) + source->requested_read_frag_size = 0; + + source->num_of_bytes_processed += free_size; + return ret; +} + +size_t source_get_frame_bytes(struct sof_source *source) +{ + return get_frame_bytes(source_get_frm_fmt(source), + source_get_channels(source)); +} + +size_t source_get_data_frames_available(struct sof_source *source) +{ + return source_get_data_available(source) / + source_get_frame_bytes(source); +} diff --git a/test/cmocka/src/audio/buffer/CMakeLists.txt b/test/cmocka/src/audio/buffer/CMakeLists.txt index acc92539a5e6..4db02de6f571 100644 --- a/test/cmocka/src/audio/buffer/CMakeLists.txt +++ b/test/cmocka/src/audio/buffer/CMakeLists.txt @@ -8,6 +8,8 @@ cmocka_test(buffer_copy ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c @@ -30,6 +32,8 @@ cmocka_test(buffer_new ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c @@ -51,6 +55,8 @@ cmocka_test(buffer_wrap ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c @@ -72,6 +78,8 @@ cmocka_test(buffer_write ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c diff --git a/test/cmocka/src/audio/component/CMakeLists.txt b/test/cmocka/src/audio/component/CMakeLists.txt index 5eb4d19c3151..866e262f0f0a 100644 --- a/test/cmocka/src/audio/component/CMakeLists.txt +++ b/test/cmocka/src/audio/component/CMakeLists.txt @@ -19,4 +19,6 @@ cmocka_test(comp_set_state ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-schedule.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ) diff --git a/test/cmocka/src/audio/eq_fir/CMakeLists.txt b/test/cmocka/src/audio/eq_fir/CMakeLists.txt index 547cb7be9642..3059f45956ab 100644 --- a/test/cmocka/src/audio/eq_fir/CMakeLists.txt +++ b/test/cmocka/src/audio/eq_fir/CMakeLists.txt @@ -31,6 +31,8 @@ add_library(audio_for_eq_fir STATIC ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c ${PROJECT_SOURCE_DIR}/src/audio/component.c ${PROJECT_SOURCE_DIR}/src/audio/data_blob.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c diff --git a/test/cmocka/src/audio/mixer/CMakeLists.txt b/test/cmocka/src/audio/mixer/CMakeLists.txt index 01aebc99223e..a16016f70044 100644 --- a/test/cmocka/src/audio/mixer/CMakeLists.txt +++ b/test/cmocka/src/audio/mixer/CMakeLists.txt @@ -24,6 +24,8 @@ cmocka_test(mixer ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-schedule.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/math/numbers.c ) target_link_libraries(mixer PRIVATE -lm) diff --git a/test/cmocka/src/audio/mux/CMakeLists.txt b/test/cmocka/src/audio/mux/CMakeLists.txt index c6f67ae89127..73451ba72458 100644 --- a/test/cmocka/src/audio/mux/CMakeLists.txt +++ b/test/cmocka/src/audio/mux/CMakeLists.txt @@ -18,6 +18,8 @@ add_library( ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/math/numbers.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c diff --git a/test/cmocka/src/audio/pcm_converter/CMakeLists.txt b/test/cmocka/src/audio/pcm_converter/CMakeLists.txt index 13adc77e000c..52f268a908c5 100644 --- a/test/cmocka/src/audio/pcm_converter/CMakeLists.txt +++ b/test/cmocka/src/audio/pcm_converter/CMakeLists.txt @@ -13,6 +13,8 @@ if(CONFIG_FORMAT_FLOAT) ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c ${PROJECT_SOURCE_DIR}/src/audio/component.c ${PROJECT_SOURCE_DIR}/src/audio/data_blob.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c diff --git a/test/cmocka/src/audio/pipeline/CMakeLists.txt b/test/cmocka/src/audio/pipeline/CMakeLists.txt index c8219517c19f..2f27d7cfcd74 100644 --- a/test/cmocka/src/audio/pipeline/CMakeLists.txt +++ b/test/cmocka/src/audio/pipeline/CMakeLists.txt @@ -29,6 +29,8 @@ cmocka_test(pipeline_new ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c @@ -51,6 +53,8 @@ cmocka_test(pipeline_connect_upstream ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c @@ -73,6 +77,8 @@ cmocka_test(pipeline_free ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c diff --git a/test/cmocka/src/audio/selector/CMakeLists.txt b/test/cmocka/src/audio/selector/CMakeLists.txt index 46be5bdac073..36c13759be6d 100644 --- a/test/cmocka/src/audio/selector/CMakeLists.txt +++ b/test/cmocka/src/audio/selector/CMakeLists.txt @@ -20,6 +20,8 @@ add_library(audio_for_selector STATIC ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c diff --git a/test/cmocka/src/audio/volume/CMakeLists.txt b/test/cmocka/src/audio/volume/CMakeLists.txt index f6530bc2b3b0..901bd3c2e4f2 100644 --- a/test/cmocka/src/audio/volume/CMakeLists.txt +++ b/test/cmocka/src/audio/volume/CMakeLists.txt @@ -28,6 +28,8 @@ add_library(audio_for_volume STATIC ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c diff --git a/test/cmocka/src/math/fft/CMakeLists.txt b/test/cmocka/src/math/fft/CMakeLists.txt index d21819848cd0..921698d04809 100644 --- a/test/cmocka/src/math/fft/CMakeLists.txt +++ b/test/cmocka/src/math/fft/CMakeLists.txt @@ -12,6 +12,8 @@ cmocka_test(fft ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index b4d729bada78..563dc6b14622 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -397,6 +397,9 @@ zephyr_library_sources( lib.c ) +# SOF module interface functions +add_subdirectory(../src/module module_unused_install/) + if(CONFIG_ZEPHYR_DP_SCHEDULER) zephyr_library_sources(${SOF_AUDIO_PATH}/dp_queue.c) endif()