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..34ed399588ce 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,69 @@ 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; +} +#endif + static int copier_init(struct processing_module *mod) { union ipc4_connector_node_id node_id; @@ -131,6 +197,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 +220,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: @@ -198,7 +283,9 @@ static int copier_free(struct processing_module *mod) default: break; } - +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + rfree(cd->mic_priv); +#endif if (cd) rfree(cd->gtw_cfg); rfree(cd); 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..d22a5c130f5c --- /dev/null +++ b/src/audio/mic_privacy_manager/mic_privacy_manager_intel.c @@ -0,0 +1,232 @@ +// 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 handle_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 handle_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"); + mic_privacy_api->set_fw_managed_mode(true); + enable_fw_managed_irq(true); + } + + return 0; +} + +int mic_privacy_manager_get_policy(void) +{ + LOG_DBG("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) + 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("mic_privacy_set_gtw_mic_state 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("mic_privacy_set_gtw_mic_state 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); + + if (mic_priv->mic_privacy_state == 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); + } else if (mic_priv->mic_privacy_state == 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); + } else if (mic_priv->mic_privacy_state == MIC_PRIV_MUTED) { + buffer_zero(buffer); + } else { + LOG_ERR("mic_privacy_process invalid state %x", mic_priv->mic_privacy_state); + } +} 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..67400d4cc433 --- /dev/null +++ b/src/include/sof/audio/mic_privacy_manager.h @@ -0,0 +1,71 @@ +/* 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]; +}; + +//describes gain direction +enum mic_priv_gain_direction { + MIC_PRIV_ADDITION = 0, + MIC_PRIV_SUBTRACTION = 1, +}; + +enum mic_privacy_state { + MIC_PRIV_UNMUTED = 0, + MIC_PRIV_FADE_IN = 1, + MIC_PRIV_FADE_OUT = 2, + MIC_PRIV_MUTED = 3, +}; + +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 130736242587..0346c83d6def 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -1208,6 +1208,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);