Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions src/audio/mic_privacy_manager/mic_privacy_manager_intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we have interrupts disabled at cpu level here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes

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);
}
}
}

Expand Down Expand Up @@ -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();
}
1 change: 1 addition & 0 deletions src/include/sof/audio/mic_privacy_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
39 changes: 39 additions & 0 deletions zephyr/lib/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
*/

#include <sof/audio/component.h>
#if CONFIG_INTEL_ADSP_MIC_PRIVACY
#include <sof/audio/mic_privacy_manager.h>
#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 <sof/init.h>
#include <sof/lib/cpu.h>
#include <sof/lib/pm_runtime.h>
Expand Down Expand Up @@ -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;
Expand All @@ -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",
Expand All @@ -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)
Expand All @@ -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;
Copy link
Contributor

Choose a reason for hiding this comment

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

What if FW went to D3 during fade in? Previous state was MIC_PRIV_FADE_IN, expected to be unmuted soon, but here we force mute. there will be state mismatch. I recommend reading mic state directly from HW

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This fragment is only intended to eliminate the fade-out effect. In the case when mic privacy was turned off during D3, fade-in is still present (at least that's how the audio behaves in the test).

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 */
Expand Down
Loading