diff --git a/src/audio/CMakeLists.txt b/src/audio/CMakeLists.txt index e5275e2359c8..0cc27656c833 100644 --- a/src/audio/CMakeLists.txt +++ b/src/audio/CMakeLists.txt @@ -4,6 +4,7 @@ if(NOT CONFIG_LIBRARY) add_local_sources(sof host.c component.c + data_blob.c buffer.c channel_map.c ) @@ -137,6 +138,7 @@ subdirs(pipeline) add_local_sources(sof component.c + data_blob.c buffer.c ) diff --git a/src/audio/component.c b/src/audio/component.c index 898abe2376ec..df4c561d612a 100644 --- a/src/audio/component.c +++ b/src/audio/component.c @@ -156,304 +156,6 @@ void comp_get_copy_limits(struct comp_buffer *source, struct comp_buffer *sink, cl->sink_bytes = cl->frames * cl->sink_frame_bytes; } -/** \brief Struct handler for large component configs */ -struct comp_data_blob_handler { - struct comp_dev *dev; /**< audio component device */ - uint32_t data_size; /**< size of component's data blob */ - uint32_t new_data_size; /**< size of component's new data blob */ - void *data; /**< pointer to data blob */ - void *data_new; /**< pointer to new data blob */ - bool data_ready; /**< set when data blob is fully received */ - uint32_t data_pos; /**< indicates a data position in data - * sending/receiving process - */ -}; - -static void comp_free_data_blob(struct comp_data_blob_handler *blob_handler) -{ - assert(blob_handler); - - if (!blob_handler->data) - return; - - rfree(blob_handler->data); - rfree(blob_handler->data_new); - blob_handler->data = NULL; - blob_handler->data_new = NULL; - blob_handler->data_size = 0; -} - -void *comp_get_data_blob(struct comp_data_blob_handler *blob_handler, - size_t *size, uint32_t *crc) -{ - assert(blob_handler); - - comp_dbg(blob_handler->dev, "comp_get_data_blob()"); - - if (size) - *size = 0; - - /* Function returns new data blob if available */ - if (comp_is_new_data_blob_available(blob_handler)) { - comp_dbg(blob_handler->dev, "comp_get_data_blob(): new data available"); - - /* Free "old" data blob and set data to data_new pointer */ - rfree(blob_handler->data); - blob_handler->data = blob_handler->data_new; - blob_handler->data_size = blob_handler->new_data_size; - - blob_handler->data_new = NULL; - blob_handler->data_ready = false; - blob_handler->new_data_size = 0; - blob_handler->data_pos = 0; - } - - /* If data is available we calculate crc32 when crc pointer is given */ - if (blob_handler->data) { - if (crc) - *crc = crc32(0, blob_handler->data, - blob_handler->data_size); - } else { - /* If blob_handler->data is equal to NULL and there is no new - * data blob it means that component hasn't got any config yet. - * Function returns NULL in that case. - */ - comp_warn(blob_handler->dev, "comp_get_data_blob(): blob_handler->data is not set."); - } - - if (size) - *size = blob_handler->data_size; - - return blob_handler->data; -} - -bool comp_is_new_data_blob_available(struct comp_data_blob_handler - *blob_handler) -{ - assert(blob_handler); - - comp_dbg(blob_handler->dev, "comp_is_new_data_blob_available()"); - - /* New data blob is available when new data blob is allocated (data_new - * is not NULL), and the component has received all required chunks of data - * (data_ready is set to TRUE) - */ - if (blob_handler->data_new && blob_handler->data_ready) - return true; - - return false; -} - -int comp_init_data_blob(struct comp_data_blob_handler *blob_handler, - uint32_t size, void *init_data) -{ - int ret; - - assert(blob_handler); - - comp_free_data_blob(blob_handler); - - if (!size) - return 0; - - /* Data blob allocation */ - blob_handler->data = rballoc(0, SOF_MEM_CAPS_RAM, size); - if (!blob_handler->data) { - comp_err(blob_handler->dev, "comp_init_data_blob(): model->data rballoc failed"); - return -ENOMEM; - } - - /* If init_data is given, data will be initialized with it. In other - * case, data will be set to zero. - */ - if (init_data) { - ret = memcpy_s(blob_handler->data, size, init_data, size); - assert(!ret); - } else { - bzero(blob_handler->data, size); - } - - blob_handler->data_new = NULL; - blob_handler->data_size = size; - blob_handler->new_data_size = 0; - - return 0; -} - -int comp_data_blob_set_cmd(struct comp_data_blob_handler *blob_handler, - struct sof_ipc_ctrl_data *cdata) -{ - int ret = 0; - - assert(blob_handler); - - comp_dbg(blob_handler->dev, "comp_data_blob_set_cmd() msg_index = %d, num_elems = %d, remaining = %d ", - cdata->msg_index, cdata->num_elems, - cdata->elems_remaining); - - /* Check that there is no work-in-progress previous request */ - if (blob_handler->data_new && cdata->msg_index == 0) { - comp_err(blob_handler->dev, "comp_data_blob_set_cmd(), busy with previous request"); - return -EBUSY; - } - - /* in case when the current package is the first, we should allocate - * memory for whole model data - */ - if (!cdata->msg_index) { - /* in case when required model size is equal to zero we do not - * allocate memory and should just return 0. - * - * Set cmd with cdata->data->size equal to 0 is possible in - * following situation: - * 1. At first boot and topology parsing stage, the driver will - * read all initial values of DSP kcontrols via IPC. Driver send - * get_model() cmd to components. If we do not initialize - * component earlier driver will get "model" with size 0. - * 2. When resuming from runtime suspended, the driver will - * restore all pipelines and kcontrols, for the tlv binary - * kcontrols, it will call the set_model() with the cached value - * and size (0 if it is not updated by any actual end user - * sof-ctl settings) - basically driver will send set_model() - * command with size equal to 0. - */ - if (!cdata->data->size) - return 0; - - blob_handler->data_new = rballoc(0, SOF_MEM_CAPS_RAM, - cdata->data->size); - if (!blob_handler->data_new) { - comp_err(blob_handler->dev, "comp_data_blob_set_cmd(): blob_handler->data_new allocation failed."); - return -ENOMEM; - } - - blob_handler->new_data_size = cdata->data->size; - blob_handler->data_ready = false; - blob_handler->data_pos = 0; - } - - /* return an error in case when we do not have allocated memory for - * model data - */ - if (!blob_handler->data_new) { - comp_err(blob_handler->dev, "comp_data_blob_set_cmd(): buffer not allocated"); - return -ENOMEM; - } - - ret = memcpy_s((char *)blob_handler->data_new + blob_handler->data_pos, - blob_handler->new_data_size - blob_handler->data_pos, - cdata->data->data, cdata->num_elems); - assert(!ret); - - blob_handler->data_pos += cdata->num_elems; - - if (!cdata->elems_remaining) { - comp_dbg(blob_handler->dev, "comp_data_blob_set_cmd(): final package received"); - - /* If component state is READY we can omit old - * configuration immediately. When in playback/capture - * the new configuration presence is checked in copy(). - */ - if (blob_handler->dev->state == COMP_STATE_READY) { - rfree(blob_handler->data); - blob_handler->data = NULL; - } - - /* If there is no existing configuration the received - * can be set to current immediately. It will be - * applied in prepare() when streaming starts. - */ - if (!blob_handler->data) { - blob_handler->data = blob_handler->data_new; - blob_handler->data_size = blob_handler->new_data_size; - - blob_handler->data_new = NULL; - - /* The new configuration has been applied */ - blob_handler->data_ready = false; - blob_handler->new_data_size = 0; - blob_handler->data_pos = 0; - } else { - /* The new configuration is ready to be applied */ - blob_handler->data_ready = true; - } - } - - return 0; -} - -int comp_data_blob_get_cmd(struct comp_data_blob_handler *blob_handler, - struct sof_ipc_ctrl_data *cdata, int size) -{ - int ret = 0; - - assert(blob_handler); - - comp_dbg(blob_handler->dev, "comp_data_blob_get_cmd() msg_index = %d, num_elems = %d, remaining = %d ", - cdata->msg_index, cdata->num_elems, - cdata->elems_remaining); - - /* Copy back to user space */ - if (blob_handler->data) { - /* reset data_pos variable in case of copying first element */ - if (!cdata->msg_index) { - blob_handler->data_pos = 0; - comp_dbg(blob_handler->dev, "comp_data_blob_get_cmd() model data_size = 0x%x", - blob_handler->data_size); - } - - /* return an error in case of mismatch between num_elems and - * required size - */ - if (cdata->num_elems > size) { - comp_err(blob_handler->dev, "comp_data_blob_get_cmd(): invalid cdata->num_elems %d", - cdata->num_elems); - return -EINVAL; - } - - /* copy required size of data */ - ret = memcpy_s(cdata->data->data, size, - (char *)blob_handler->data + blob_handler->data_pos, - cdata->num_elems); - assert(!ret); - - cdata->data->abi = SOF_ABI_VERSION; - cdata->data->size = blob_handler->data_size; - blob_handler->data_pos += cdata->num_elems; - } else { - comp_warn(blob_handler->dev, "comp_data_blob_get_cmd(): model->data not allocated yet."); - cdata->data->abi = SOF_ABI_VERSION; - cdata->data->size = 0; - } - - return ret; -} - -struct comp_data_blob_handler *comp_data_blob_handler_new(struct comp_dev *dev) -{ - struct comp_data_blob_handler *handler; - - comp_dbg(dev, "comp_data_blob_handler_new()"); - - handler = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - sizeof(struct comp_data_blob_handler)); - - if (handler) - handler->dev = dev; - - return handler; -} - -void comp_data_blob_handler_free(struct comp_data_blob_handler *blob_handler) -{ - if (!blob_handler) - return; - - comp_free_data_blob(blob_handler); - - rfree(blob_handler); -} - struct comp_dev *comp_make_shared(struct comp_dev *dev) { struct list_item *old_bsource_list = &dev->bsource_list; diff --git a/src/audio/data_blob.c b/src/audio/data_blob.c new file mode 100644 index 000000000000..39b365228cfc --- /dev/null +++ b/src/audio/data_blob.c @@ -0,0 +1,359 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Jyri Sarha + +#include +#include +#include +#include +#include +#include + +/** \brief Struct handler for large component configs */ +struct comp_data_blob_handler { + struct comp_dev *dev; /**< audio component device */ + uint32_t data_size; /**< size of component's data blob */ + uint32_t new_data_size; /**< size of component's new data blob */ + void *data; /**< pointer to data blob */ + void *data_new; /**< pointer to new data blob */ + bool data_ready; /**< set when data blob is fully received */ + uint32_t data_pos; /**< indicates a data position in data + * sending/receiving process + */ + uint32_t single_blob:1; /**< Allocate only one blob. Module can not + * be active while reconfguring. + */ + void *(*alloc)(size_t size); /**< alternate allocator, maybe null */ + void (*free)(void *buf); /**< alternate free(), maybe null */ +}; + +static void comp_free_data_blob(struct comp_data_blob_handler *blob_handler) +{ + assert(blob_handler); + + if (!blob_handler->data) + return; + + blob_handler->free(blob_handler->data); + blob_handler->free(blob_handler->data_new); + blob_handler->data = NULL; + blob_handler->data_new = NULL; + blob_handler->data_size = 0; +} + +void *comp_get_data_blob(struct comp_data_blob_handler *blob_handler, + size_t *size, uint32_t *crc) +{ + assert(blob_handler); + + comp_dbg(blob_handler->dev, "comp_get_data_blob()"); + + if (size) + *size = 0; + + /* Function returns new data blob if available */ + if (comp_is_new_data_blob_available(blob_handler)) { + comp_dbg(blob_handler->dev, "comp_get_data_blob(): new data available"); + + /* Free "old" data blob and set data to data_new pointer */ + blob_handler->free(blob_handler->data); + blob_handler->data = blob_handler->data_new; + blob_handler->data_size = blob_handler->new_data_size; + + blob_handler->data_new = NULL; + blob_handler->data_ready = false; + blob_handler->new_data_size = 0; + blob_handler->data_pos = 0; + } + + /* If data is available we calculate crc32 when crc pointer is given */ + if (blob_handler->data) { + if (crc) + *crc = crc32(0, blob_handler->data, + blob_handler->data_size); + } else { + /* If blob_handler->data is equal to NULL and there is no new + * data blob it means that component hasn't got any config yet. + * Function returns NULL in that case. + */ + comp_warn(blob_handler->dev, "comp_get_data_blob(): blob_handler->data is not set."); + } + + if (size) + *size = blob_handler->data_size; + + return blob_handler->data; +} + +bool comp_is_new_data_blob_available(struct comp_data_blob_handler + *blob_handler) +{ + assert(blob_handler); + + comp_dbg(blob_handler->dev, "comp_is_new_data_blob_available()"); + + /* New data blob is available when new data blob is allocated (data_new + * is not NULL), and the component has received all required chunks of data + * (data_ready is set to TRUE) + */ + if (blob_handler->data_new && blob_handler->data_ready) + return true; + + return false; +} + +bool comp_is_current_data_blob_valid(struct comp_data_blob_handler + *blob_handler) +{ + return !!blob_handler->data; +} + +int comp_init_data_blob(struct comp_data_blob_handler *blob_handler, + uint32_t size, void *init_data) +{ + int ret; + + assert(blob_handler); + + comp_free_data_blob(blob_handler); + + if (!size) + return 0; + + /* Data blob allocation */ + blob_handler->data = blob_handler->alloc(size); + if (!blob_handler->data) { + comp_err(blob_handler->dev, "comp_init_data_blob(): model->data allocation failed"); + return -ENOMEM; + } + + /* If init_data is given, data will be initialized with it. In other + * case, data will be set to zero. + */ + if (init_data) { + ret = memcpy_s(blob_handler->data, size, init_data, size); + assert(!ret); + } else { + bzero(blob_handler->data, size); + } + + blob_handler->data_new = NULL; + blob_handler->data_size = size; + blob_handler->new_data_size = 0; + + return 0; +} + +int comp_data_blob_set_cmd(struct comp_data_blob_handler *blob_handler, + struct sof_ipc_ctrl_data *cdata) +{ + int ret = 0; + + assert(blob_handler); + + comp_dbg(blob_handler->dev, "comp_data_blob_set_cmd() msg_index = %d, num_elems = %d, remaining = %d ", + cdata->msg_index, cdata->num_elems, + cdata->elems_remaining); + + /* Check that there is no work-in-progress previous request */ + if (blob_handler->data_new && cdata->msg_index == 0) { + comp_err(blob_handler->dev, "comp_data_blob_set_cmd(), busy with previous request"); + return -EBUSY; + } + + /* In single blob mode the component can not be reconfigured if + * the component is active. + */ + if (blob_handler->single_blob && + blob_handler->dev->state == COMP_STATE_ACTIVE) { + comp_err(blob_handler->dev, "comp_data_blob_set_cmd(), on the fly updates forbidden in single blob mode"); + return -EBUSY; + } + + /* in case when the current package is the first, we should allocate + * memory for whole model data + */ + if (!cdata->msg_index) { + /* in case when required model size is equal to zero we do not + * allocate memory and should just return 0. + * + * Set cmd with cdata->data->size equal to 0 is possible in + * following situation: + * 1. At first boot and topology parsing stage, the driver will + * read all initial values of DSP kcontrols via IPC. Driver send + * get_model() cmd to components. If we do not initialize + * component earlier driver will get "model" with size 0. + * 2. When resuming from runtime suspended, the driver will + * restore all pipelines and kcontrols, for the tlv binary + * kcontrols, it will call the set_model() with the cached value + * and size (0 if it is not updated by any actual end user + * sof-ctl settings) - basically driver will send set_model() + * command with size equal to 0. + */ + if (!cdata->data->size) + return 0; + + if (blob_handler->single_blob) { + if (cdata->data->size != blob_handler->data_size) { + blob_handler->free(blob_handler->data); + blob_handler->data = NULL; + } else { + blob_handler->data_new = blob_handler->data; + blob_handler->data = NULL; + } + } + + if (!blob_handler->data_new) { + blob_handler->data_new = + blob_handler->alloc(cdata->data->size); + if (!blob_handler->data_new) { + comp_err(blob_handler->dev, "comp_data_blob_set_cmd(): blob_handler->data_new allocation failed."); + return -ENOMEM; + } + } + + blob_handler->new_data_size = cdata->data->size; + blob_handler->data_ready = false; + blob_handler->data_pos = 0; + } + + /* return an error in case when we do not have allocated memory for + * model data + */ + if (!blob_handler->data_new) { + comp_err(blob_handler->dev, "comp_data_blob_set_cmd(): buffer not allocated"); + return -ENOMEM; + } + + ret = memcpy_s((char *)blob_handler->data_new + blob_handler->data_pos, + blob_handler->new_data_size - blob_handler->data_pos, + cdata->data->data, cdata->num_elems); + assert(!ret); + + blob_handler->data_pos += cdata->num_elems; + + if (!cdata->elems_remaining) { + comp_dbg(blob_handler->dev, "comp_data_blob_set_cmd(): final package received"); + + /* If component state is READY we can omit old + * configuration immediately. When in playback/capture + * the new configuration presence is checked in copy(). + */ + if (blob_handler->dev->state == COMP_STATE_READY) { + blob_handler->free(blob_handler->data); + blob_handler->data = NULL; + } + + /* If there is no existing configuration the received + * can be set to current immediately. It will be + * applied in prepare() when streaming starts. + */ + if (!blob_handler->data) { + blob_handler->data = blob_handler->data_new; + blob_handler->data_size = blob_handler->new_data_size; + + blob_handler->data_new = NULL; + + /* The new configuration has been applied */ + blob_handler->data_ready = false; + blob_handler->new_data_size = 0; + blob_handler->data_pos = 0; + } else { + /* The new configuration is ready to be applied */ + blob_handler->data_ready = true; + } + } + + return 0; +} + +int comp_data_blob_get_cmd(struct comp_data_blob_handler *blob_handler, + struct sof_ipc_ctrl_data *cdata, int size) +{ + int ret = 0; + + assert(blob_handler); + + comp_dbg(blob_handler->dev, "comp_data_blob_get_cmd() msg_index = %d, num_elems = %d, remaining = %d ", + cdata->msg_index, cdata->num_elems, + cdata->elems_remaining); + + /* Copy back to user space */ + if (blob_handler->data) { + /* reset data_pos variable in case of copying first element */ + if (!cdata->msg_index) { + blob_handler->data_pos = 0; + comp_dbg(blob_handler->dev, "comp_data_blob_get_cmd() model data_size = 0x%x", + blob_handler->data_size); + } + + /* return an error in case of mismatch between num_elems and + * required size + */ + if (cdata->num_elems > size) { + comp_err(blob_handler->dev, "comp_data_blob_get_cmd(): invalid cdata->num_elems %d", + cdata->num_elems); + return -EINVAL; + } + + /* copy required size of data */ + ret = memcpy_s(cdata->data->data, size, + (char *)blob_handler->data + blob_handler->data_pos, + cdata->num_elems); + assert(!ret); + + cdata->data->abi = SOF_ABI_VERSION; + cdata->data->size = blob_handler->data_size; + blob_handler->data_pos += cdata->num_elems; + } else { + comp_warn(blob_handler->dev, "comp_data_blob_get_cmd(): model->data not allocated yet."); + cdata->data->abi = SOF_ABI_VERSION; + cdata->data->size = 0; + } + + return ret; +} + +static void *default_alloc(size_t size) +{ + return rballoc(0, SOF_MEM_CAPS_RAM, size); +} + +static void default_free(void *buf) +{ + rfree(buf); +} + +struct comp_data_blob_handler * +comp_data_blob_handler_new_ext(struct comp_dev *dev, bool single_blob, + void *(*alloc)(size_t size), + void (*free)(void *buf)) +{ + struct comp_data_blob_handler *handler; + + comp_dbg(dev, "comp_data_blob_handler_new_ext()"); + + handler = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, + sizeof(struct comp_data_blob_handler)); + + if (handler) { + handler->dev = dev; + handler->single_blob = single_blob; + handler->alloc = alloc ? alloc : default_alloc; + handler->free = free ? free : default_free; + } + + return handler; +} + +void comp_data_blob_handler_free(struct comp_data_blob_handler *blob_handler) +{ + if (!blob_handler) + return; + + comp_free_data_blob(blob_handler); + + rfree(blob_handler); +} diff --git a/src/audio/drc/drc.c b/src/audio/drc/drc.c index 4ffa8cb8cb13..888a2718f32e 100644 --- a/src/audio/drc/drc.c +++ b/src/audio/drc/drc.c @@ -5,6 +5,7 @@ // Author: Pin-chih Lin #include +#include #include #include #include diff --git a/src/audio/eq_fir/eq_fir.c b/src/audio/eq_fir/eq_fir.c index 7ea2264e1954..7345156e80fe 100644 --- a/src/audio/eq_fir/eq_fir.c +++ b/src/audio/eq_fir/eq_fir.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/src/audio/eq_iir/eq_iir.c b/src/audio/eq_iir/eq_iir.c index ab6e9b3fcc30..3e5e45b01769 100644 --- a/src/audio/eq_iir/eq_iir.c +++ b/src/audio/eq_iir/eq_iir.c @@ -7,6 +7,7 @@ // Keyon Jie #include +#include #include #include #include diff --git a/src/audio/google_hotword_detect.c b/src/audio/google_hotword_detect.c index 916509d3842c..1cdd5b5131e7 100644 --- a/src/audio/google_hotword_detect.c +++ b/src/audio/google_hotword_detect.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include diff --git a/src/audio/google_rtc_audio_processing.c b/src/audio/google_rtc_audio_processing.c index 143485443ab8..e560c5be19e1 100644 --- a/src/audio/google_rtc_audio_processing.c +++ b/src/audio/google_rtc_audio_processing.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/src/audio/igo_nr/igo_nr.c b/src/audio/igo_nr/igo_nr.c index e9d752aad059..b6b8c062cc99 100755 --- a/src/audio/igo_nr/igo_nr.c +++ b/src/audio/igo_nr/igo_nr.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/src/audio/rtnr/rtnr.c b/src/audio/rtnr/rtnr.c index 9f1e741d7c7f..c61a656f75fb 100644 --- a/src/audio/rtnr/rtnr.c +++ b/src/audio/rtnr/rtnr.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include diff --git a/src/audio/tdfb/tdfb.c b/src/audio/tdfb/tdfb.c index b215cbd2d9f2..f32ed4f43943 100644 --- a/src/audio/tdfb/tdfb.c +++ b/src/audio/tdfb/tdfb.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/src/include/sof/audio/codec_adapter/codec/generic.h b/src/include/sof/audio/codec_adapter/codec/generic.h index 7afad17658bb..18c452490fc5 100644 --- a/src/include/sof/audio/codec_adapter/codec/generic.h +++ b/src/include/sof/audio/codec_adapter/codec/generic.h @@ -13,6 +13,7 @@ #define __SOF_AUDIO_CODEC_GENERIC__ #include +#include #include #include diff --git a/src/include/sof/audio/component.h b/src/include/sof/audio/component.h index aa87f2f3884c..4cc70c89fb61 100644 --- a/src/include/sof/audio/component.h +++ b/src/include/sof/audio/component.h @@ -841,72 +841,6 @@ static inline int comp_get_state(struct comp_dev *req_dev, struct comp_dev *dev) return dev->state; } -struct comp_data_blob_handler; - -/** - * Returns data blob. In case when new data blob is available it returns new - * one. Function returns also data blob size in case when size pointer is given. - * - * @param blob_handler Data blob handler - * @param size Pointer to data blob size variable - * @param crc Pointer to data blolb crc value - */ -void *comp_get_data_blob(struct comp_data_blob_handler *blob_handler, - size_t *size, uint32_t *crc); - -/** - * Checks whether new data blob is available. Function allows to check (even - * during streaming - in copy() function) whether new config is available and - * if it is, component can perform reconfiguration. - * - * @param blob_handler Data blob handler - */ -bool comp_is_new_data_blob_available(struct comp_data_blob_handler - *blob_handler); - -/** - * Initilizes data blob with given value. If init_data is not specified, - * function will zero data blob. - * - * @param blob_handler Data blob handler - * @param size Data blob size - * @param init_data Initial data blob values - */ -int comp_init_data_blob(struct comp_data_blob_handler *blob_handler, - uint32_t size, void *init_data); - -/** - * Handles IPC set command. - * - * @param blob_handler Data blob handler - * @param cdata IPC ctrl data - */ -int comp_data_blob_set_cmd(struct comp_data_blob_handler *blob_handler, - struct sof_ipc_ctrl_data *cdata); -/** - * Handles IPC get command. - * - * @param blob_handler Data blob handler - * @param cdata IPC ctrl data - * @param size Required size - */ -int comp_data_blob_get_cmd(struct comp_data_blob_handler *blob_handler, - struct sof_ipc_ctrl_data *cdata, int size); - -/** - * Returns new data blob handler. - * - * @param dev Component device - */ -struct comp_data_blob_handler *comp_data_blob_handler_new(struct comp_dev *dev); - -/** - * Free data blob handler. - * - * @param blob_handler Data blob handler - */ -void comp_data_blob_handler_free(struct comp_data_blob_handler *blob_handler); - /** * Called by component in params() function in order to set and update some of * downstream (playback) or upstream (capture) buffer parameters with pcm diff --git a/src/include/sof/audio/data_blob.h b/src/include/sof/audio/data_blob.h new file mode 100644 index 000000000000..9b8575395acb --- /dev/null +++ b/src/include/sof/audio/data_blob.h @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Jyri Sarha + */ + +#ifndef __SOF_AUDIO_DATA_BLOB_H__ +#define __SOF_AUDIO_DATA_BLOB_H__ + +#include + +struct comp_dev; + +struct comp_data_blob_handler; + +/** + * Returns data blob. In case when new data blob is available it returns new + * one. Function returns also data blob size in case when size pointer is given. + * + * @param blob_handler Data blob handler + * @param size Pointer to data blob size variable + * @param crc Pointer to data blolb crc value + */ +void *comp_get_data_blob(struct comp_data_blob_handler *blob_handler, + size_t *size, uint32_t *crc); + +/** + * Checks whether new data blob is available. Function allows to check (even + * during streaming - in copy() function) whether new config is available and + * if it is, component can perform reconfiguration. + * + * @param blob_handler Data blob handler + */ +bool comp_is_new_data_blob_available(struct comp_data_blob_handler + *blob_handler); + +/** + * Checks whether there is a valid data blob is available. + * + * @param blob_handler Data blob handler + */ +bool comp_is_current_data_blob_valid(struct comp_data_blob_handler + *blob_handler); + +/** + * Initializes data blob with given value. If init_data is not specified, + * function will zero data blob. + * + * @param blob_handler Data blob handler + * @param size Data blob size + * @param init_data Initial data blob values + */ +int comp_init_data_blob(struct comp_data_blob_handler *blob_handler, + uint32_t size, void *init_data); + +/** + * Handles IPC set command. + * + * @param blob_handler Data blob handler + * @param cdata IPC ctrl data + */ +int comp_data_blob_set_cmd(struct comp_data_blob_handler *blob_handler, + struct sof_ipc_ctrl_data *cdata); +/** + * Handles IPC get command. + * @param blob_handler Data blob handler + * @param cdata IPC ctrl data + * @param size Required size + */ +int comp_data_blob_get_cmd(struct comp_data_blob_handler *blob_handler, + struct sof_ipc_ctrl_data *cdata, int size); + +/** + * Returns new data blob handler. + * + * Data blob handler has two modes of operation, single_blob == false + * stands for double blob mode that allow seamless configuration + * updates on the fly. In single_blob == true mode there is at most + * one blob allocated at one time and configuration update is not + * allowed if the component is active. The single blob mode should be + * used with components with very big configuration blobs to save DSP + * memory. + * + * @param dev Component device + * @param single_blob Set true for single configuration blob operation + * @param alloc Optional blob memory allocator function pointer + * @param free Optional blob memory free function pointer + */ +struct comp_data_blob_handler * +comp_data_blob_handler_new_ext(struct comp_dev *dev, bool single_blob, + void *(*alloc)(size_t size), + void (*free)(void *buf)); + +/** + * Returns new data blob handler. + * + * This is a simplified version of comp_data_blob_handler_new_ext() using + * default memory allocator and double blob mode for on the fly updates. + * + * @param dev Component device + */ +static inline +struct comp_data_blob_handler *comp_data_blob_handler_new(struct comp_dev *dev) +{ + return comp_data_blob_handler_new_ext(dev, false, NULL, NULL); +} + +/** + * Free data blob handler. + * + * @param blob_handler Data blob handler + */ +void comp_data_blob_handler_free(struct comp_data_blob_handler *blob_handler); + +#endif /* __SOF_AUDIO_DATA_BLOB_H__ */ diff --git a/src/include/sof/audio/multiband_drc/multiband_drc.h b/src/include/sof/audio/multiband_drc/multiband_drc.h index fc9f1274a534..ae98aa785b14 100644 --- a/src/include/sof/audio/multiband_drc/multiband_drc.h +++ b/src/include/sof/audio/multiband_drc/multiband_drc.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include diff --git a/src/include/sof/samples/audio/smart_amp_test.h b/src/include/sof/samples/audio/smart_amp_test.h index 6bde3b7a9a42..4cf6de52a950 100644 --- a/src/include/sof/samples/audio/smart_amp_test.h +++ b/src/include/sof/samples/audio/smart_amp_test.h @@ -10,6 +10,7 @@ #include #include +#include #define SMART_AMP_MAX_STREAM_CHAN 8 diff --git a/src/samples/audio/detect_test.c b/src/samples/audio/detect_test.c index b809eb8cc8e7..3231ad1665cb 100644 --- a/src/samples/audio/detect_test.c +++ b/src/samples/audio/detect_test.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include diff --git a/test/cmocka/src/audio/component/CMakeLists.txt b/test/cmocka/src/audio/component/CMakeLists.txt index 7655d7513c2b..115f14d236eb 100644 --- a/test/cmocka/src/audio/component/CMakeLists.txt +++ b/test/cmocka/src/audio/component/CMakeLists.txt @@ -3,6 +3,7 @@ cmocka_test(comp_set_state comp_set_state.c ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/audio/data_blob.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/eq_iir/CMakeLists.txt b/test/cmocka/src/audio/eq_iir/CMakeLists.txt index ac9ae0c93aa6..62fb12e6cfe0 100644 --- a/test/cmocka/src/audio/eq_iir/CMakeLists.txt +++ b/test/cmocka/src/audio/eq_iir/CMakeLists.txt @@ -18,6 +18,7 @@ add_library(audio_for_eq_iir STATIC ${PROJECT_SOURCE_DIR}/src/math/iir_df2t_hifi3.c ${PROJECT_SOURCE_DIR}/src/audio/buffer.c ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/audio/data_blob.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/mux/CMakeLists.txt b/test/cmocka/src/audio/mux/CMakeLists.txt index 36e98f78f188..f5381566dd9a 100644 --- a/test/cmocka/src/audio/mux/CMakeLists.txt +++ b/test/cmocka/src/audio/mux/CMakeLists.txt @@ -12,6 +12,7 @@ add_library( ${PROJECT_SOURCE_DIR}/src/audio/mux/mux.c ${PROJECT_SOURCE_DIR}/src/audio/mux/mux_generic.c ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/audio/data_blob.c ${PROJECT_SOURCE_DIR}/src/audio/buffer.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 df08e29e256d..85d4d1b04928 100644 --- a/test/cmocka/src/audio/pcm_converter/CMakeLists.txt +++ b/test/cmocka/src/audio/pcm_converter/CMakeLists.txt @@ -7,6 +7,7 @@ if(CONFIG_FORMAT_FLOAT) ${PROJECT_SOURCE_DIR}/src/audio/pcm_converter/pcm_converter_generic.c ${PROJECT_SOURCE_DIR}/src/audio/buffer.c ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/audio/data_blob.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/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index a08ce761d326..ab3ae45826bd 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -502,6 +502,7 @@ zephyr_library_sources( ${SOF_AUDIO_PATH}/pcm_converter/pcm_converter_generic.c ${SOF_AUDIO_PATH}/buffer.c ${SOF_AUDIO_PATH}/component.c + ${SOF_AUDIO_PATH}/data_blob.c ${SOF_AUDIO_PATH}/pipeline/pipeline-graph.c ${SOF_AUDIO_PATH}/pipeline/pipeline-params.c ${SOF_AUDIO_PATH}/pipeline/pipeline-schedule.c