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