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

mic_privacy: initial implementation #9788

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 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: 2 additions & 0 deletions app/boards/intel_adsp_ace30_ptl.conf
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ CONFIG_INTEL_ADSP_TIMER=y
CONFIG_MM_DRV_INTEL_ADSP_TLB_REMAP_UNUSED_RAM=y
CONFIG_SYS_CLOCK_TICKS_PER_SEC=12000

CONFIG_MICROPHONE_PRIVACY=y
Copy link
Collaborator

Choose a reason for hiding this comment

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

if this belongs to the "Zephyr / device drivers" then you probably don't need an empty line above it


# Zephyr / power settings
CONFIG_ADSP_IMR_CONTEXT_SAVE=y
CONFIG_PM=y
Expand Down
4 changes: 3 additions & 1 deletion posix/include/sof/lib/dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <rtos/atomic.h>
#include <rtos/bit.h>
#include <rtos/alloc.h>
#include <sof/audio/component.h>
#include <sof/lib/io.h>
#include <sof/lib/memory.h>
#include <rtos/sof.h>
Expand Down Expand Up @@ -550,7 +551,8 @@ int dma_buffer_copy_to(struct comp_buffer __sparse_cache *source,
* conversion function. DMA buffer consume should be performed after the data has been copied
* to all sinks.
*/
int stream_copy_from_no_consume(struct comp_buffer __sparse_cache *source,
int stream_copy_from_no_consume(struct comp_dev *dev,
struct comp_buffer __sparse_cache *source,
struct comp_buffer __sparse_cache *sink,
dma_process_func process,
uint32_t source_bytes, uint32_t chmap);
Expand Down
3 changes: 3 additions & 0 deletions src/audio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ if(NOT CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD)
if(CONFIG_COMP_VOLUME)
add_subdirectory(volume)
endif()
if(CONFIG_MICROPHONE_PRIVACY)
add_subdirectory(mic_privacy_manager)
endif()
subdirs(pipeline)
add_subdirectory(google)
if(CONFIG_COMP_CHAIN_DMA)
Expand Down
10 changes: 10 additions & 0 deletions src/audio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,16 @@ config IPC4_GATEWAY
host and DSP without using DMA: via memory window (audio payload) and
IPC4 messages (set/get/flush commands).

config MICROPHONE_PRIVACY
bool "microphone privacy"
default y
depends on IPC_MAJOR_4
help
Audio privacy feature allows end user to directly control if user space
applications receive actual data from input devices (microphones).
The control is bypassing application level settings or operating system
controls (like audio endpoint volume).

rsource "up_down_mixer/Kconfig"

config COMP_BLOB
Expand Down
12 changes: 12 additions & 0 deletions src/audio/base_fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <sof/debug/telemetry/performance_monitor.h>
#include <sof/debug/telemetry/telemetry.h>
#include <sof/debug/telemetry/performance_monitor.h>
#include <sof/audio/mic_privacy_manager.h>
/* FIXME:
* Builds for some platforms like tgl fail because their defines related to memory windows are
* already defined somewhere else. Remove this ifdef after it's cleaned up
Expand All @@ -49,6 +50,7 @@ static int basefw_config(uint32_t *data_offset, char *data)
uint16_t version[4] = {SOF_MAJOR, SOF_MINOR, SOF_MICRO, SOF_BUILD};
struct sof_tlv *tuple = (struct sof_tlv *)data;
struct ipc4_scheduler_config sche_cfg;
struct privacy_capabilities priv_caps;
uint32_t plat_data_offset = 0;
uint32_t log_bytes_size = 0;

Expand Down Expand Up @@ -122,6 +124,16 @@ static int basefw_config(uint32_t *data_offset, char *data)

tuple = tlv_next(tuple);


priv_caps.privacy_version = 1;
priv_caps.capabilities_length = 1;
priv_caps.capabilities[0] = mic_privacy_get_policy_register();
Copy link
Contributor

@ujfalusi ujfalusi Jan 21, 2025

Choose a reason for hiding this comment

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

How can this even compile in case of CONFIG_MICROPHONE_PRIVACY=n (everything other than PTL)?


tlv_value_set(tuple, IPC4_PRIVACY_CAPS_HW_CFG, sizeof(priv_caps), &priv_caps);
Copy link
Contributor

@ujfalusi ujfalusi Jan 21, 2025

Choose a reason for hiding this comment

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

This sets the privacy to the wrong TLV, this is the FW_CONFIG, not the HW_CONFIG.
IPC4_PRIVACY_CAPS_HW_CFG == IPC4_MAX_ASTATE_COUNT_FW_CFG


tuple = tlv_next(tuple);


/* add platform specific tuples */
basefw_vendor_fw_config(&plat_data_offset, (char *)tuple);

Expand Down
78 changes: 78 additions & 0 deletions src/audio/copier/copier.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "host_copier.h"
#include "dai_copier.h"
#include "ipcgtw_copier.h"
#include <zephyr/drivers/mic_privacy.h>

#if CONFIG_ZEPHYR_NATIVE_DRIVERS
#include <zephyr/drivers/dai.h>
Expand All @@ -51,6 +52,8 @@ SOF_DEFINE_REG_UUID(copier);

DECLARE_TR_CTX(copier_comp_tr, SOF_UUID(copier_uuid), LOG_LEVEL_INFO);

static int mic_privacy_configure(struct comp_dev *dev, struct copier_data *cd);

static int copier_init(struct processing_module *mod)
{
union ipc4_connector_node_id node_id;
Expand Down Expand Up @@ -131,6 +134,15 @@ static int copier_init(struct processing_module *mod)
comp_err(dev, "unable to create host");
goto error;
}

if (cd->direction == SOF_IPC_STREAM_CAPTURE && node_id.f.dma_type == ipc4_hda_host_output_class) {
ret = mic_privacy_configure(dev, cd);
if (ret < 0) {
comp_err(dev, "unable to configure mic privacy");
goto error;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

indentation, more cases below

}

break;
case ipc4_hda_link_output_class:
case ipc4_hda_link_input_class:
Expand All @@ -144,6 +156,14 @@ static int copier_init(struct processing_module *mod)
comp_err(dev, "unable to create dai");
goto error;
}

if (cd->direction == SOF_IPC_STREAM_CAPTURE) {
ret = mic_privacy_configure(dev, cd);
if (ret < 0) {
comp_err(dev, "unable to configure mic privacy");
goto error;
}
}
break;
#if CONFIG_IPC4_GATEWAY
case ipc4_ipc_output_class:
Expand Down Expand Up @@ -198,6 +218,8 @@ static int copier_free(struct processing_module *mod)
default:
break;
}
if(cd->mic_priv)
rfree(cd->mic_priv);

if (cd)
rfree(cd->gtw_cfg);
Expand Down Expand Up @@ -1098,6 +1120,62 @@ static int copier_unbind(struct processing_module *mod, void *data)
return 0;
}

static void mic_privacy_event(void *arg, enum notify_id type, void *data)
{
LOG_INF("mic_privacy_event");
struct mic_privacy_data *mic_priv_data = arg;
struct mic_privacy_settings *mic_privacy_settings = data;

LOG_INF("mic_privacy_event, arg = %p, data = %p", arg, data);
Copy link
Collaborator

Choose a reason for hiding this comment

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

please reduce the number of logs to a minimum


if (type == NOTIFIER_ID_MIC_PRIVACY_STATE_CHANGE) {

LOG_INF("NOTIFIER_ID_MIC_PRIVACY_STATE_CHANGE, max ramp time = %d, ", mic_privacy_settings->max_ramp_time);
LOG_INF("mic_privacy_event, state1 = %d, state2 = %d ", mic_privacy_settings->mic_privacy_state, mic_priv_data->mic_privacy_state);

if (mic_privacy_settings->mic_privacy_state == UNMUTED) {
if (mic_priv_data->mic_privacy_state == MUTED) {
mic_priv_data->mic_privacy_state = FADE_IN;
LOG_INF("mic_privacy_event switch to FADE_IN");
}
} else {
//In case when mute would be triggered before copier instantiation.
if (mic_priv_data->mic_privacy_state != MUTED) {
mic_priv_data->mic_privacy_state = FADE_OUT;
LOG_INF("mic_privacy_event switch to FADE_OUT");
}
}
mic_priv_data->max_ramp_time_in_ms = (mic_privacy_settings->max_ramp_time * 1000) / ADSP_RTC_FREQUENCY;
LOG_INF("max_ramp_time_in_ms= %d, audio_freq = %d, max_ramp_time = %d", mic_priv_data->max_ramp_time_in_ms, mic_priv_data->audio_freq, mic_privacy_settings->max_ramp_time);

}
}

static int mic_privacy_configure(struct comp_dev *dev, struct copier_data *cd)
{
int ret;
struct mic_privacy_data* mic_priv_data;
mic_priv_data = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(struct mic_privacy_data));
if (!mic_priv_data) {
rfree(mic_priv_data);
Copy link
Collaborator

Choose a reason for hiding this comment

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

not needed, allocation failed

return -ENOMEM;
}

mic_priv_data->audio_freq = cd->config.base.audio_fmt.sampling_frequency;

uint32_t zeroing_wait_time = (get_dma_zeroing_wait_time() *1000) / ADSP_RTC_FREQUENCY;

ret = copier_gain_set_params(dev, &mic_priv_data->mic_priv_gain_params, zeroing_wait_time, SOF_DAI_INTEL_NONE);
if(ret != 0)
Copy link
Collaborator

Choose a reason for hiding this comment

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

but here you do want to free memory

return ret;

cd->mic_priv = mic_priv_data;

ret = notifier_register(cd->mic_priv, NULL, NOTIFIER_ID_MIC_PRIVACY_STATE_CHANGE,
mic_privacy_event, 0);
Copy link
Collaborator

Choose a reason for hiding this comment

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

what if notifier registration fails? You return an error, will the component be usable after that? If not - also free memory

return ret;
}

static struct module_endpoint_ops copier_endpoint_ops = {
.get_total_data_processed = copier_get_processed_data,
.position = copier_position,
Expand Down
5 changes: 5 additions & 0 deletions src/audio/copier/copier.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
#include <sof/compiler_attributes.h>
#include <sof/audio/buffer.h>
#include <sof/audio/pcm_converter.h>
#include <sof/lib/notifier.h>
#include <sof/audio/mic_privacy_manager.h>

static const uint32_t INVALID_QUEUE_ID = 0xFFFFFFFF;

Expand Down Expand Up @@ -270,6 +272,7 @@ struct copier_data {
uint32_t channels[IPC4_ALH_MAX_NUMBER_OF_GTW];
uint32_t chan_map[IPC4_ALH_MAX_NUMBER_OF_GTW];
struct ipcgtw_data *ipcgtw_data;
struct mic_privacy_data *mic_priv;
};

int apply_attenuation(struct comp_dev *dev, struct copier_data *cd,
Expand All @@ -291,4 +294,6 @@ enum sof_ipc_stream_direction

void copier_update_params(struct copier_data *cd, struct comp_dev *dev,
struct sof_ipc_stream_params *params);

void mic_privacy_event(void *arg, enum notify_id type, void *data);
#endif
3 changes: 2 additions & 1 deletion src/audio/copier/copier_dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,8 @@ static int copier_dai_init(struct comp_dev *dev,
}
cd->dd[index]->gain_data = gain_data;

ret = copier_gain_set_params(dev, cd->dd[index]);
ret = copier_gain_set_params(dev, cd->dd[index]->gain_data, GAIN_DEFAULT_FADE_PERIOD,
cd->dd[index]->dai->type);
Copy link
Contributor

Choose a reason for hiding this comment

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

indentation

if (ret < 0) {
comp_err(dev, "Failed to set gain params!");
goto gain_free;
Expand Down
30 changes: 16 additions & 14 deletions src/audio/copier/copier_gain.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,22 @@

LOG_MODULE_DECLARE(copier, CONFIG_SOF_LOG_LEVEL);

int copier_gain_set_params(struct comp_dev *dev, struct dai_data *dd)
int copier_gain_set_params(struct comp_dev *dev,
struct copier_gain_params *gain_params,
uint32_t fade_period,
enum sof_ipc_dai_type dai_type)
{
struct processing_module *mod = comp_mod(dev);
struct copier_data *cd = module_get_private_data(mod);
struct ipc4_base_module_cfg *ipc4_cfg = &cd->config.base;
uint32_t sampling_freq = ipc4_cfg->audio_fmt.sampling_frequency;
uint32_t frames = sampling_freq / dev->pipeline->period;
uint32_t fade_period = GAIN_DEFAULT_FADE_PERIOD;
int ret;

/* Set basic gain parameters */
copier_gain_set_basic_params(dev, dd, ipc4_cfg);
copier_gain_set_basic_params(dev, gain_params, ipc4_cfg);

switch (dd->dai->type) {
switch (dai_type) {
case SOF_DAI_INTEL_DMIC:
{
struct dmic_config_data *dmic_cfg = cd->gtw_cfg;
Expand All @@ -43,18 +45,18 @@ int copier_gain_set_params(struct comp_dev *dev, struct dai_data *dd)
/* 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 =
gain_params->silence_sg_length =
frames * dmic_glb_cfg->ext_global_cfg.silence_period;
dd->gain_data->fade_sg_length = frames * fade_period;
gain_params->fade_sg_length = frames * fade_period;
}
break;
default:
comp_info(dev, "Apply default fade period for dai type %d", dd->dai->type);
comp_info(dev, "Apply default fade period for dai type %d", dai_type);
break;
}

/* Set fade parameters */
ret = copier_gain_set_fade_params(dev, dd, ipc4_cfg, fade_period, frames);
ret = copier_gain_set_fade_params(dev, gain_params, ipc4_cfg, fade_period, frames);
if (ret)
comp_err(dev, "Failed to set fade params");

Expand Down Expand Up @@ -150,7 +152,10 @@ int copier_gain_dma_control(union ipc4_connector_node_id node, const char *confi
break;
}

ret = copier_set_gain(dev, cd->dd[0], gain_data);
struct ipc4_copier_module_cfg *copier_cfg = cd->dd[0]->dai_spec_config;
const int channels = copier_cfg->base.audio_fmt.channels_count;

ret = copier_set_gain(dev, cd->dd[0]->gain_data, gain_data, channels);
if (ret)
comp_err(dev, "Gain DMA control: failed to set gain");
return ret;
Expand All @@ -159,12 +164,9 @@ int copier_gain_dma_control(union ipc4_connector_node_id node, const char *confi
return -ENODEV;
}

int copier_set_gain(struct comp_dev *dev, struct dai_data *dd,
struct gain_dma_control_data *gain_data)
int copier_set_gain(struct comp_dev *dev, struct copier_gain_params *gain_params,
struct gain_dma_control_data *gain_data, int channels)
{
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;

Expand Down
22 changes: 13 additions & 9 deletions src/audio/copier/copier_gain.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,13 @@ struct gain_dma_control_data {
* the given device and DAI data.
*
* @param dev The pointer to the component device structure.
* @param dd The pointer to the DAI data structure.
* @param gain_params The pointer to gain params structure.
* @param fade_period The fade period in milliseconds.
* @param dai_type DAI type
* @return 0 on success, negative error code on failure.
*/
int copier_gain_set_params(struct comp_dev *dev, struct dai_data *dd);
int copier_gain_set_params(struct comp_dev *dev, struct copier_gain_params *gain_params, uint32_t fade_period,
enum sof_ipc_dai_type dai_type);

/**
* @brief Sets the basic gain parameters.
Expand All @@ -129,10 +132,10 @@ int copier_gain_set_params(struct comp_dev *dev, struct dai_data *dd);
* by the given device and DAI data.
*
* @param dev The pointer to the component device structure.
* @param dd The pointer to the DAI data structure.
* @param gain_params The pointer to gain params structure.
* @param ipc4_cfg The pointer to the IPC4 base module config.
*/
void copier_gain_set_basic_params(struct comp_dev *dev, struct dai_data *dd,
void copier_gain_set_basic_params(struct comp_dev *dev, struct copier_gain_params *gain_params,
struct ipc4_base_module_cfg *ipc4_cfg);

/**
Expand All @@ -142,13 +145,13 @@ void copier_gain_set_basic_params(struct comp_dev *dev, struct dai_data *dd,
* by the given device and DAI data.
*
* @param dev The pointer to the component device structure.
* @param dd The pointer to the DAI data structure.
* @param gain_params The pointer to gain params structure.
* @param ipc4_cfg The pointer to the IPC4 base module config.
* @param fade_period The fade period in milliseconds.
* @param frames The number of frames to fade.
* @return 0 on success, negative error code on failure.
*/
int copier_gain_set_fade_params(struct comp_dev *dev, struct dai_data *dd,
int copier_gain_set_fade_params(struct comp_dev *dev, struct copier_gain_params *gain_params,
struct ipc4_base_module_cfg *ipc4_cfg,
uint32_t fade_period, uint32_t frames);

Expand Down Expand Up @@ -209,12 +212,13 @@ enum copier_gain_state copier_gain_eval_state(struct copier_gain_params *gain_pa
* Sets/modify gain for a copier module in runtime.
*
* @param dev The copier device structure.
* @param dd The DAI data structure.
* @param gain_params The pointer to the copier_gain_params structure.
* @param gain_data The gain control data structure.
* @param channels Number of audio channels.
* @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);
int copier_set_gain(struct comp_dev *dev, struct copier_gain_params *gain_params,
struct gain_dma_control_data *gain_data, int channels);

/**
* Checks for unity gain mode.
Expand Down
Loading