From c53d745e0acabd8c915e1604ba58616be6fdeeb5 Mon Sep 17 00:00:00 2001 From: Jaska Uimonen Date: Wed, 6 Feb 2019 09:43:58 +0200 Subject: [PATCH] eq: make fir to receive large blobs in parts Use ctrl data message id to receive and send large binary blobs over ipc. When first message arrives, reserve memory for the whole blob. Signed-off-by: Jaska Uimonen --- src/audio/eq_fir.c | 82 +++++++++++++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 27 deletions(-) diff --git a/src/audio/eq_fir.c b/src/audio/eq_fir.c index 643f034ac..6c5e19647 100644 --- a/src/audio/eq_fir.c +++ b/src/audio/eq_fir.c @@ -334,7 +334,7 @@ static int eq_fir_setup(struct comp_data *cd, int nch) return 0; /* Allocate all FIR channels data in a big chunk and clear it */ - cd->fir_delay = rzalloc(RZONE_RUNTIME, SOF_MEM_CAPS_RAM, size_sum); + cd->fir_delay = rballoc(RZONE_RUNTIME, SOF_MEM_CAPS_RAM, size_sum); if (!cd->fir_delay) { trace_eq_error("eq_fir_setup() error: alloc failed, size = %u", size_sum); @@ -421,7 +421,7 @@ static struct comp_dev *eq_fir_new(struct sof_ipc_comp *comp) * the EQ is configured later in run-time the size is zero. */ if (bs) { - cd->config = rzalloc(RZONE_RUNTIME, SOF_MEM_CAPS_RAM, bs); + cd->config = rballoc(RZONE_RUNTIME, SOF_MEM_CAPS_RAM, bs); if (!cd->config) { rfree(dev); rfree(cd); @@ -491,7 +491,8 @@ static int fir_cmd_get_data(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata, int max_size) { struct comp_data *cd = comp_get_drvdata(dev); - + unsigned char *dst, *src; + size_t offset; size_t bs; int ret = 0; @@ -499,17 +500,29 @@ static int fir_cmd_get_data(struct comp_dev *dev, case SOF_CTRL_CMD_BINARY: trace_eq("fir_cmd_get_data(), SOF_CTRL_CMD_BINARY"); + max_size -= sizeof(struct sof_ipc_ctrl_data) + + sizeof(struct sof_abi_hdr); + /* Copy back to user space */ if (cd->config) { + src = (unsigned char *)cd->config; + dst = (unsigned char *)cdata->data->data; bs = cd->config->size; - if (bs > SOF_EQ_FIR_MAX_SIZE || bs == 0 || - bs > max_size) - return -EINVAL; - ret = memcpy_s(cdata->data->data, - ((struct sof_abi_hdr *) - (cdata->data))->size, - cd->config, bs); - + cdata->elems_remaining = 0; + offset = 0; + if (bs > max_size) { + bs = (cdata->msg_index + 1) * max_size > bs ? + bs - cdata->msg_index * max_size : + max_size; + offset = cdata->msg_index * max_size; + cdata->elems_remaining = cd->config->size - + offset; + } + cdata->num_elems = bs; + trace_eq("fir_cmd_get_data(), blob size %zu " + "msg index %u max size %u offset %zu", bs, + cdata->msg_index, max_size, offset); + memcpy(dst, src + offset, bs); cdata->data->abi = SOF_ABI_VERSION; cdata->data->size = bs; } else { @@ -531,8 +544,8 @@ static int fir_cmd_set_data(struct comp_dev *dev, { struct comp_data *cd = comp_get_drvdata(dev); struct sof_ipc_ctrl_value_comp *compv; - struct sof_eq_fir_config *cfg; - size_t bs; + unsigned char *dst, *src; + uint32_t offset; int i; int ret = 0; @@ -580,28 +593,43 @@ static int fir_cmd_set_data(struct comp_dev *dev, return -EBUSY; } - /* Check and free old config */ - eq_fir_free_parameters(&cd->config); - /* Copy new config, find size from header */ - cfg = (struct sof_eq_fir_config *)cdata->data->data; - bs = cfg->size; - trace_eq("fir_cmd_set_data(): blob size: %u", bs); - if (bs > SOF_EQ_FIR_MAX_SIZE || bs == 0) + trace_eq("fir_cmd_set_data(): blob size: %u msg_index %u", + cdata->num_elems + cdata->elems_remaining, + cdata->msg_index); + if (cdata->num_elems + cdata->elems_remaining > + SOF_EQ_FIR_MAX_SIZE) return -EINVAL; - /* Allocate buffer for copy of the blob. */ - cd->config = rzalloc(RZONE_RUNTIME, SOF_MEM_CAPS_RAM, bs); - if (!cd->config) { - trace_eq_error("fir_cmd_set_data() error: " - "buffer allocation failed"); - return -EINVAL; + if (cdata->msg_index == 0) { + /* Check and free old config */ + eq_fir_free_parameters(&cd->config); + + /* Allocate buffer for copy of the blob. */ + cd->config = rballoc(RZONE_RUNTIME, SOF_MEM_CAPS_RAM, + cdata->num_elems + + cdata->elems_remaining); + + if (!cd->config) { + trace_eq_error("fir_cmd_set_data() error: " + "buffer allocation failed"); + return -EINVAL; + } + offset = 0; + } else { + offset = cd->config->size - cdata->elems_remaining - + cdata->num_elems; } + dst = (unsigned char *)cd->config; + src = (unsigned char *)cdata->data->data; + /* Just copy the configuration. The EQ will be initialized in * prepare(). */ - ret = memcpy_s(cd->config, bs, cfg, bs); + memcpy(dst + offset, src, cdata->num_elems); + + /* we can check data when elems_remaining == 0 */ break; default: trace_eq_error("fir_cmd_set_data() error: invalid cdata->cmd");