diff --git a/src/audio/mic_privacy_manager/mic_privacy_manager_intel.c b/src/audio/mic_privacy_manager/mic_privacy_manager_intel.c index 94f4d6d44216..5120c2ab4b59 100644 --- a/src/audio/mic_privacy_manager/mic_privacy_manager_intel.c +++ b/src/audio/mic_privacy_manager/mic_privacy_manager_intel.c @@ -62,11 +62,29 @@ static void enable_fw_managed_irq(bool enable_irq) void mic_privacy_enable_dmic_irq(bool enable_irq) { + /* Only proceed if we have a valid device and API */ + if (!mic_priv_dev || !mic_privacy_api) { + LOG_ERR("mic_privacy device or API not initialized"); + return; + } + if (mic_privacy_api->get_policy() == MIC_PRIVACY_HW_MANAGED) { - if (enable_irq) + if (enable_irq) { mic_privacy_api->enable_dmic_irq(true, handle_dmic_irq); - else + + /* Check current status immediately to handle any transitions during D3 */ + if (mic_privacy_api->get_dmic_irq_status()) { + struct mic_privacy_settings settings; + uint32_t mic_disable_status = + mic_privacy_api->get_dmic_mic_disable_status(); + + mic_privacy_fill_settings(&settings, mic_disable_status); + mic_privacy_propagate_settings(&settings); + mic_privacy_api->clear_dmic_irq_status(); + } + } else { mic_privacy_api->enable_dmic_irq(false, NULL); + } } } @@ -235,3 +253,17 @@ void mic_privacy_process(struct comp_dev *dev, struct mic_privacy_data *mic_priv break; } } + +uint32_t mic_privacy_get_mic_disable_status(void) +{ + if (!mic_priv_dev) { + LOG_ERR("mic_privacy device not initialized"); + return 0; + } + + mic_privacy_api = (struct mic_privacy_api_funcs *)mic_priv_dev->api; + if (mic_privacy_api->get_policy() == MIC_PRIVACY_FW_MANAGED) + return mic_privacy_api->get_fw_managed_mic_disable_status(); + + return mic_privacy_api->get_dmic_mic_disable_status(); +} diff --git a/src/include/sof/audio/mic_privacy_manager.h b/src/include/sof/audio/mic_privacy_manager.h index 98fd81a85a42..61689343a37e 100644 --- a/src/include/sof/audio/mic_privacy_manager.h +++ b/src/include/sof/audio/mic_privacy_manager.h @@ -51,6 +51,7 @@ 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); +uint32_t mic_privacy_get_mic_disable_status(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, diff --git a/zephyr/lib/cpu.c b/zephyr/lib/cpu.c index 79946cc039f1..8141557e8987 100644 --- a/zephyr/lib/cpu.c +++ b/zephyr/lib/cpu.c @@ -11,6 +11,12 @@ */ #include +#if CONFIG_INTEL_ADSP_MIC_PRIVACY +#include +#ifdef CONFIG_ADSP_IMR_CONTEXT_SAVE +static uint32_t mic_disable_status; +#endif /* CONFIG_ADSP_IMR_CONTEXT_SAVE */ +#endif /* CONFIG_INTEL_ADSP_MIC_PRIVACY */ #include #include #include @@ -64,6 +70,7 @@ extern void *global_imr_ram_storage; * data integrity across D3 transitions, which is critical for SOF's operation * and currently outside the scope of Zephyr's device-level PM capabilities. */ + static void suspend_dais(void) { struct ipc_comp_dev *icd; @@ -79,6 +86,10 @@ static void suspend_dais(void) mod = comp_mod(icd->cd); cd = module_get_private_data(mod); +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + if (cd->mic_priv) + mic_disable_status = mic_privacy_get_mic_disable_status(); +#endif dd = cd->dd[0]; if (dai_remove(dd->dai->dev) < 0) { tr_err(&zephyr_tr, "DAI suspend failed, type %d index %d", @@ -95,6 +106,11 @@ static void resume_dais(void) struct copier_data *cd; struct dai_data *dd; +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + /* Re-initialize mic privacy manager first to ensure proper state before DAI resume */ + mic_privacy_manager_init(); +#endif + list_for_item(clist, &ipc_get()->comp_list) { icd = container_of(clist, struct ipc_comp_dev, list); if (icd->type != COMP_TYPE_COMPONENT || dev_comp_type(icd->cd) != SOF_COMP_DAI) @@ -107,6 +123,29 @@ static void resume_dais(void) tr_err(&zephyr_tr, "DAI resume failed, type %d index %d", dd->dai->type, dd->dai->index); } + +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + if (cd->mic_priv) { + uint32_t current_mic_status = mic_privacy_get_mic_disable_status(); + + if (mic_disable_status != current_mic_status) { + tr_dbg(&zephyr_tr, "MIC privacy settings cheange after D3"); + struct mic_privacy_settings settings; + + /* Update privacy settings based on new state */ + mic_privacy_fill_settings(&settings, current_mic_status); + mic_privacy_propagate_settings(&settings); + /* Ensure we're starting from a clean state with no fade effects */ + if (cd->mic_priv->mic_privacy_state) { + /* Force immediate mute without fade effect */ + cd->mic_priv->mic_privacy_state = MIC_PRIV_MUTED; + cd->mic_priv->fade_in_out_bytes = 0; + cd->mic_priv->mic_priv_gain_params.gain_env = 0; + cd->mic_priv->mic_priv_gain_params.fade_in_sg_count = 0; + } + } + } +#endif } } #endif /* CONFIG_ADSP_IMR_CONTEXT_SAVE */