From 9cdef9fc13bb214afce77e09accf7ec6807453cb Mon Sep 17 00:00:00 2001 From: Ievgen Ganakov Date: Tue, 23 Jul 2024 11:06:38 +0200 Subject: [PATCH] copier: dmic: enable gain for dmic dai Enable gain for DMIC interface. Configure gain feature with parameters received in DMIC BLOB. Add support for runtime DMIC gain parameters update using DMA Control IPC. Signed-off-by: Ievgen Ganakov --- src/audio/base_fw.c | 2 +- src/audio/base_fw_intel.c | 13 ++++++++ src/audio/copier/copier_dai.c | 3 ++ src/audio/copier/copier_gain.c | 55 ++++++++++++++++++++++++++++++++-- src/audio/copier/copier_gain.h | 4 +-- src/include/ipc4/base_fw.h | 2 +- 6 files changed, 73 insertions(+), 6 deletions(-) diff --git a/src/audio/base_fw.c b/src/audio/base_fw.c index 6820d54364b2..a6e5394f3618 100644 --- a/src/audio/base_fw.c +++ b/src/audio/base_fw.c @@ -588,7 +588,7 @@ static int basefw_dma_control(bool first_block, } dma_control = (struct ipc4_dma_control *)data; - data_size = data_offset - (sizeof(struct ipc4_dma_control) - sizeof(uint32_t)); + data_size = data_offset - sizeof(struct ipc4_dma_control); if (data_size < (dma_control->config_length * sizeof(uint32_t))) { tr_err(&ipc_tr, "DMA Control data too short: got %u, expected %u", diff --git a/src/audio/base_fw_intel.c b/src/audio/base_fw_intel.c index ff22b16ea9d3..520894ec2d0a 100644 --- a/src/audio/base_fw_intel.c +++ b/src/audio/base_fw_intel.c @@ -9,6 +9,7 @@ #include #include #include +#include #if defined(CONFIG_SOC_SERIES_INTEL_ADSP_ACE) #include @@ -24,6 +25,7 @@ #include #include +#include "copier/copier_gain.h" struct ipc4_modules_info { uint32_t modules_count; @@ -353,7 +355,18 @@ int basefw_vendor_dma_control(uint32_t node_id, const char *config_data, size_t tr_info(&basefw_comp_tr, "node_id 0x%x, config_data 0x%x, data_size %u", node_id, (uint32_t)config_data, data_size); + switch (node.f.dma_type) { + case ipc4_dmic_link_input_class: + /* In DMIC case we don't need to update zephyr dai params */ + ret = copier_gain_dma_control(node, config_data, data_size, + SOF_DAI_INTEL_DMIC); + if (ret) { + tr_err(&basefw_comp_tr, + "Failed to update copier gain coefs, error: %d", ret); + return IPC4_INVALID_REQUEST; + } + return IPC4_SUCCESS; case ipc4_i2s_link_output_class: case ipc4_i2s_link_input_class: type = DAI_INTEL_SSP; diff --git a/src/audio/copier/copier_dai.c b/src/audio/copier/copier_dai.c index c1f748d5eeb4..f79c2b225255 100644 --- a/src/audio/copier/copier_dai.c +++ b/src/audio/copier/copier_dai.c @@ -322,6 +322,9 @@ int copier_dai_create(struct comp_dev *dev, struct copier_data *cd, return -EINVAL; } dai.out_fmt = &copier->out_fmt; +#if CONFIG_COPIER_GAIN + dai.apply_gain = true; +#endif break; default: return -EINVAL; diff --git a/src/audio/copier/copier_gain.c b/src/audio/copier/copier_gain.c index 06fe92629b01..f7e2f24fdb8d 100644 --- a/src/audio/copier/copier_gain.c +++ b/src/audio/copier/copier_gain.c @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include "copier.h" #include "copier_gain.h" @@ -26,6 +28,31 @@ int copier_gain_set_params(struct comp_dev *dev, struct dai_data *dd) /* Set basic gain parameters */ copier_gain_set_basic_params(dev, dd, ipc4_cfg); + switch (dd->dai->type) { + case SOF_DAI_INTEL_DMIC: + { + struct dmic_config_data *dmic_cfg = cd->gtw_cfg; + + if (!dmic_cfg) { + comp_err(dev, "No dmic config found"); + return -EINVAL; + } + + union dmic_global_cfg *dmic_glb_cfg = &dmic_cfg->dmic_blob.global_cfg; + + /* Get fade period from DMIC blob */ + fade_period = dmic_glb_cfg->ext_global_cfg.fade_in_period; + /* Convert and assign silence and fade length values */ + dd->gain_data->silence_sg_length = + frames * dmic_glb_cfg->ext_global_cfg.silence_period; + dd->gain_data->fade_sg_length = frames * fade_period; + } + break; + default: + comp_info(dev, "Apply default fade period for dai type %d", dd->dai->type); + break; + } + /* Set fade parameters */ ret = copier_gain_set_fade_params(dev, dd, ipc4_cfg, fade_period, frames); if (ret) @@ -73,18 +100,19 @@ 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, +int copier_gain_dma_control(union ipc4_connector_node_id node, const char *config_data, size_t config_size, enum sof_ipc_dai_type dai_type) { + struct sof_tlv *tlv = (struct sof_tlv *)config_data; 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; + void *tlv_val = NULL; icd = container_of(clist, struct ipc_comp_dev, list); @@ -99,6 +127,29 @@ int copier_gain_dma_control(uint32_t node_id, const uint32_t *config_data, struct processing_module *mod = comp_mod(dev); struct copier_data *cd = module_get_private_data(mod); + switch (dai_type) { + case SOF_DAI_INTEL_DMIC: + if (cd->dd[0]->dai->index != node.f.v_index) + continue; + + if (!config_size) { + comp_err(dev, "Config length for DMIC couldn't be zero"); + return -EINVAL; + } + + /* Gain coefficients for DMIC */ + tlv_val = tlv_value_ptr_get(tlv, DMIC_SET_GAIN_COEFFICIENTS); + if (!tlv_val) { + comp_err(dev, "No gain coefficients in DMA_CONTROL ipc"); + return -EINVAL; + } + gain_data = tlv_val; + break; + default: + comp_warn(dev, "Gain DMA control: no dai type=%d found", dai_type); + break; + } + ret = copier_set_gain(dev, cd->dd[0], gain_data); if (ret) comp_err(dev, "Gain DMA control: failed to set gain"); diff --git a/src/audio/copier/copier_gain.h b/src/audio/copier/copier_gain.h index 0ec6e3a502a7..fd2132765ad8 100644 --- a/src/audio/copier/copier_gain.h +++ b/src/audio/copier/copier_gain.h @@ -230,13 +230,13 @@ bool copier_is_unity_gain(struct copier_gain_params *gain_params); * 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 node 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, +int copier_gain_dma_control(union ipc4_connector_node_id node, const char *config_data, size_t config_size, enum sof_ipc_dai_type dai_type); #endif /* __SOF_COPIER_GAIN_H__ */ diff --git a/src/include/ipc4/base_fw.h b/src/include/ipc4/base_fw.h index b1367971ffcb..ab98fad44160 100644 --- a/src/include/ipc4/base_fw.h +++ b/src/include/ipc4/base_fw.h @@ -485,7 +485,7 @@ struct ipc4_astate_table { struct ipc4_dma_control { uint32_t node_id; uint32_t config_length; - uint32_t config_data[1]; + uint32_t config_data[0]; } __attribute__((packed, aligned(4))); enum ipc4_perf_measurements_state_set {