From 8bbbddf6edab9f5af7e3a5a94a7f6f1826577178 Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Thu, 13 Feb 2025 16:23:18 +0100 Subject: [PATCH 1/5] [DNM] west: update zephyr to 5ebb04fb5 This pulls in Intel Mic Privacy driver Signed-off-by: Adrian Bonislawski --- west.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/west.yml b/west.yml index 7be1028f0985..9f60c7ca15f4 100644 --- a/west.yml +++ b/west.yml @@ -10,7 +10,7 @@ manifest: - name: thesofproject url-base: https://github.com/thesofproject - name: zephyrproject - url-base: https://github.com/zephyrproject-rtos + url-base: https://github.com/abonislawski # When upgrading projects here please run git log --oneline in the # project and if not too long then include the output in your commit @@ -43,7 +43,7 @@ manifest: - name: zephyr repo-path: zephyr - revision: fe29c40a9366b5ffdcdd2eac26023ce4502413b1 + revision: 02b5a4c6cc15ab3deaeb7e0be72ea327d8a8775d remote: zephyrproject # Import some projects listed in zephyr/west.yml@revision From 98fd59c89c459ebec46d44c140a326f7e5286645 Mon Sep 17 00:00:00 2001 From: Michal Bukowski Date: Wed, 9 Oct 2024 00:18:50 +0200 Subject: [PATCH 2/5] 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 | 4 +++- src/audio/copier/copier_gain.c | 30 ++++++++++++++++-------------- src/audio/copier/copier_gain.h | 23 ++++++++++++++--------- src/audio/copier/copier_generic.c | 8 ++++---- src/audio/copier/copier_hifi.c | 8 ++++---- 5 files changed, 41 insertions(+), 32 deletions(-) diff --git a/src/audio/copier/copier_dai.c b/src/audio/copier/copier_dai.c index 587a133ebd75..56cf02f112b0 100644 --- a/src/audio/copier/copier_dai.c +++ b/src/audio/copier/copier_dai.c @@ -229,7 +229,9 @@ 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); 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..b48ccca0ab7f 100644 --- a/src/audio/copier/copier_gain.c +++ b/src/audio/copier/copier_gain.c @@ -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; @@ -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"); @@ -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; @@ -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; diff --git a/src/audio/copier/copier_gain.h b/src/audio/copier/copier_gain.h index 077a47f468c3..ec55ff999206 100644 --- a/src/audio/copier/copier_gain.h +++ b/src/audio/copier/copier_gain.h @@ -10,6 +10,7 @@ #include #include +#include #include #if SOF_USE_HIFI(3, COPIER) || SOF_USE_HIFI(4, COPIER) || SOF_USE_HIFI(5, COPIER) #include @@ -117,10 +118,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. @@ -129,10 +133,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 +146,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); @@ -209,12 +213,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_generic.c b/src/audio/copier/copier_generic.c index a4fc8ca6c9a1..bd0698cf3504 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..7a2b2def8ed8 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,6 +111,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 */ From b7d2a8d3152e388f169e3bc5fddbd62874410c52 Mon Sep 17 00:00:00 2001 From: Michal Bukowski Date: Fri, 5 Jul 2024 17:48:23 +0200 Subject: [PATCH 3/5] 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 --- posix/include/sof/lib/dma.h | 4 +- src/audio/CMakeLists.txt | 3 + src/audio/base_fw_intel.c | 16 ++ src/audio/copier/copier.c | 99 ++++++++ src/audio/copier/copier.h | 7 + src/audio/copier/copier_host.c | 4 + src/audio/dai-zephyr.c | 7 +- src/audio/mic_privacy_manager/CMakeLists.txt | 3 + .../mic_privacy_manager_intel.c | 237 ++++++++++++++++++ src/include/ipc4/base_fw.h | 4 +- src/include/sof/audio/mic_privacy_manager.h | 65 +++++ src/include/sof/lib/notifier.h | 1 + src/lib/dma.c | 17 +- src/platform/intel/ace/platform.c | 11 +- xtos/include/sof/lib/dma.h | 6 +- zephyr/CMakeLists.txt | 4 + zephyr/include/sof/lib/dma.h | 4 +- 17 files changed, 481 insertions(+), 11 deletions(-) create mode 100644 src/audio/mic_privacy_manager/CMakeLists.txt create mode 100644 src/audio/mic_privacy_manager/mic_privacy_manager_intel.c create mode 100644 src/include/sof/audio/mic_privacy_manager.h diff --git a/posix/include/sof/lib/dma.h b/posix/include/sof/lib/dma.h index ffae21574916..1ff90693926b 100644 --- a/posix/include/sof/lib/dma.h +++ b/posix/include/sof/lib/dma.h @@ -34,6 +34,7 @@ #endif struct comp_buffer; +struct comp_dev; /** \addtogroup sof_dma_drivers DMA Drivers * DMA Drivers API specification. @@ -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..0ef1083e3ae8 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_INTEL_ADSP_MIC_PRIVACY) + add_subdirectory(mic_privacy_manager) + endif() subdirs(pipeline) add_subdirectory(google) if(CONFIG_COMP_CHAIN_DMA) diff --git a/src/audio/base_fw_intel.c b/src/audio/base_fw_intel.c index 5c38d07960cc..dec04bb7227c 100644 --- a/src/audio/base_fw_intel.c +++ b/src/audio/base_fw_intel.c @@ -28,6 +28,10 @@ #include #include "copier/copier_gain.h" +#if CONFIG_INTEL_ADSP_MIC_PRIVACY +#include +#endif + struct ipc4_modules_info { uint32_t modules_count; struct sof_man_module modules[0]; @@ -100,6 +104,18 @@ int basefw_vendor_hw_config(uint32_t *data_offset, char *data) tlv_value_uint32_set(tuple, IPC4_I2S_CAPS_HW_CFG, I2S_VER_30_PTL); #endif +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + struct privacy_capabilities priv_caps; + + 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_INTEL_MIC_PRIVACY_CAPS_HW_CFG, sizeof(priv_caps), &priv_caps); +#endif + tuple = tlv_next(tuple); *data_offset = (int)((char *)tuple - data); diff --git a/src/audio/copier/copier.c b/src/audio/copier/copier.c index 0fe324cb78f3..560e3bce52a2 100644 --- a/src/audio/copier/copier.c +++ b/src/audio/copier/copier.c @@ -39,6 +39,9 @@ #include "host_copier.h" #include "dai_copier.h" #include "ipcgtw_copier.h" +#if CONFIG_INTEL_ADSP_MIC_PRIVACY +#include +#endif #if CONFIG_ZEPHYR_NATIVE_DRIVERS #include @@ -51,6 +54,79 @@ SOF_DEFINE_REG_UUID(copier); DECLARE_TR_CTX(copier_comp_tr, SOF_UUID(copier_uuid), LOG_LEVEL_INFO); +#if CONFIG_INTEL_ADSP_MIC_PRIVACY +static void mic_privacy_event(void *arg, enum notify_id type, void *data) +{ + struct mic_privacy_data *mic_priv_data = arg; + struct mic_privacy_settings *mic_privacy_settings = data; + + if (type == NOTIFIER_ID_MIC_PRIVACY_STATE_CHANGE) { + 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 == MIC_PRIV_UNMUTED) { + if (mic_priv_data->mic_privacy_state == MIC_PRIV_MUTED) { + mic_priv_data->mic_privacy_state = MIC_PRIV_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 != MIC_PRIV_MUTED) { + mic_priv_data->mic_privacy_state = MIC_PRIV_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; + } +} + +static int mic_privacy_configure(struct comp_dev *dev, struct copier_data *cd) +{ + struct mic_privacy_data *mic_priv_data; + int ret; + + mic_priv_data = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, + sizeof(struct mic_privacy_data)); + if (!mic_priv_data) + return -ENOMEM; + + if (cd->gtw_type == ipc4_gtw_dmic) + mic_privacy_enable_dmic_irq(true); + + mic_priv_data->audio_freq = cd->config.base.audio_fmt.sampling_frequency; + + uint32_t zeroing_wait_time = (mic_privacy_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) { + rfree(mic_priv_data); + 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); + if (ret != 0) + rfree(mic_priv_data); + + return ret; +} + +static void mic_privacy_free(struct copier_data *cd) +{ + if (cd->gtw_type == ipc4_gtw_dmic) + mic_privacy_enable_dmic_irq(false); + + notifier_unregister(cd->mic_priv, NULL, NOTIFIER_ID_MIC_PRIVACY_STATE_CHANGE); + + rfree(cd->mic_priv); +} +#endif + static int copier_init(struct processing_module *mod) { union ipc4_connector_node_id node_id; @@ -131,6 +207,16 @@ static int copier_init(struct processing_module *mod) comp_err(dev, "unable to create host"); goto error; } +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + 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; + } + } +#endif break; case ipc4_hda_link_output_class: case ipc4_hda_link_input_class: @@ -144,6 +230,15 @@ static int copier_init(struct processing_module *mod) comp_err(dev, "unable to create dai"); goto error; } +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + 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; + } + } +#endif break; #if CONFIG_IPC4_GATEWAY case ipc4_ipc_output_class: @@ -184,6 +279,10 @@ static int copier_free(struct processing_module *mod) struct copier_data *cd = module_get_private_data(mod); struct comp_dev *dev = mod->dev; +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + mic_privacy_free(cd); +#endif + switch (dev->ipc_config.type) { case SOF_COMP_HOST: if (!cd->ipc_gtw) diff --git a/src/audio/copier/copier.h b/src/audio/copier/copier.h index 43c125134f07..4a6091d99dca 100644 --- a/src/audio/copier/copier.h +++ b/src/audio/copier/copier.h @@ -32,6 +32,10 @@ #include #include #include +#if CONFIG_INTEL_ADSP_MIC_PRIVACY +#include +#include +#endif static const uint32_t INVALID_QUEUE_ID = 0xFFFFFFFF; @@ -270,6 +274,9 @@ 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; +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + struct mic_privacy_data *mic_priv; +#endif }; int apply_attenuation(struct comp_dev *dev, struct copier_data *cd, diff --git a/src/audio/copier/copier_host.c b/src/audio/copier/copier_host.c index b61af44bfe0e..53b6a2aed0d5 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 CONFIG_INTEL_ADSP_MIC_PRIVACY + if (cd->mic_priv) + mic_privacy_process(dev, cd->mic_priv, cd->hd->local_buffer, bytes); +#endif } 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 5ca6db25ab10..37cf6131cb90 100644 --- a/src/audio/dai-zephyr.c +++ b/src/audio/dai-zephyr.c @@ -309,7 +309,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); } } @@ -322,7 +322,8 @@ 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, + + 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 */ @@ -369,7 +370,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->dma_buffer, + ret = stream_copy_from_no_consume(dev, dd->dma_buffer, sink, converter[j], bytes, dd->chmap); } diff --git a/src/audio/mic_privacy_manager/CMakeLists.txt b/src/audio/mic_privacy_manager/CMakeLists.txt new file mode 100644 index 000000000000..b4ae270f7669 --- /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_intel.c) diff --git a/src/audio/mic_privacy_manager/mic_privacy_manager_intel.c b/src/audio/mic_privacy_manager/mic_privacy_manager_intel.c new file mode 100644 index 000000000000..94f4d6d44216 --- /dev/null +++ b/src/audio/mic_privacy_manager/mic_privacy_manager_intel.c @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 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); + +void handle_dmic_irq(void const *self, int a, int b) +{ + LOG_DBG("mic_privacy DMIC IRQ"); + + 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; + + mic_privacy_fill_settings(&settings, mic_disable_status); + mic_privacy_propagate_settings(&settings); + mic_privacy_api->clear_dmic_irq_status(); + } +} + +void handle_fw_managed_irq(void const *dev) +{ + LOG_DBG("mic_privacy FW Managed IRQ"); + + uint32_t mic_disable_status = mic_privacy_api->get_fw_managed_mic_disable_status(); + struct mic_privacy_settings settings; + + mic_privacy_fill_settings(&settings, mic_disable_status); + mic_privacy_propagate_settings(&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(); +} + +static void enable_fw_managed_irq(bool enable_irq) +{ + if (enable_irq) + mic_privacy_api->enable_fw_managed_irq(true, handle_fw_managed_irq); + else + mic_privacy_api->enable_fw_managed_irq(false, NULL); +} + +void mic_privacy_enable_dmic_irq(bool enable_irq) +{ + if (mic_privacy_api->get_policy() == MIC_PRIVACY_HW_MANAGED) { + if (enable_irq) + mic_privacy_api->enable_dmic_irq(true, handle_dmic_irq); + else + mic_privacy_api->enable_dmic_irq(false, NULL); + } +} + +int mic_privacy_manager_init(void) +{ + mic_priv_dev = DEVICE_DT_GET(DT_NODELABEL(mic_privacy)); + + if (!mic_priv_dev) + 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 == MIC_PRIVACY_FW_MANAGED) { + LOG_INF("mic_privacy init FW_MANAGED mode"); + mic_privacy_api->set_fw_managed_mode(true); + enable_fw_managed_irq(true); + } + + return 0; +} + +int mic_privacy_manager_get_policy(void) +{ + 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) + return 0; + mic_privacy_api = (struct mic_privacy_api_funcs *)mic_priv_dev->api; + + return mic_privacy_api->get_privacy_policy_register_raw_value(); +} + +void mic_privacy_propagate_settings(struct mic_privacy_settings *settings) +{ + notifier_event(mic_priv_dev, NOTIFIER_ID_MIC_PRIVACY_STATE_CHANGE, + NOTIFIER_TARGET_CORE_ALL_MASK, settings, + sizeof(struct mic_privacy_settings)); +} + +uint32_t mic_privacy_get_dma_zeroing_wait_time(void) +{ + return (uint32_t)mic_privacy_api->get_dma_data_zeroing_wait_time(); +} + +uint32_t mic_privacy_get_privacy_mask(void) +{ + if (mic_privacy_policy == MIC_PRIVACY_HW_MANAGED) + return mic_privacy_api->get_dma_data_zeroing_link_select(); + + /* hardcoded for FW_MANAGED */ + return 0xFFFFFFFF; +} + +void mic_privacy_fill_settings(struct mic_privacy_settings *settings, uint32_t mic_disable_status) +{ + if (!settings) { + LOG_ERR("Invalid mic_privacy_settings pointer"); + return; + } + + settings->mic_privacy_mode = mic_privacy_policy; + settings->mic_privacy_state = mic_disable_status; + settings->privacy_mask_bits.value = mic_privacy_get_privacy_mask(); + settings->max_ramp_time = mic_privacy_get_dma_zeroing_wait_time(); + + LOG_DBG("mic_privacy_mode = %d, mic_disable_status = %d, \ + privacy_mask = %x, max_ramp_time_in_ms = %d", + settings->mic_privacy_mode, + settings->mic_privacy_state, + settings->privacy_mask_bits.value, + settings->max_ramp_time); +} + +void mic_privacy_set_gtw_mic_state(struct mic_privacy_data *mic_priv_data, + uint32_t mic_disable_status) +{ + if (mic_privacy_policy == MIC_PRIVACY_HW_MANAGED) { + if (mic_disable_status != 0) + mic_priv_data->mic_privacy_state = MIC_PRIV_MUTED; + else + mic_priv_data->mic_privacy_state = MIC_PRIV_UNMUTED; + } else if (mic_privacy_policy == MIC_PRIVACY_FW_MANAGED) { + if (mic_disable_status != 0) { + LOG_DBG("MUTED"); + mic_priv_data->mic_privacy_state = MIC_PRIV_MUTED; + mic_priv_data->dma_data_zeroing = true; + mic_privacy_api->set_fw_mic_disable_status(true); + } else { + LOG_DBG("UNMUTED"); + mic_priv_data->mic_privacy_state = MIC_PRIV_UNMUTED; + mic_priv_data->dma_data_zeroing = false; + mic_privacy_api->set_fw_mic_disable_status(false); + } + } +} + +void mic_privacy_update_gtw_mic_state(struct mic_privacy_data *mic_priv_data, + uint32_t hw_mic_disable_status) +{ + switch (mic_privacy_policy) { + case MIC_PRIVACY_HW_MANAGED: + mic_privacy_set_gtw_mic_state(mic_priv_data, hw_mic_disable_status); + break; + case MIC_PRIVACY_FW_MANAGED: + mic_privacy_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); + + switch (mic_priv->mic_privacy_state) { + case MIC_PRIV_UNMUTED: + break; + case MIC_PRIV_MUTED: + buffer_zero(buffer); + break; + case MIC_PRIV_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 = MIC_PRIV_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); + break; + case MIC_PRIV_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 = INT64_MAX; + } + 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 = MIC_PRIV_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); + break; + default: + LOG_ERR("invalid state %x", mic_priv->mic_privacy_state); + break; + } +} diff --git a/src/include/ipc4/base_fw.h b/src/include/ipc4/base_fw.h index ab98fad44160..338926add5c9 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_INTEL_MIC_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..98fd81a85a42 --- /dev/null +++ b/src/include/sof/audio/mic_privacy_manager.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. All rights reserved. + * + */ + +#ifndef ADSP_FW_MIC_PRIVACY_MANAGER_H +#define ADSP_FW_MIC_PRIVACY_MANAGER_H + +#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 mic_privacy_mask privacy_mask_bits; +}; + +struct privacy_capabilities { + uint32_t privacy_version; + uint32_t capabilities_length; + uint32_t capabilities[1]; +}; + +enum mic_privacy_state { + MIC_PRIV_UNMUTED, + MIC_PRIV_FADE_IN, + MIC_PRIV_FADE_OUT, + MIC_PRIV_MUTED, +}; + +int mic_privacy_manager_init(void); +int mic_privacy_manager_get_policy(void); +uint32_t mic_privacy_get_policy_register(void); +void mic_privacy_propagate_settings(struct mic_privacy_settings *settings); +uint32_t mic_privacy_get_dma_zeroing_wait_time(void); +uint32_t mic_privacy_get_privacy_mask(void); +void mic_privacy_enable_dmic_irq(bool enable_irq); +void mic_privacy_fill_settings(struct mic_privacy_settings *settings, uint32_t mic_disable_status); +void mic_privacy_set_gtw_mic_state(struct mic_privacy_data *mic_priv_data, + uint32_t mic_disable_status); +void mic_privacy_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_privacy_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..afd7dac001ca 100644 --- a/src/lib/dma.c +++ b/src/lib/dma.c @@ -7,6 +7,10 @@ #include #include #include +#include +#if CONFIG_INTEL_ADSP_MIC_PRIVACY +#include +#endif #include #include #include @@ -20,6 +24,8 @@ #include #include #include +#include +#include "../audio/copier/copier.h" LOG_MODULE_REGISTER(dma, CONFIG_SOF_LOG_LEVEL); @@ -453,7 +459,8 @@ 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, +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); @@ -501,6 +508,14 @@ 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); +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + 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); +#endif + 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..4af68f92af15 100644 --- a/src/platform/intel/ace/platform.c +++ b/src/platform/intel/ace/platform.c @@ -26,7 +26,9 @@ #include #include #include - +#if CONFIG_INTEL_ADSP_MIC_PRIVACY +#include "sof/audio/mic_privacy_manager.h" +#endif #include #include @@ -137,6 +139,13 @@ int platform_init(struct sof *sof) watchdog_init(); +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + /* Init mic privacy manager */ + ret = mic_privacy_manager_init(); + if (ret < 0) + return ret; +#endif + /* 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..c11c6c75bd72 100644 --- a/xtos/include/sof/lib/dma.h +++ b/xtos/include/sof/lib/dma.h @@ -33,6 +33,7 @@ #endif struct comp_buffer; +struct comp_dev; /** \addtogroup sof_dma_drivers DMA Drivers * DMA Drivers API specification. @@ -544,9 +545,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, - struct comp_buffer *sink, - dma_process_func process, +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 */ diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 567c03e5e5df..382c3d7cec30 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -1214,6 +1214,10 @@ zephyr_library_sources_ifdef(CONFIG_SHELL sof_shell.c ) +zephyr_library_sources_ifdef(CONFIG_INTEL_ADSP_MIC_PRIVACY + ${SOF_AUDIO_PATH}/mic_privacy_manager/mic_privacy_manager_intel.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..adec97dc1a1e 100644 --- a/zephyr/include/sof/lib/dma.h +++ b/zephyr/include/sof/lib/dma.h @@ -33,6 +33,7 @@ #include struct comp_buffer; +struct comp_dev; /** \addtogroup sof_dma_drivers DMA Drivers * SOF DMA Drivers API specification (deprecated interface, to be @@ -316,7 +317,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 621d414f523165fd1f3d54cf5992c80e49020cbf Mon Sep 17 00:00:00 2001 From: Michal Bukowski Date: Mon, 8 Jul 2024 12:13:08 +0200 Subject: [PATCH 4/5] 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_intel.c | 14 ++++++++++++++ src/include/ipc4/base_fw.h | 3 +++ 2 files changed, 17 insertions(+) diff --git a/src/audio/base_fw_intel.c b/src/audio/base_fw_intel.c index dec04bb7227c..71c573481a9a 100644 --- a/src/audio/base_fw_intel.c +++ b/src/audio/base_fw_intel.c @@ -351,6 +351,18 @@ static int basefw_set_fw_config(bool first_block, return 0; } +static int basefw_set_mic_priv_policy(bool first_block, + bool last_block, + uint32_t data_offset_or_size, + const char *data) +{ +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + return 0; +#else + return IPC4_UNAVAILABLE; +#endif +} + int basefw_vendor_set_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block, @@ -361,6 +373,8 @@ int basefw_vendor_set_large_config(struct comp_dev *dev, switch (param_id) { case IPC4_FW_CONFIG: return basefw_set_fw_config(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 338926add5c9..f1e64fe0e353 100644 --- a/src/include/ipc4/base_fw.h +++ b/src/include/ipc4/base_fw.h @@ -288,6 +288,9 @@ enum ipc4_basefw_params { /* Use LARGE_CONFIG_SET to change SDW ownership */ IPC4_SDW_OWNERSHIP = 31, + + /* Set policy mask for mic privacy in FW managed mode */ + IPC4_SET_MIC_PRIVACY_FW_MANAGED_POLICY_MASK = 36, }; enum ipc4_fw_config_params { From 52c9e0da7c449525bc9dbff4e0e3fc0a17757dee Mon Sep 17 00:00:00 2001 From: Michal Bukowski Date: Mon, 20 Jan 2025 18:18:47 +0100 Subject: [PATCH 5/5] 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_intel.c | 22 ++++++++++++++++++++++ src/include/ipc4/base_fw.h | 3 +++ 2 files changed, 25 insertions(+) diff --git a/src/audio/base_fw_intel.c b/src/audio/base_fw_intel.c index 71c573481a9a..85db72115764 100644 --- a/src/audio/base_fw_intel.c +++ b/src/audio/base_fw_intel.c @@ -363,6 +363,26 @@ static int basefw_set_mic_priv_policy(bool first_block, #endif } +static int basefw_mic_priv_state_changed(bool first_block, + bool last_block, + uint32_t data_offset_or_size, + const char *data) +{ +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + tr_info(&basefw_comp_tr, "state changed to %d", *data); + + uint32_t mic_disable_status = (uint32_t)(*data); + struct mic_privacy_settings settings; + + mic_privacy_fill_settings(&settings, mic_disable_status); + mic_privacy_propagate_settings(&settings); + + return 0; +#else + return IPC4_UNAVAILABLE; +#endif +} + int basefw_vendor_set_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block, @@ -375,6 +395,8 @@ int basefw_vendor_set_large_config(struct comp_dev *dev, return basefw_set_fw_config(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); + case IPC4_MIC_PRIVACY_HW_MANAGED_STATE_CHANGE: + return basefw_mic_priv_state_changed(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 f1e64fe0e353..25601b1209f0 100644 --- a/src/include/ipc4/base_fw.h +++ b/src/include/ipc4/base_fw.h @@ -289,6 +289,9 @@ 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 */ + IPC4_MIC_PRIVACY_HW_MANAGED_STATE_CHANGE = 35, + /* Set policy mask for mic privacy in FW managed mode */ IPC4_SET_MIC_PRIVACY_FW_MANAGED_POLICY_MASK = 36, };