From 7350f2fee19ace58e3bfa7aa1ea2a76cfbda9df2 Mon Sep 17 00:00:00 2001 From: Michal Bukowski Date: Wed, 9 Oct 2024 00:18:50 +0200 Subject: [PATCH 1/4] copier: gain: interface changes for setting gain params Change type of arguments for gain params setting functions. DAI data struct is replaced by gain_params. Components other than DAI can also use copier gain feature (eg. microphone privacy) Signed-off-by: Michal Bukowski --- src/audio/copier/copier_dai.c | 2 +- src/audio/copier/copier_gain.c | 7 +++---- src/audio/copier/copier_gain.h | 13 +++++++------ src/audio/copier/copier_generic.c | 8 ++++---- src/audio/copier/copier_hifi.c | 10 +++++----- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/audio/copier/copier_dai.c b/src/audio/copier/copier_dai.c index 587a133ebd75..6bed7736fd42 100644 --- a/src/audio/copier/copier_dai.c +++ b/src/audio/copier/copier_dai.c @@ -229,7 +229,7 @@ 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); if (ret < 0) { comp_err(dev, "Failed to set gain params!"); goto gain_free; diff --git a/src/audio/copier/copier_gain.c b/src/audio/copier/copier_gain.c index f7e2f24fdb8d..a0019ec127a1 100644 --- a/src/audio/copier/copier_gain.c +++ b/src/audio/copier/copier_gain.c @@ -15,18 +15,17 @@ 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) { 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) { case SOF_DAI_INTEL_DMIC: @@ -54,7 +53,7 @@ int copier_gain_set_params(struct comp_dev *dev, struct dai_data *dd) } /* 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"); diff --git a/src/audio/copier/copier_gain.h b/src/audio/copier/copier_gain.h index 077a47f468c3..cdae26fae723 100644 --- a/src/audio/copier/copier_gain.h +++ b/src/audio/copier/copier_gain.h @@ -117,10 +117,11 @@ 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. * @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); /** * @brief Sets the basic gain parameters. @@ -129,10 +130,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); /** @@ -142,13 +143,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); diff --git a/src/audio/copier/copier_generic.c b/src/audio/copier/copier_generic.c index a4fc8ca6c9a1..2c14d7f9c4db 100644 --- a/src/audio/copier/copier_generic.c +++ b/src/audio/copier/copier_generic.c @@ -60,10 +60,9 @@ int apply_attenuation(struct comp_dev *dev, struct copier_data *cd, } } -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) { - struct copier_gain_params *gain_params = dd->gain_data; gain_params->channels_count = ipc4_cfg->audio_fmt.channels_count; @@ -71,11 +70,10 @@ void copier_gain_set_basic_params(struct comp_dev *dev, struct dai_data *dd, gain_params->gain_coeffs[i] = UNITY_GAIN_GENERIC; } -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) { - struct copier_gain_params *gain_params = dd->gain_data; uint16_t step_i64_to_i16; if (fade_period == GAIN_DEFAULT_FADE_PERIOD) { @@ -88,6 +86,8 @@ int copier_gain_set_fade_params(struct comp_dev *dev, struct dai_data *dd, /* Special case for GAIN_ZERO_TRANS_MS to support zero fade-in transition time */ gain_params->fade_sg_length = 0; return 0; + } else { + gain_params->fade_sg_length = frames * fade_period; } /* High precision step for fade-in calculation, keeps accurate precision */ diff --git a/src/audio/copier/copier_hifi.c b/src/audio/copier/copier_hifi.c index 0d0d454f2c41..131b36ea8a7a 100644 --- a/src/audio/copier/copier_hifi.c +++ b/src/audio/copier/copier_hifi.c @@ -75,10 +75,9 @@ int apply_attenuation(struct comp_dev *dev, struct copier_data *cd, } } -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) { - struct copier_gain_params *gain_params = dd->gain_data; /* Set default gain coefficients */ for (int i = 0; i < ARRAY_SIZE(gain_params->gain_coeffs); ++i) @@ -91,11 +90,10 @@ void copier_gain_set_basic_params(struct comp_dev *dev, struct dai_data *dd, gain_params->channels_count = ipc4_cfg->audio_fmt.channels_count; } -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) { - struct copier_gain_params *gain_params = dd->gain_data; uint16_t init_gain[MAX_GAIN_COEFFS_CNT]; uint16_t step_i64_to_i16; ae_f16 step_f16; @@ -113,7 +111,9 @@ int copier_gain_set_fade_params(struct comp_dev *dev, struct dai_data *dd, /* Special case for GAIN_ZERO_TRANS_MS to support zero fade in transition time */ gain_params->fade_sg_length = 0; return 0; - } + } else { + gain_params->fade_sg_length = frames * fade_period; + } /* High precision step for fade-in calculation, keeps accurate precision */ gain_params->step_i64 = INT64_MAX / gain_params->fade_sg_length; From f087cb5f1c22b61cbdba49203072b89e3ba73aba Mon Sep 17 00:00:00 2001 From: Michal Bukowski Date: Fri, 5 Jul 2024 17:48:23 +0200 Subject: [PATCH 2/4] mic_privacy: initial implementation 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). Signed-off-by: Michal Bukowski --- app/boards/intel_adsp_ace30_ptl.conf | 2 + posix/include/sof/lib/dma.h | 4 +- src/audio/CMakeLists.txt | 3 + src/audio/Kconfig | 10 + src/audio/base_fw.c | 12 + src/audio/copier/copier.c | 78 +++++ src/audio/copier/copier.h | 5 + src/audio/copier/copier_dai.c | 3 +- src/audio/copier/copier_gain.c | 25 +- src/audio/copier/copier_gain.h | 11 +- src/audio/copier/copier_host.c | 4 + src/audio/dai-zephyr.c | 17 +- src/audio/mic_privacy_manager/CMakeLists.txt | 3 + .../mic_privacy_manager/mic_privacy_manager.c | 275 ++++++++++++++++++ src/include/ipc4/base_fw.h | 4 +- src/include/sof/audio/mic_privacy_manager.h | 88 ++++++ src/include/sof/lib/notifier.h | 1 + src/lib/dma.c | 23 +- src/platform/intel/ace/platform.c | 7 + xtos/include/sof/lib/dma.h | 8 +- zephyr/CMakeLists.txt | 4 + zephyr/include/sof/lib/dma.h | 3 +- 22 files changed, 554 insertions(+), 36 deletions(-) create mode 100644 src/audio/mic_privacy_manager/CMakeLists.txt create mode 100644 src/audio/mic_privacy_manager/mic_privacy_manager.c create mode 100644 src/include/sof/audio/mic_privacy_manager.h diff --git a/app/boards/intel_adsp_ace30_ptl.conf b/app/boards/intel_adsp_ace30_ptl.conf index 62106d05e02e..c39bde0240d8 100644 --- a/app/boards/intel_adsp_ace30_ptl.conf +++ b/app/boards/intel_adsp_ace30_ptl.conf @@ -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 + # Zephyr / power settings CONFIG_ADSP_IMR_CONTEXT_SAVE=y CONFIG_PM=y diff --git a/posix/include/sof/lib/dma.h b/posix/include/sof/lib/dma.h index ffae21574916..f41b16b38e1e 100644 --- a/posix/include/sof/lib/dma.h +++ b/posix/include/sof/lib/dma.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -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); diff --git a/src/audio/CMakeLists.txt b/src/audio/CMakeLists.txt index bd43559aaa80..81d9154093a0 100644 --- a/src/audio/CMakeLists.txt +++ b/src/audio/CMakeLists.txt @@ -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) diff --git a/src/audio/Kconfig b/src/audio/Kconfig index d0be938077df..abe4bc0912e6 100644 --- a/src/audio/Kconfig +++ b/src/audio/Kconfig @@ -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 diff --git a/src/audio/base_fw.c b/src/audio/base_fw.c index ea495a433a0e..15ac5b806d31 100644 --- a/src/audio/base_fw.c +++ b/src/audio/base_fw.c @@ -25,6 +25,7 @@ #include #include #include +#include /* 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 @@ -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; @@ -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(); + + tlv_value_set(tuple, IPC4_PRIVACY_CAPS_HW_CFG, sizeof(priv_caps), &priv_caps); + + tuple = tlv_next(tuple); + + /* add platform specific tuples */ basefw_vendor_fw_config(&plat_data_offset, (char *)tuple); diff --git a/src/audio/copier/copier.c b/src/audio/copier/copier.c index 0fe324cb78f3..452af0352cfd 100644 --- a/src/audio/copier/copier.c +++ b/src/audio/copier/copier.c @@ -39,6 +39,7 @@ #include "host_copier.h" #include "dai_copier.h" #include "ipcgtw_copier.h" +#include #if CONFIG_ZEPHYR_NATIVE_DRIVERS #include @@ -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; @@ -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; + } + } + break; case ipc4_hda_link_output_class: case ipc4_hda_link_input_class: @@ -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: @@ -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); @@ -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); + + 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); + 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) + 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); + return ret; +} + static struct module_endpoint_ops copier_endpoint_ops = { .get_total_data_processed = copier_get_processed_data, .position = copier_position, diff --git a/src/audio/copier/copier.h b/src/audio/copier/copier.h index 43c125134f07..76f90f0c7dae 100644 --- a/src/audio/copier/copier.h +++ b/src/audio/copier/copier.h @@ -32,6 +32,8 @@ #include #include #include +#include +#include static const uint32_t INVALID_QUEUE_ID = 0xFFFFFFFF; @@ -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, @@ -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 diff --git a/src/audio/copier/copier_dai.c b/src/audio/copier/copier_dai.c index 6bed7736fd42..fcfd45bb59c1 100644 --- a/src/audio/copier/copier_dai.c +++ b/src/audio/copier/copier_dai.c @@ -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]->gain_data, GAIN_DEFAULT_FADE_PERIOD); + ret = copier_gain_set_params(dev, cd->dd[index]->gain_data, GAIN_DEFAULT_FADE_PERIOD, + cd->dd[index]->dai->type); if (ret < 0) { comp_err(dev, "Failed to set gain params!"); goto gain_free; diff --git a/src/audio/copier/copier_gain.c b/src/audio/copier/copier_gain.c index a0019ec127a1..2321325fde19 100644 --- a/src/audio/copier/copier_gain.c +++ b/src/audio/copier/copier_gain.c @@ -15,7 +15,10 @@ LOG_MODULE_DECLARE(copier, CONFIG_SOF_LOG_LEVEL); -int copier_gain_set_params(struct comp_dev *dev, struct copier_gain_params *gain_params, uint32_t fade_period) +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); @@ -27,7 +30,7 @@ int copier_gain_set_params(struct comp_dev *dev, struct copier_gain_params *gain /* Set basic gain parameters */ 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; @@ -42,13 +45,13 @@ int copier_gain_set_params(struct comp_dev *dev, struct copier_gain_params *gain /* 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; } @@ -149,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; @@ -158,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; diff --git a/src/audio/copier/copier_gain.h b/src/audio/copier/copier_gain.h index cdae26fae723..c7cda43d30ff 100644 --- a/src/audio/copier/copier_gain.h +++ b/src/audio/copier/copier_gain.h @@ -119,9 +119,11 @@ struct gain_dma_control_data { * @param dev The pointer to the component device 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 copier_gain_params *gain_params, uint32_t fade_period); +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. @@ -210,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. diff --git a/src/audio/copier/copier_host.c b/src/audio/copier/copier_host.c index b61af44bfe0e..8f324e3ea288 100644 --- a/src/audio/copier/copier_host.c +++ b/src/audio/copier/copier_host.c @@ -271,6 +271,10 @@ void copier_host_dma_cb(struct comp_dev *dev, size_t bytes) buffer_stream_writeback(cd->hd->local_buffer, bytes); } + + if(cd->mic_priv) + mic_privacy_process(dev, cd->mic_priv, cd->hd->local_buffer, bytes); + } static void copier_notifier_cb(void *arg, enum notify_id type, void *data) diff --git a/src/audio/dai-zephyr.c b/src/audio/dai-zephyr.c index c43d2f87332f..c4f60b68714b 100644 --- a/src/audio/dai-zephyr.c +++ b/src/audio/dai-zephyr.c @@ -305,7 +305,7 @@ dai_dma_cb(struct dai_data *dd, struct comp_dev *dev, uint32_t bytes, if (sink_dev && sink_dev->state == COMP_STATE_ACTIVE && audio_buffer_hw_params_configured(&sink->audio_buffer)) { - ret = stream_copy_from_no_consume(dd->local_buffer, sink, + ret = stream_copy_from_no_consume(dev, dd->local_buffer, sink, converter[j], bytes, dd->chmap); } } @@ -318,8 +318,9 @@ dai_dma_cb(struct dai_data *dd, struct comp_dev *dev, uint32_t bytes, * The PCM converter functions used during DMA buffer copy can never fail, * so no need to check the return value of stream_copy_from_no_consume(). */ - ret = stream_copy_from_no_consume(dd->dma_buffer, dd->local_buffer, - dd->process, bytes, dd->chmap); + + ret = stream_copy_from_no_consume(dev, dd->dma_buffer, dd->local_buffer, + dd->process, bytes, dd->chmap); #if CONFIG_IPC_MAJOR_4 /* Apply gain to the local buffer */ if (dd->ipc_config.apply_gain) { @@ -362,12 +363,12 @@ dai_dma_cb(struct dai_data *dd, struct comp_dev *dev, uint32_t bytes, ret = -EINVAL; continue; } - if (sink_dev && sink_dev->state == COMP_STATE_ACTIVE && - audio_buffer_hw_params_configured(&sink->audio_buffer)) - ret = stream_copy_from_no_consume(dd->dma_buffer, - sink, converter[j], - bytes, dd->chmap); + audio_buffer_hw_params_configured(&sink->audio_buffer)) + ret = stream_copy_from_no_consume(dev, dd->dma_buffer, + sink, converter[j], + bytes, dd->chmap); + } } #endif diff --git a/src/audio/mic_privacy_manager/CMakeLists.txt b/src/audio/mic_privacy_manager/CMakeLists.txt new file mode 100644 index 000000000000..ee22713403b8 --- /dev/null +++ b/src/audio/mic_privacy_manager/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof mic_privacy_manager.c) diff --git a/src/audio/mic_privacy_manager/mic_privacy_manager.c b/src/audio/mic_privacy_manager/mic_privacy_manager.c new file mode 100644 index 000000000000..2db681e08ac3 --- /dev/null +++ b/src/audio/mic_privacy_manager/mic_privacy_manager.c @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. + +#include "sof/audio/mic_privacy_manager.h" + +#include +#include +#include +#include +#include +#include + +const struct device *mic_priv_dev; + +static struct mic_privacy_api_funcs *mic_privacy_api; +static enum mic_privacy_policy mic_privacy_policy; + +#define LOG_DOMAIN mic_priv + +LOG_MODULE_REGISTER(LOG_DOMAIN); + +#define MAX_INT64 (0x7FFFFFFFFFFFFFFFULL) + + +int mic_privacy_manager_init(void) +{ + mic_priv_dev = DEVICE_DT_GET(DT_NODELABEL(mic_privacy)); + + if (mic_priv_dev == NULL) + return -EINVAL; + + mic_privacy_api = (struct mic_privacy_api_funcs *) mic_priv_dev->api; + + mic_privacy_policy = mic_privacy_api->get_policy(); + + if (mic_privacy_policy == FW_MANAGED) + { + LOG_INF("mic_privacy FW_MANAGED"); + + mic_privacy_api->set_fw_managed_mode(true); + } + + //Enable interrupts + if (mic_privacy_policy == HW_MANAGED) { + LOG_INF("mic_privacy init HW_MANAGED"); + enable_dmic_irq(true); + } + + else { + enable_fw_managed_irq(true); + } + + return 0; +} + +int mic_privacy_manager_get_policy(void) +{ + LOG_INF("mic_privacy_manager_get_policy "); + + mic_privacy_api = (struct mic_privacy_api_funcs *) mic_priv_dev->api; + + return mic_privacy_api->get_policy(); +} + +uint32_t mic_privacy_get_policy_register(void) +{ + if (mic_priv_dev == NULL) + return -EINVAL; + mic_privacy_api = (struct mic_privacy_api_funcs *) mic_priv_dev->api; + + return mic_privacy_api->get_privacy_policy_register_raw_value(); +} + +void enable_fw_managed_irq(bool enable_irq) +{ + LOG_INF("enable_fw_managed_irq %d", enable_irq); + + if (enable_irq) + mic_privacy_api->enable_fw_managed_irq(true, handle_fw_managed_interrupt); + else + mic_privacy_api->enable_fw_managed_irq(false, NULL); +} + +void handle_dmic_interrupt(void *const self, int a, int b) +{ + LOG_INF("mic_privacy handle_dmic_interrupt"); + + if (mic_privacy_api->get_dmic_irq_status() ) + { + uint32_t mic_disable_status = mic_privacy_api->get_dmic_mic_disable_status(); + struct mic_privacy_settings settings = fill_mic_priv_settings(mic_disable_status); + propagate_privacy_settings(&settings); + mic_privacy_api->clear_dmic_irq_status(); + } +} + + +void enable_dmic_irq(bool enable_irq) +{ + if (enable_irq) + mic_privacy_api->enable_dmic_irq(true, handle_dmic_interrupt); + else + mic_privacy_api->enable_dmic_irq(false, NULL); +} + + +void handle_fw_managed_interrupt(void * const dev) +{ + LOG_INF("handle_fw_managed_interrupt"); + uint32_t mic_disable_status = mic_privacy_api->get_fw_managed_mic_disable_status(); + + + struct mic_privacy_settings mic_privacy_settings = + fill_mic_priv_settings(mic_disable_status); + + propagate_privacy_settings(&mic_privacy_settings); + + + if (mic_disable_status) + mic_privacy_api->set_fw_mic_disable_status(true); + else + mic_privacy_api->set_fw_mic_disable_status(false); + + mic_privacy_api->clear_fw_managed_irq(); +} + +void propagate_privacy_settings(struct mic_privacy_settings *mic_privacy_settings) +{ + LOG_INF("propagate_privacy_settings"); + notifier_event(mic_priv_dev, NOTIFIER_ID_MIC_PRIVACY_STATE_CHANGE, + NOTIFIER_TARGET_CORE_ALL_MASK, + mic_privacy_settings, sizeof(struct mic_privacy_settings)); +} + +uint32_t get_dma_zeroing_wait_time(void) +{ + return (uint32_t)mic_privacy_api->get_dma_data_zeroing_wait_time(); +} + + +uint32_t get_privacy_mask(void) +{ + if (mic_privacy_policy == HW_MANAGED) + { + return mic_privacy_api->get_dma_data_zeroing_link_select(); + } + //hardcoded for FW_MANAGED + return 0xFFFFFFFF; +} + +struct mic_privacy_settings fill_mic_priv_settings(uint32_t mic_disable_status) +{ + LOG_INF("fill_mic_priv_settings"); + + struct mic_privacy_settings mic_privacy_settings = {}; + + mic_privacy_settings.mic_privacy_mode = mic_privacy_policy; + mic_privacy_settings.mic_privacy_state = mic_disable_status; + mic_privacy_settings.privacy_mask_bits.value = get_privacy_mask(); + mic_privacy_settings.max_ramp_time = get_dma_zeroing_wait_time(); + + LOG_INF("mic_privacy_mode = %d, mic_disable_status = %d, privacy_mask = 0x%x, max_ramp_time_in_ms = %d", + mic_privacy_settings.mic_privacy_mode, + mic_privacy_settings.mic_privacy_state, + mic_privacy_settings.privacy_mask_bits.value, + mic_privacy_settings.max_ramp_time ); + + return mic_privacy_settings; +} + +void set_gtw_mic_state(struct mic_privacy_data *mic_priv_data, uint32_t mic_disable_status) +{ + + if (mic_privacy_policy == HW_MANAGED) { + if (mic_disable_status != 0) { + mic_priv_data->mic_privacy_state = MUTED; + } else { + mic_priv_data->mic_privacy_state = UNMUTED; + } + } else if (mic_privacy_policy == FW_MANAGED) { + LOG_INF("set_gtw_mic_state FW_MANAGED, mic_disable_status = %d", + mic_disable_status); + + if (mic_disable_status != 0) { + LOG_INF("set_gtw_mic_state MUTED"); + mic_priv_data->mic_privacy_state = MUTED; + mic_priv_data->dma_data_zeroing = true; + mic_privacy_api->set_fw_mic_disable_status(true); + } else { + LOG_INF("set_gtw_mic_state UNMUTED"); + mic_priv_data->mic_privacy_state = UNMUTED; + mic_priv_data->dma_data_zeroing = false; + mic_privacy_api->set_fw_mic_disable_status(false); + } + } +} + + +void update_gtw_mic_state(struct mic_privacy_data *mic_priv_data, uint32_t hw_mic_disable_status) +{ + + switch (mic_privacy_policy) { + case HW_MANAGED: + { + LOG_INF("update_gtw_mic_state HW_MANAGED"); + set_gtw_mic_state(mic_priv_data, hw_mic_disable_status); + break; + } + case FW_MANAGED: + { + LOG_INF("update_gtw_mic_state FW_MANAGED"); + set_gtw_mic_state(mic_priv_data, + mic_privacy_api->get_fw_managed_mic_disable_status()); + break; + } + default: + { + break; + } + } +} + + +void mic_privacy_process(struct comp_dev *dev, struct mic_privacy_data *mic_priv, struct comp_buffer *buffer, uint32_t copy_samples) +{ + uint32_t sg_size_in_bytes; + sg_size_in_bytes = audio_stream_frame_bytes(&buffer->stream); + uint32_t one_ms_in_bytes = sg_size_in_bytes * (buffer->stream.runtime_stream_params.rate / 1000); + uint32_t copy_bytes = copy_samples * audio_stream_sample_bytes(&buffer->stream); + + if (mic_priv->mic_privacy_state == FADE_IN) { + if (mic_priv->fade_in_out_bytes == 0) { + //start addition + mic_priv->mic_priv_gain_params.fade_in_sg_count = 0; + mic_priv->mic_priv_gain_params.gain_env = 0; + + } + mic_priv->fade_in_out_bytes += copy_bytes; + if (mic_priv->fade_in_out_bytes > one_ms_in_bytes * mic_priv->max_ramp_time_in_ms) { + mic_priv->mic_privacy_state = UNMUTED; + mic_priv->fade_in_out_bytes = 0; + } + + if (mic_priv->max_ramp_time_in_ms > 0) { + copier_gain_input(dev, buffer, &mic_priv->mic_priv_gain_params, GAIN_ADD, copy_bytes); + } + } + else if (mic_priv->mic_privacy_state == FADE_OUT){ + if (mic_priv->fade_in_out_bytes == 0) { + //start subtraction + mic_priv->mic_priv_gain_params.fade_in_sg_count = 0; + mic_priv->mic_priv_gain_params.gain_env = MAX_INT64; + } + mic_priv->fade_in_out_bytes += copy_bytes; + if (mic_priv->fade_in_out_bytes > one_ms_in_bytes * mic_priv->max_ramp_time_in_ms) { + mic_priv->mic_privacy_state = MUTED; + mic_priv->fade_in_out_bytes = 0; + buffer_zero(buffer); + } + if (mic_priv->max_ramp_time_in_ms > 0) { + copier_gain_input(dev, buffer, &mic_priv->mic_priv_gain_params, GAIN_SUBTRACT, copy_bytes); + } + } + else if (mic_priv->mic_privacy_state == MUTED) { + buffer_zero(buffer); + } + else + { + LOG_ERR("mic_privacy_process invalid state 0x%x", mic_priv->mic_privacy_state); + } + +} + + diff --git a/src/include/ipc4/base_fw.h b/src/include/ipc4/base_fw.h index ab98fad44160..bb048930200e 100644 --- a/src/include/ipc4/base_fw.h +++ b/src/include/ipc4/base_fw.h @@ -399,7 +399,9 @@ enum ipc4_hw_config_params { /* Size of a single memory bank (EBB) in bytes */ IPC4_EBB_SIZE_BYTES_HW_CFG = 9, /* UAOL capabilities */ - IPC4_UAOL_CAPS_HW_CFG = 10 + IPC4_UAOL_CAPS_HW_CFG = 10, + /* Mic privacy capabilities */ + IPC4_PRIVACY_CAPS_HW_CFG = 11 }; enum ipc4_memory_type { diff --git a/src/include/sof/audio/mic_privacy_manager.h b/src/include/sof/audio/mic_privacy_manager.h new file mode 100644 index 000000000000..5d9064cde6bc --- /dev/null +++ b/src/include/sof/audio/mic_privacy_manager.h @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. + +#ifndef ADSP_FW_MIC_PRIVACY_MANAGER_H +#define ADSP_FW_MIC_PRIVACY_MANAGER_H + +#include +#include +#include +#include +#include "../audio/copier/copier_gain.h" + +#define ADSP_RTC_FREQUENCY 32768 + + +struct mic_privacy_data { + enum ipc4_sampling_frequency audio_freq; + uint32_t mic_privacy_state; + bool dma_data_zeroing; + uint32_t fade_in_out_bytes; + uint32_t max_ramp_time_in_ms; + + struct copier_gain_params mic_priv_gain_params; +}; + + +struct mic_privacy_settings { + enum mic_privacy_policy mic_privacy_mode; + /* 0-Mic Unmute, 1-Mic Mute */ + uint32_t mic_privacy_state; + uint32_t max_ramp_time; + union privacy_mask privacy_mask_bits; + +}; + +struct privacy_capabilities { + uint32_t privacy_version; + uint32_t capabilities_length; + uint32_t capabilities[1]; +}; + +//describes gain direction +enum mic_priv_gain_direction +{ + ADDITION = 0, + SUBTRACTION = 1, +}; + +enum mic_privacy_state { + UNMUTED = 0, + FADE_IN = 1, + FADE_OUT = 2, + MUTED = 3, +}; + +int mic_privacy_manager_init(void); + +int mic_privacy_manager_get_policy(void); + +uint32_t mic_privacy_get_policy_register(void); + +void enable_fw_managed_irq(bool enable_irq); + +void enable_dmic_irq(bool enable_irq); + +void handle_dmic_interrupt(void * const self, int a, int b); + +void handle_fw_managed_interrupt(void * const dev); + +void propagate_privacy_settings(struct mic_privacy_settings *mic_privacy_settings); + +uint32_t get_dma_zeroing_wait_time(void); + +uint32_t get_privacy_mask(void); + +struct mic_privacy_settings fill_mic_priv_settings(uint32_t mic_disable_status); + +void set_gtw_mic_state(struct mic_privacy_data *mic_priv_data, uint32_t mic_disable_status); + +void update_gtw_mic_state(struct mic_privacy_data *mic_priv_data, uint32_t hw_mic_disable_status); + +void mic_privacy_process(struct comp_dev *dev, struct mic_privacy_data *mic_priv, struct comp_buffer *buffer, uint32_t copy_samples); + +void mic_priv_gain_input(uint8_t *buff, uint32_t buff_size, uint32_t mic_priv_state, + const struct ipc4_audio_format *in_fmt); + +#endif /* ADSP_FW_MIC_PRIVACY_MANAGER_H */ diff --git a/src/include/sof/lib/notifier.h b/src/include/sof/lib/notifier.h index abf893281f70..060906655cb8 100644 --- a/src/include/sof/lib/notifier.h +++ b/src/include/sof/lib/notifier.h @@ -34,6 +34,7 @@ enum notify_id { NOTIFIER_ID_LL_POST_RUN, /* NULL */ NOTIFIER_ID_DMA_IRQ, /* struct dma_chan_data * */ NOTIFIER_ID_DAI_TRIGGER, /* struct dai_group * */ + NOTIFIER_ID_MIC_PRIVACY_STATE_CHANGE, /* struct mic_privacy_settings * */ NOTIFIER_ID_COUNT }; diff --git a/src/lib/dma.c b/src/lib/dma.c index 552c487cb296..29f455b17467 100644 --- a/src/lib/dma.c +++ b/src/lib/dma.c @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include #include @@ -20,6 +22,8 @@ #include #include #include +#include +#include "../audio/copier/copier.h" LOG_MODULE_REGISTER(dma, CONFIG_SOF_LOG_LEVEL); @@ -344,7 +348,7 @@ int dma_buffer_copy_from(struct comp_buffer *source, * cannot be used with Host DMA. Fortunately, remapping conversion is specifically * designed for use with IPC4 DAI gateway's device posture feature. IPC4 DAI gateway * does not have the same size alignment limitations. Therefore, frame-based calculations - * are employed only when necessary —- in the case of IPC4 DAI gateway with remapping + * are employed only when necessary —- in the case of IPC4 DAI gateway with remapping * conversion that modifies number of channels. */ if (source_channels == sink_channels) { @@ -408,7 +412,7 @@ int dma_buffer_copy_to(struct comp_buffer *source, * cannot be used with Host DMA. Fortunately, remapping conversion is specifically * designed for use with IPC4 DAI gateway's device posture feature. IPC4 DAI gateway * does not have the same size alignment limitations. Therefore, frame-based calculations - * are employed only when necessary —- in the case of IPC4 DAI gateway with remapping + * are employed only when necessary —- in the case of IPC4 DAI gateway with remapping * conversion that modifies number of channels. */ if (source_channels == sink_channels) { @@ -453,8 +457,10 @@ int dma_buffer_copy_to(struct comp_buffer *source, return ret; } -int stream_copy_from_no_consume(struct comp_buffer *source, struct comp_buffer *sink, - dma_process_func process, uint32_t source_bytes, uint32_t chmap) + +int stream_copy_from_no_consume(struct comp_dev *dev, struct comp_buffer *source, + struct comp_buffer *sink, + dma_process_func process, uint32_t source_bytes, uint32_t chmap) { int source_channels = audio_stream_get_channels(&source->stream); int sink_channels = audio_stream_get_channels(&sink->stream); @@ -471,7 +477,7 @@ int stream_copy_from_no_consume(struct comp_buffer *source, struct comp_buffer * * cannot be used with Host DMA. Fortunately, remapping conversion is specifically * designed for use with IPC4 DAI gateway's device posture feature. IPC4 DAI gateway * does not have the same size alignment limitations. Therefore, frame-based calculations - * are employed only when necessary —- in the case of IPC4 DAI gateway with remapping + * are employed only when necessary —- in the case of IPC4 DAI gateway with remapping * conversion that modifies number of channels. */ if (source_channels == sink_channels) { @@ -501,6 +507,13 @@ int stream_copy_from_no_consume(struct comp_buffer *source, struct comp_buffer * /* process data */ ret = process(istream, 0, &sink->stream, 0, source_samples, chmap); + + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + + if(cd->mic_priv) + mic_privacy_process(dev, cd->mic_priv, sink, source_samples); + buffer_stream_writeback(sink, sink_bytes); comp_update_buffer_produce(sink, sink_bytes); diff --git a/src/platform/intel/ace/platform.c b/src/platform/intel/ace/platform.c index 9e88861d9a97..002f3219668b 100644 --- a/src/platform/intel/ace/platform.c +++ b/src/platform/intel/ace/platform.c @@ -26,6 +26,7 @@ #include #include #include +#include "sof/audio/mic_privacy_manager.h" #include #include @@ -137,6 +138,12 @@ int platform_init(struct sof *sof) watchdog_init(); + /* Init mic privacy manager */ + ret = mic_privacy_manager_init(); + if (ret < 0) + return ret; + + /* show heap status */ heap_trace_all(1); diff --git a/xtos/include/sof/lib/dma.h b/xtos/include/sof/lib/dma.h index 7cfd6cecdc2b..7c785d19becf 100644 --- a/xtos/include/sof/lib/dma.h +++ b/xtos/include/sof/lib/dma.h @@ -544,10 +544,10 @@ int dma_buffer_copy_from(struct comp_buffer *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 *source, - struct comp_buffer *sink, - dma_process_func process, - uint32_t source_bytes, uint32_t chmap); + +int stream_copy_from_no_consume(struct comp_dev *dev, struct comp_buffer *source, + struct comp_buffer *sink, + dma_process_func process, uint32_t source_bytes, uint32_t chmap); /* copies data to DMA buffer using provided processing function */ int dma_buffer_copy_to(struct comp_buffer *source, diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index e3e6534bcb88..1a670a415d50 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -1189,6 +1189,10 @@ zephyr_library_sources_ifdef(CONFIG_SHELL sof_shell.c ) +zephyr_library_sources_ifdef(CONFIG_MICROPHONE_PRIVACY + ${SOF_AUDIO_PATH}/mic_privacy_manager/mic_privacy_manager.c +) + zephyr_library_link_libraries(SOF) target_link_libraries(SOF INTERFACE zephyr_interface) diff --git a/zephyr/include/sof/lib/dma.h b/zephyr/include/sof/lib/dma.h index e5c68f9b31c9..9031d6f263d6 100644 --- a/zephyr/include/sof/lib/dma.h +++ b/zephyr/include/sof/lib/dma.h @@ -316,7 +316,8 @@ int dma_buffer_copy_from(struct comp_buffer *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 *source, +int stream_copy_from_no_consume(struct comp_dev *dev, + struct comp_buffer *source, struct comp_buffer *sink, dma_process_func process, uint32_t source_bytes, uint32_t chmap); From 6ae51744dcfa17ce5273131194bde735f6db4714 Mon Sep 17 00:00:00 2001 From: Michal Bukowski Date: Mon, 8 Jul 2024 12:13:08 +0200 Subject: [PATCH 3/4] ipc: added IPC SET_MIC_PRIVACY_FW_MANAGED_POLICY_MAS Added empty implementation which always returns success Signed-off-by: Michal Bukowski --- src/audio/base_fw.c | 11 +++++++++++ src/include/ipc4/base_fw.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/src/audio/base_fw.c b/src/audio/base_fw.c index 15ac5b806d31..a9bf8d9ec11c 100644 --- a/src/audio/base_fw.c +++ b/src/audio/base_fw.c @@ -274,6 +274,15 @@ static int basefw_resource_allocation_request(bool first_block, } } +static int basefw_set_mic_priv_policy(bool first_block, + bool last_block, + uint32_t data_offset_or_size, + const char *data) +{ + tr_info(&basefw_comp_tr, "basefw_set_mic_priv_policy"); + return 0; +} + static int basefw_power_state_info_get(uint32_t *data_offset, char *data) { #if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL @@ -655,6 +664,8 @@ static int basefw_set_large_config(struct comp_dev *dev, case IPC4_RESOURCE_ALLOCATION_REQUEST: return basefw_resource_allocation_request(first_block, last_block, data_offset, data); + case IPC4_SET_MIC_PRIVACY_FW_MANAGED_POLICY_MASK: + return basefw_set_mic_priv_policy(first_block, last_block, data_offset, data); default: break; } diff --git a/src/include/ipc4/base_fw.h b/src/include/ipc4/base_fw.h index bb048930200e..508201de70ca 100644 --- a/src/include/ipc4/base_fw.h +++ b/src/include/ipc4/base_fw.h @@ -288,6 +288,8 @@ enum ipc4_basefw_params { /* Use LARGE_CONFIG_SET to change SDW ownership */ IPC4_SDW_OWNERSHIP = 31, + + IPC4_SET_MIC_PRIVACY_FW_MANAGED_POLICY_MASK =36, }; enum ipc4_fw_config_params { From ac8073ffca95686bc6ed222cd0df54c04bd4bb22 Mon Sep 17 00:00:00 2001 From: Michal Bukowski Date: Mon, 20 Jan 2025 18:18:47 +0100 Subject: [PATCH 4/4] mic_privacy: implement new IPC - SNDW_MIC_PRIVACY_HW_MANAGED_STATE_CHANGE SW sends this IPC when microphone privacy state is changed for HW_MANAGED mode and SNDW interface. Signed-off-by: Michal Bukowski --- src/audio/base_fw.c | 17 +++++++++++++++++ src/include/ipc4/base_fw.h | 6 ++++++ 2 files changed, 23 insertions(+) diff --git a/src/audio/base_fw.c b/src/audio/base_fw.c index a9bf8d9ec11c..7a98bcbec01f 100644 --- a/src/audio/base_fw.c +++ b/src/audio/base_fw.c @@ -274,6 +274,20 @@ static int basefw_resource_allocation_request(bool first_block, } } +static int basefw_mic_priv_state_changed(bool first_block, + bool last_block, + uint32_t data_offset_or_size, + const char *data) +{ + tr_info(&basefw_comp_tr, "basefw_mic_priv_state_changed, status = %d", *data); + + uint32_t mic_disable_status = (uint32_t)(*data); + struct mic_privacy_settings settings = fill_mic_priv_settings(mic_disable_status); + propagate_privacy_settings(&settings); + + return 0; +} + static int basefw_set_mic_priv_policy(bool first_block, bool last_block, uint32_t data_offset_or_size, @@ -664,6 +678,9 @@ static int basefw_set_large_config(struct comp_dev *dev, case IPC4_RESOURCE_ALLOCATION_REQUEST: return basefw_resource_allocation_request(first_block, last_block, data_offset, data); + case SNDW_MIC_PRIVACY_HW_MANAGED_STATE_CHANGE: + return basefw_mic_priv_state_changed(first_block, last_block, data_offset, + data); case IPC4_SET_MIC_PRIVACY_FW_MANAGED_POLICY_MASK: return basefw_set_mic_priv_policy(first_block, last_block, data_offset, data); default: diff --git a/src/include/ipc4/base_fw.h b/src/include/ipc4/base_fw.h index 508201de70ca..15d2b89fce3a 100644 --- a/src/include/ipc4/base_fw.h +++ b/src/include/ipc4/base_fw.h @@ -289,6 +289,12 @@ enum ipc4_basefw_params { /* Use LARGE_CONFIG_SET to change SDW ownership */ IPC4_SDW_OWNERSHIP = 31, + /*! + * This command is used by SW to notify FW for changing state of Mic Privacy + * for SoundWire Gateways + */ + SNDW_MIC_PRIVACY_HW_MANAGED_STATE_CHANGE = 35, + IPC4_SET_MIC_PRIVACY_FW_MANAGED_POLICY_MASK =36, };