From eb8625c5e4c853cbdc338640ffcc0f3e2157da20 Mon Sep 17 00:00:00 2001 From: Ievgen Ganakov Date: Mon, 22 Jul 2024 18:40:38 +0200 Subject: [PATCH] copier: gain: add dma control ipc handling Add methods to update gain coefficients in runtime by handling DMA CONTROL IPC message being sent to specific dai device based on provided node id. Check for unity gain flag. Signed-off-by: Ievgen Ganakov --- src/audio/copier/copier_gain.c | 76 +++++++++++++++++++++++++++++++ src/audio/copier/copier_gain.h | 43 +++++++++++++++++ src/audio/copier/copier_generic.c | 10 ++++ src/audio/copier/copier_hifi.c | 8 ++++ 4 files changed, 137 insertions(+) diff --git a/src/audio/copier/copier_gain.c b/src/audio/copier/copier_gain.c index 93b389b1404f..06fe92629b01 100644 --- a/src/audio/copier/copier_gain.c +++ b/src/audio/copier/copier_gain.c @@ -72,3 +72,79 @@ enum copier_gain_state copier_gain_eval_state(struct copier_gain_params *gain_pa return state; } + +int copier_gain_dma_control(uint32_t node_id, const uint32_t *config_data, + size_t config_size, enum sof_ipc_dai_type dai_type) +{ + struct ipc *ipc = ipc_get(); + struct ipc_comp_dev *icd; + struct comp_dev *dev; + struct list_item *clist; + + int ret; + + list_for_item(clist, &ipc->comp_list) { + struct gain_dma_control_data *gain_data = NULL; + + icd = container_of(clist, struct ipc_comp_dev, list); + + if (!icd || icd->type != COMP_TYPE_COMPONENT) + continue; + + dev = icd->cd; + + if (!dev || dev->ipc_config.type != SOF_COMP_DAI) + continue; + + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + + ret = copier_set_gain(dev, cd->dd[0], gain_data); + if (ret) + comp_err(dev, "Gain DMA control: failed to set gain"); + return ret; + } + + return -ENODEV; +} + +int copier_set_gain(struct comp_dev *dev, struct dai_data *dd, + struct gain_dma_control_data *gain_data) +{ + struct copier_gain_params *gain_params = dd->gain_data; + struct ipc4_copier_module_cfg *copier_cfg = dd->dai_spec_config; + const int channels = copier_cfg->base.audio_fmt.channels_count; + uint16_t static_gain[MAX_GAIN_COEFFS_CNT]; + int ret; + + if (!gain_data) { + comp_err(dev, "Gain data is NULL"); + return -EINVAL; + } + + /* Set gain coefficients */ + comp_info(dev, "Update gain coefficients from DMA_CONTROL ipc"); + + size_t gain_coef_size = channels * sizeof(uint16_t); + + ret = memcpy_s(static_gain, gain_coef_size, gain_data->gain_coeffs, + gain_coef_size); + if (ret) { + comp_err(dev, "memcpy_s failed with error %d", ret); + return ret; + } + + for (int i = channels; i < MAX_GAIN_COEFFS_CNT; i++) + static_gain[i] = static_gain[i % channels]; + + ret = memcpy_s(gain_params->gain_coeffs, sizeof(static_gain), + static_gain, sizeof(static_gain)); + if (ret) { + comp_err(dev, "memcpy_s failed with error %d", ret); + return ret; + } + + gain_params->unity_gain = copier_is_unity_gain(gain_params); + + return 0; +} diff --git a/src/audio/copier/copier_gain.h b/src/audio/copier/copier_gain.h index bf2b7b6eae14..0ec6e3a502a7 100644 --- a/src/audio/copier/copier_gain.h +++ b/src/audio/copier/copier_gain.h @@ -101,6 +101,15 @@ struct copier_gain_params { uint16_t channels_count; /**< Number of channels */ }; +/** Gain Coefficients IO Control + * + * This parameter is sent by the driver to add/modify a static gain. + * Coefficients are encoded in Q10 format. + */ +struct gain_dma_control_data { + uint16_t gain_coeffs[MAX_GAIN_COEFFS_CNT]; +} __packed __aligned(4); + /** * @brief Sets gain parameters. * @@ -196,4 +205,38 @@ int copier_gain_input(struct comp_dev *dev, struct comp_buffer *buff, */ enum copier_gain_state copier_gain_eval_state(struct copier_gain_params *gain_params); +/** + * Sets/modify gain for a copier module in runtime. + * + * @param dev The copier device structure. + * @param dd The DAI data structure. + * @param gain_data The gain control data structure. + * @return 0 on success, otherwise a negative error code. + */ +int copier_set_gain(struct comp_dev *dev, struct dai_data *dd, + struct gain_dma_control_data *gain_data); + +/** + * Checks for unity gain mode. + * + * @param gain_params The copier gain parameters structure. + * @return true if the gain is set to unity gain, false otherwise. + */ +bool copier_is_unity_gain(struct copier_gain_params *gain_params); + +/** + * Controls the gain for a copier device using DMA Control IPC message. + * + * This function retrieves gain data from the DMA Control IPC message and updates + * corresponding dai device gain params structure. + * + * @param node_id Gateway node id. + * @param config_data The gain configuration data. + * @param config_size The size of the gain configuration data. + * @param dai_type The type of the DAI device. + * @return 0 on success, otherwise a negative error code. + */ +int copier_gain_dma_control(uint32_t node_id, const uint32_t *config_data, + size_t config_size, enum sof_ipc_dai_type dai_type); + #endif /* __SOF_COPIER_GAIN_H__ */ diff --git a/src/audio/copier/copier_generic.c b/src/audio/copier/copier_generic.c index 31e9c5405146..fef8b53f462f 100644 --- a/src/audio/copier/copier_generic.c +++ b/src/audio/copier/copier_generic.c @@ -289,6 +289,16 @@ int copier_gain_input32(struct comp_buffer *buff, enum copier_gain_state state, return 0; } +bool copier_is_unity_gain(struct copier_gain_params *gain_params) +{ + /* Set unity gain flag */ + for (int i = 0; i < MAX_GAIN_COEFFS_CNT; i++) { + if (gain_params->gain_coeffs[i] != UNITY_GAIN_GENERIC) + return false; + } + return true; +} + #endif void copier_update_params(struct copier_data *cd, struct comp_dev *dev, diff --git a/src/audio/copier/copier_hifi.c b/src/audio/copier/copier_hifi.c index 84f9c4598230..4651b8cdd339 100644 --- a/src/audio/copier/copier_hifi.c +++ b/src/audio/copier/copier_hifi.c @@ -415,4 +415,12 @@ int copier_gain_input32(struct comp_buffer *buff, enum copier_gain_state state, return 0; } +bool copier_is_unity_gain(struct copier_gain_params *gain_params) +{ + ae_int16x4 gain_coeffs = AE_MOVF16X4_FROMINT64(UNITY_GAIN_4X_Q10); + xtbool4 unity_gain_check = AE_EQ16(gain_params->gain_coeffs[0], gain_coeffs); + + return XT_ALL4(unity_gain_check) ? true : false; +} + #endif