Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Copier Gain feature for DMIC interface #9537

Merged
merged 2 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/audio/base_fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
13 changes: 13 additions & 0 deletions src/audio/base_fw_intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <rtos/string.h>
#include <sof/tlv.h>
#include <sof/lib/dai.h>
#include <ipc/dai.h>

#if defined(CONFIG_SOC_SERIES_INTEL_ADSP_ACE)
#include <intel_adsp_hda.h>
Expand All @@ -24,6 +25,7 @@

#include <ipc4/base_fw.h>
#include <rimage/sof/user/manifest.h>
#include "copier/copier_gain.h"

struct ipc4_modules_info {
uint32_t modules_count;
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions src/audio/copier/copier_dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens when no configuration is passed from the host (like in case of Linux driver)? Unity gain applied? This seems to be enabled by default.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kv2019i Yes, unity gain applied (gain = 1)

break;
default:
return -EINVAL;
Expand Down
55 changes: 53 additions & 2 deletions src/audio/copier/copier_gain.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <ipc4/base-config.h>
#include <sof/audio/component_ext.h>
#include <module/module/base.h>
#include <sof/tlv.h>
#include <ipc4/dmic.h>
#include "copier.h"
#include "copier_gain.h"

Expand All @@ -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)
Expand Down Expand Up @@ -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);

Expand All @@ -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");
Expand Down
4 changes: 2 additions & 2 deletions src/audio/copier/copier_gain.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__ */
2 changes: 1 addition & 1 deletion src/include/ipc4/base_fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
lgirdwood marked this conversation as resolved.
Show resolved Hide resolved
tlissows marked this conversation as resolved.
Show resolved Hide resolved
} __attribute__((packed, aligned(4)));

enum ipc4_perf_measurements_state_set {
Expand Down
219 changes: 219 additions & 0 deletions src/include/ipc4/dmic.h
Original file line number Diff line number Diff line change
@@ -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 <stdint.h>
#include <stddef.h>
#include <sof/drivers/dmic.h>
#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__ */