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 {