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 <ranjani.sridharan@linux.intel.com>
This commit is contained in:
Ranjani Sridharan 2022-06-15 15:14:14 -07:00 committed by Liam Girdwood
parent e0935332f2
commit 9966556105
2 changed files with 138 additions and 0 deletions

View File

@ -4,6 +4,7 @@
//
// Author: Jyri Sarha <jyri.sarha@intel.com>
#include <sof/audio/module_adapter/module/generic.h>
#include <sof/sof.h>
#include <sof/lib/alloc.h>
#include <ipc/topology.h>
@ -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)
{

View File

@ -8,6 +8,7 @@
#ifndef __SOF_AUDIO_DATA_BLOB_H__
#define __SOF_AUDIO_DATA_BLOB_H__
#include <sof/audio/module_adapter/module/generic.h>
#include <sof/sof.h>
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