Skip to content

Commit 52609de

Browse files
tmlemanlgirdwood
authored andcommitted
audio: mic_privacy: Fix feature functionality after D3 resume
When resuming from D3 state, the microphone privacy feature wasn't properly restored, causing two critical issues: 1. The system didn't respond to privacy button inputs after D3 transitions 2. A short fade-out effect appeared in audio when privacy was enabled, causing test failures that expected complete silence This patch provides a comprehensive solution by: - Adding mic_privacy_manager_init() to resume_dais() to ensure proper re-initialization of the microphone privacy subsystem after D3 - Implementing mic_privacy_get_mic_disable_status() to correctly retrieve the current microphone disable status - Storing the mic_disable_status before entering D3 and comparing it after resume to detect changes during low power state - Enhancing mic_privacy_enable_dmic_irq() to immediately check for IRQ status after D3 transitions to catch events that occurred during suspended state - Explicitly resetting fade parameters (fade_in_out_bytes, gain parameters) to ensure immediate silence without fade artifacts when privacy is enabled - Adding proper error handling and validation to ensure the mic_priv structure is valid before access With these changes, the microphone privacy feature works correctly through power state transitions and properly mutes audio without fade artifacts when privacy is enabled after D3 resume. Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com> (cherry picked from commit aea8101) Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
1 parent 2913f9d commit 52609de

File tree

3 files changed

+74
-2
lines changed

3 files changed

+74
-2
lines changed

src/audio/mic_privacy_manager/mic_privacy_manager_intel.c

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,29 @@ static void enable_fw_managed_irq(bool enable_irq)
6262

6363
void mic_privacy_enable_dmic_irq(bool enable_irq)
6464
{
65+
/* Only proceed if we have a valid device and API */
66+
if (!mic_priv_dev || !mic_privacy_api) {
67+
LOG_ERR("mic_privacy device or API not initialized");
68+
return;
69+
}
70+
6571
if (mic_privacy_api->get_policy() == MIC_PRIVACY_HW_MANAGED) {
66-
if (enable_irq)
72+
if (enable_irq) {
6773
mic_privacy_api->enable_dmic_irq(true, handle_dmic_irq);
68-
else
74+
75+
/* Check current status immediately to handle any transitions during D3 */
76+
if (mic_privacy_api->get_dmic_irq_status()) {
77+
struct mic_privacy_settings settings;
78+
uint32_t mic_disable_status =
79+
mic_privacy_api->get_dmic_mic_disable_status();
80+
81+
mic_privacy_fill_settings(&settings, mic_disable_status);
82+
mic_privacy_propagate_settings(&settings);
83+
mic_privacy_api->clear_dmic_irq_status();
84+
}
85+
} else {
6986
mic_privacy_api->enable_dmic_irq(false, NULL);
87+
}
7088
}
7189
}
7290

@@ -235,3 +253,17 @@ void mic_privacy_process(struct comp_dev *dev, struct mic_privacy_data *mic_priv
235253
break;
236254
}
237255
}
256+
257+
uint32_t mic_privacy_get_mic_disable_status(void)
258+
{
259+
if (!mic_priv_dev) {
260+
LOG_ERR("mic_privacy device not initialized");
261+
return 0;
262+
}
263+
264+
mic_privacy_api = (struct mic_privacy_api_funcs *)mic_priv_dev->api;
265+
if (mic_privacy_api->get_policy() == MIC_PRIVACY_FW_MANAGED)
266+
return mic_privacy_api->get_fw_managed_mic_disable_status();
267+
268+
return mic_privacy_api->get_dmic_mic_disable_status();
269+
}

src/include/sof/audio/mic_privacy_manager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ uint32_t mic_privacy_get_policy_register(void);
5151
void mic_privacy_propagate_settings(struct mic_privacy_settings *settings);
5252
uint32_t mic_privacy_get_dma_zeroing_wait_time(void);
5353
uint32_t mic_privacy_get_privacy_mask(void);
54+
uint32_t mic_privacy_get_mic_disable_status(void);
5455
void mic_privacy_enable_dmic_irq(bool enable_irq);
5556
void mic_privacy_fill_settings(struct mic_privacy_settings *settings, uint32_t mic_disable_status);
5657
void mic_privacy_set_gtw_mic_state(struct mic_privacy_data *mic_priv_data,

zephyr/lib/cpu.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111
*/
1212

1313
#include <sof/audio/component.h>
14+
#if CONFIG_INTEL_ADSP_MIC_PRIVACY
15+
#include <sof/audio/mic_privacy_manager.h>
16+
#ifdef CONFIG_ADSP_IMR_CONTEXT_SAVE
17+
static uint32_t mic_disable_status;
18+
#endif /* CONFIG_ADSP_IMR_CONTEXT_SAVE */
19+
#endif /* CONFIG_INTEL_ADSP_MIC_PRIVACY */
1420
#include <sof/init.h>
1521
#include <sof/lib/cpu.h>
1622
#include <sof/lib/pm_runtime.h>
@@ -64,6 +70,7 @@ extern void *global_imr_ram_storage;
6470
* data integrity across D3 transitions, which is critical for SOF's operation
6571
* and currently outside the scope of Zephyr's device-level PM capabilities.
6672
*/
73+
6774
static void suspend_dais(void)
6875
{
6976
struct ipc_comp_dev *icd;
@@ -79,6 +86,10 @@ static void suspend_dais(void)
7986

8087
mod = comp_mod(icd->cd);
8188
cd = module_get_private_data(mod);
89+
#if CONFIG_INTEL_ADSP_MIC_PRIVACY
90+
if (cd->mic_priv)
91+
mic_disable_status = mic_privacy_get_mic_disable_status();
92+
#endif
8293
dd = cd->dd[0];
8394
if (dai_remove(dd->dai->dev) < 0) {
8495
tr_err(&zephyr_tr, "DAI suspend failed, type %d index %d",
@@ -95,6 +106,11 @@ static void resume_dais(void)
95106
struct copier_data *cd;
96107
struct dai_data *dd;
97108

109+
#if CONFIG_INTEL_ADSP_MIC_PRIVACY
110+
/* Re-initialize mic privacy manager first to ensure proper state before DAI resume */
111+
mic_privacy_manager_init();
112+
#endif
113+
98114
list_for_item(clist, &ipc_get()->comp_list) {
99115
icd = container_of(clist, struct ipc_comp_dev, list);
100116
if (icd->type != COMP_TYPE_COMPONENT || dev_comp_type(icd->cd) != SOF_COMP_DAI)
@@ -107,6 +123,29 @@ static void resume_dais(void)
107123
tr_err(&zephyr_tr, "DAI resume failed, type %d index %d",
108124
dd->dai->type, dd->dai->index);
109125
}
126+
127+
#if CONFIG_INTEL_ADSP_MIC_PRIVACY
128+
if (cd->mic_priv) {
129+
uint32_t current_mic_status = mic_privacy_get_mic_disable_status();
130+
131+
if (mic_disable_status != current_mic_status) {
132+
tr_dbg(&zephyr_tr, "MIC privacy settings cheange after D3");
133+
struct mic_privacy_settings settings;
134+
135+
/* Update privacy settings based on new state */
136+
mic_privacy_fill_settings(&settings, current_mic_status);
137+
mic_privacy_propagate_settings(&settings);
138+
/* Ensure we're starting from a clean state with no fade effects */
139+
if (cd->mic_priv->mic_privacy_state) {
140+
/* Force immediate mute without fade effect */
141+
cd->mic_priv->mic_privacy_state = MIC_PRIV_MUTED;
142+
cd->mic_priv->fade_in_out_bytes = 0;
143+
cd->mic_priv->mic_priv_gain_params.gain_env = 0;
144+
cd->mic_priv->mic_priv_gain_params.fade_in_sg_count = 0;
145+
}
146+
}
147+
}
148+
#endif
110149
}
111150
}
112151
#endif /* CONFIG_ADSP_IMR_CONTEXT_SAVE */

0 commit comments

Comments
 (0)