From 99665561059b0c6f9d806772b4bddfdc0297f65c Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 15 Jun 2022 15:14:14 -0700 Subject: [PATCH] data_blob: Introduce a new helper for setting the blob Introduce a new helper function to set the blob to be used with the module adapter set_configuration op. When all modules are converted to use the new op, the comp_data_blob_set_cmd() can be removed. Signed-off-by: Ranjani Sridharan --- src/audio/data_blob.c | 124 ++++++++++++++++++++++++++++++ src/include/sof/audio/data_blob.h | 14 ++++ 2 files changed, 138 insertions(+) diff --git a/src/audio/data_blob.c b/src/audio/data_blob.c index 67d924d88..a2bedeecb 100644 --- a/src/audio/data_blob.c +++ b/src/audio/data_blob.c @@ -4,6 +4,7 @@ // // Author: Jyri Sarha +#include #include #include #include @@ -148,6 +149,129 @@ int comp_init_data_blob(struct comp_data_blob_handler *blob_handler, return 0; } +int comp_data_blob_set(struct comp_data_blob_handler *blob_handler, + enum module_cfg_fragment_position pos, uint32_t data_offset_size, + const uint8_t *fragment, size_t fragment_size) +{ + int ret; + + if (!blob_handler) + return -EINVAL; + + comp_dbg(blob_handler->dev, "comp_data_blob_set_cmd() pos = %d, fragment size = %d", + pos, fragment_size); + + /* Check that there is no work-in-progress previous request */ + if (blob_handler->data_new && + (pos == MODULE_CFG_FRAGMENT_FIRST || pos == MODULE_CFG_FRAGMENT_SINGLE)) { + 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 (pos == MODULE_CFG_FRAGMENT_FIRST || pos == MODULE_CFG_FRAGMENT_SINGLE) { + /* 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 (!fragment_size) + return 0; + + if (blob_handler->single_blob) { + if (data_offset_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(data_offset_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 = data_offset_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, + fragment, fragment_size); + if (ret) { + comp_err(blob_handler->dev, "comp_data_blob_set_cmd(): failed to copy fragment"); + return ret; + } + + blob_handler->data_pos += fragment_size; + + if (pos == MODULE_CFG_FRAGMENT_SINGLE || pos == MODULE_CFG_FRAGMENT_LAST) { + 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_set_cmd(struct comp_data_blob_handler *blob_handler, struct sof_ipc_ctrl_data *cdata) { diff --git a/src/include/sof/audio/data_blob.h b/src/include/sof/audio/data_blob.h index 9b8575395..034554443 100644 --- a/src/include/sof/audio/data_blob.h +++ b/src/include/sof/audio/data_blob.h @@ -8,6 +8,7 @@ #ifndef __SOF_AUDIO_DATA_BLOB_H__ #define __SOF_AUDIO_DATA_BLOB_H__ +#include #include struct comp_dev; @@ -62,6 +63,19 @@ int comp_init_data_blob(struct comp_data_blob_handler *blob_handler, */ int comp_data_blob_set_cmd(struct comp_data_blob_handler *blob_handler, struct sof_ipc_ctrl_data *cdata); + +/** + * Handles IPC set command. + * + * @param blob_handler: Data blob handler + * @param pos position: of the data fragment + * @param data_offset_size: offset of the fragment in the whole data + * @param fragment: pointer to the fragment data + * @param fragment_size: size of the fragment data + */ +int comp_data_blob_set(struct comp_data_blob_handler *blob_handler, + enum module_cfg_fragment_position pos, uint32_t data_offset_size, + const uint8_t *fragment, size_t fragment_size); /** * Handles IPC get command. * @param blob_handler Data blob handler