From 6b1f8233fd300b0c54d1331b92b345d0064b1b14 Mon Sep 17 00:00:00 2001 From: Ievgen Ganakov Date: Thu, 18 Jul 2024 17:07:51 +0200 Subject: [PATCH 1/2] ipc4: dmic: add dmic blob Define common IPC4 Dmic blob structures Signed-off-by: Ievgen Ganakov --- src/include/ipc4/dmic.h | 219 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 src/include/ipc4/dmic.h diff --git a/src/include/ipc4/dmic.h b/src/include/ipc4/dmic.h new file mode 100644 index 000000000000..d09332ec9c5c --- /dev/null +++ b/src/include/ipc4/dmic.h @@ -0,0 +1,219 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. + */ + +#ifndef __SOF_IPC4_DMIC_H__ +#define __SOF_IPC4_DMIC_H__ + +#include +#include +#include +#include "gateway.h" + +/** + * \file include/ipc4/dmic.h + * \brief IPC4 DMIC definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +/* IOCTL ID of DMIC Set Gain Coefficients */ +#define DMIC_SET_GAIN_COEFFICIENTS 2 + +/* Maximum number of dmic gain coefficients */ +#define DMIC_MAX_GAIN_COEFFS_CNT 4 + +/** + * @brief Structure representing the global configuration for DMIC (Digital Microphone) module. + */ +union dmic_global_cfg { + /** + * @brief Raw 32-bit value of Global Cfg. + */ + uint32_t clock_on_delay; + + /** + * @brief Bitfields of Extended Global Config. + */ + struct { + /** + * @brief Specifies the period in milliseconds to override data with silence after + * DMA transfer is started. + */ + uint32_t silence_period : 16; + + /** + * @brief Specifies the period in milliseconds for fade-in to apply on input data + * (following silence_period if applied). + */ + uint32_t fade_in_period : 16; + } ext_global_cfg; +} __packed __aligned(4); + +/** + * @brief Structure representing the configuration of a DMIC channel. + */ +struct dmic_channel_cfg { + /** + * @brief Outcontrol + */ + uint32_t out_control; +}; + +/** + * @brief Structure representing FIR (Finite Impulse Response) configuration. + */ +struct dmic_fir_cfg { + /** + * @brief FIR_CONTROL + * Control register for FIR configuration. + */ + uint32_t fir_control; + + /** + * @brief FIR_CONFIG + * Configuration register for FIR filter. + */ + uint32_t fir_config; + + /** + * @brief DC_OFFSET_LEFT + * DC offset value for the left channel. + */ + uint32_t dc_offset_left; + + /** + * @brief DC_OFFSET_RIGHT + * DC offset value for the right channel. + */ + uint32_t dc_offset_rigth; + + /** + * @brief OUT_GAIN_LEFT + * Output gain value for the left channel. + */ + uint32_t out_gain_left; + + /** + * @brief OUT_GAIN_RIGHT + * Output gain value for the right channel. + */ + uint32_t out_gain_rigth; + + /** + * @brief rsvd_2 + * Reserved field. + */ + uint32_t rsvd_2[2]; +} __packed __aligned(4); + +/** + * @brief Structure representing the configuration of the PDM control for DMIC. + * + * This structure defines the configuration parameters for the PDM control of the DMIC + * (Digital Microphone) module. It includes fields for controlling the CIC (Cascaded + * Integrator-Comb) filter, MIC (Microphone) control, SoundWire mapping, FIR (Finite + * Impulse Response) configurations, and FIR coefficients. + */ +struct dmic_pdm_ctrl_cfg { + /** + * @brief CIC_CONTROL + * Control register for CIC configuration. + */ + uint32_t cic_control; + /** + * @brief CIC_CONFIG + * Configuration register for CIC filter. + */ + uint32_t cic_config; + /** + * @brief Reserved field + */ + uint32_t rsvd_0; + /** + * @brief MIC_CONTROL + * Control register for MIC configuration. + */ + uint32_t mic_control; + /** + * @brief + * This field is used on platforms with SoundWire, otherwise ignored. + */ + uint32_t pdmsm; + /** + * @brief Index of another PDMCtrlCfg to be used as a source of FIR coefficients. + */ + uint32_t reuse_fir_from_pdm; + /** + * @brief Reserved field + */ + uint32_t rsvd_1[2]; + /** + * @brief FIR configurations + */ + struct dmic_fir_cfg fir_config[2]; + /** + * @brief Array of FIR coefficients, channel A goes first, then channel B. + */ + uint32_t fir_coeffs[0]; +} __packed __aligned(4); + +/** + * @brief Structure representing the configuration blob for DMIC (Digital Microphone) settings. + * + * This structure contains various configuration settings for DMIC, including time-slot mappings, + * global configuration, PDM channel configuration, and PDM controller configuration. + */ +struct dmic_config_blob { + /** + * @brief Time-slot mappings. + */ + uint32_t ts_group[4]; + + /** + * @brief DMIC global configuration. + */ + union dmic_global_cfg global_cfg; + + /** + * @brief PDM channels to be programmed using data from channel_cfg array. + */ + uint32_t channel_ctrl_mask : 8; + + /** + * @brief Clock source for DMIC. + */ + uint32_t clock_source : 8; + + /** + * @brief Reserved field. + */ + uint32_t rsvd : 16; + + /** + * @brief PDM channel configuration settings. + */ + struct dmic_channel_cfg channel_cfg[0]; + + /** + * @brief PDM controllers to be programmed using data from pdm_ctrl_cfg array. + */ + uint32_t pdm_ctrl_mask; + + /** + * @brief PDM controller configuration settings. + */ + struct dmic_pdm_ctrl_cfg pdm_ctrl_cfg[0]; +} __packed __aligned(4); + +/** + * @brief Structure representing the configuration data for DMIC. + */ +struct dmic_config_data { + /**< Gateway attributes */ + union ipc4_gateway_attributes gtw_attributes; + /**< DMIC Configuration BLOB */ + struct dmic_config_blob dmic_blob; +} __packed __aligned(4); + +#endif /* __SOF_IPC4_DMIC_H__ */ From 0fd9030961e5107c855ae59084a1c49b07ef23a9 Mon Sep 17 00:00:00 2001 From: Ievgen Ganakov Date: Tue, 23 Jul 2024 11:06:38 +0200 Subject: [PATCH 2/2] 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 {