Skip to content

Commit 8a11858

Browse files
mbukowsklgirdwood
authored andcommitted
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 <[email protected]>
1 parent 6e461bd commit 8a11858

File tree

17 files changed

+481
-11
lines changed

17 files changed

+481
-11
lines changed

posix/include/sof/lib/dma.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#endif
3535

3636
struct comp_buffer;
37+
struct comp_dev;
3738

3839
/** \addtogroup sof_dma_drivers DMA Drivers
3940
* DMA Drivers API specification.
@@ -550,7 +551,8 @@ int dma_buffer_copy_to(struct comp_buffer __sparse_cache *source,
550551
* conversion function. DMA buffer consume should be performed after the data has been copied
551552
* to all sinks.
552553
*/
553-
int stream_copy_from_no_consume(struct comp_buffer __sparse_cache *source,
554+
int stream_copy_from_no_consume(struct comp_dev *dev,
555+
struct comp_buffer __sparse_cache *source,
554556
struct comp_buffer __sparse_cache *sink,
555557
dma_process_func process,
556558
uint32_t source_bytes, uint32_t chmap);

src/audio/CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ if(NOT CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD)
103103
if(CONFIG_COMP_VOLUME)
104104
add_subdirectory(volume)
105105
endif()
106+
if(CONFIG_INTEL_ADSP_MIC_PRIVACY)
107+
add_subdirectory(mic_privacy_manager)
108+
endif()
106109
subdirs(pipeline)
107110
add_subdirectory(google)
108111
if(CONFIG_COMP_CHAIN_DMA)

src/audio/base_fw_intel.c

+16
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
#include <rimage/sof/user/manifest.h>
2929
#include "copier/copier_gain.h"
3030

31+
#if CONFIG_INTEL_ADSP_MIC_PRIVACY
32+
#include <sof/audio/mic_privacy_manager.h>
33+
#endif
34+
3135
struct ipc4_modules_info {
3236
uint32_t modules_count;
3337
struct sof_man_module modules[0];
@@ -100,6 +104,18 @@ int basefw_vendor_hw_config(uint32_t *data_offset, char *data)
100104
tlv_value_uint32_set(tuple, IPC4_I2S_CAPS_HW_CFG, I2S_VER_30_PTL);
101105
#endif
102106

107+
#if CONFIG_INTEL_ADSP_MIC_PRIVACY
108+
struct privacy_capabilities priv_caps;
109+
110+
tuple = tlv_next(tuple);
111+
112+
priv_caps.privacy_version = 1;
113+
priv_caps.capabilities_length = 1;
114+
priv_caps.capabilities[0] = mic_privacy_get_policy_register();
115+
116+
tlv_value_set(tuple, IPC4_INTEL_MIC_PRIVACY_CAPS_HW_CFG, sizeof(priv_caps), &priv_caps);
117+
#endif
118+
103119
tuple = tlv_next(tuple);
104120
*data_offset = (int)((char *)tuple - data);
105121

src/audio/copier/copier.c

+99
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
#include "host_copier.h"
4040
#include "dai_copier.h"
4141
#include "ipcgtw_copier.h"
42+
#if CONFIG_INTEL_ADSP_MIC_PRIVACY
43+
#include <zephyr/drivers/mic_privacy/intel/mic_privacy.h>
44+
#endif
4245

4346
#if CONFIG_ZEPHYR_NATIVE_DRIVERS
4447
#include <zephyr/drivers/dai.h>
@@ -51,6 +54,79 @@ SOF_DEFINE_REG_UUID(copier);
5154

5255
DECLARE_TR_CTX(copier_comp_tr, SOF_UUID(copier_uuid), LOG_LEVEL_INFO);
5356

57+
#if CONFIG_INTEL_ADSP_MIC_PRIVACY
58+
static void mic_privacy_event(void *arg, enum notify_id type, void *data)
59+
{
60+
struct mic_privacy_data *mic_priv_data = arg;
61+
struct mic_privacy_settings *mic_privacy_settings = data;
62+
63+
if (type == NOTIFIER_ID_MIC_PRIVACY_STATE_CHANGE) {
64+
LOG_INF("mic_privacy_event, state1 = %d, state2 = %d ",
65+
mic_privacy_settings->mic_privacy_state, mic_priv_data->mic_privacy_state);
66+
67+
if (mic_privacy_settings->mic_privacy_state == MIC_PRIV_UNMUTED) {
68+
if (mic_priv_data->mic_privacy_state == MIC_PRIV_MUTED) {
69+
mic_priv_data->mic_privacy_state = MIC_PRIV_FADE_IN;
70+
LOG_INF("mic_privacy_event switch to FADE_IN");
71+
}
72+
} else {
73+
/* In case when mute would be triggered before copier instantiation. */
74+
if (mic_priv_data->mic_privacy_state != MIC_PRIV_MUTED) {
75+
mic_priv_data->mic_privacy_state = MIC_PRIV_FADE_OUT;
76+
LOG_INF("mic_privacy_event switch to FADE_OUT");
77+
}
78+
}
79+
mic_priv_data->max_ramp_time_in_ms = (mic_privacy_settings->max_ramp_time * 1000) /
80+
ADSP_RTC_FREQUENCY;
81+
}
82+
}
83+
84+
static int mic_privacy_configure(struct comp_dev *dev, struct copier_data *cd)
85+
{
86+
struct mic_privacy_data *mic_priv_data;
87+
int ret;
88+
89+
mic_priv_data = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM,
90+
sizeof(struct mic_privacy_data));
91+
if (!mic_priv_data)
92+
return -ENOMEM;
93+
94+
if (cd->gtw_type == ipc4_gtw_dmic)
95+
mic_privacy_enable_dmic_irq(true);
96+
97+
mic_priv_data->audio_freq = cd->config.base.audio_fmt.sampling_frequency;
98+
99+
uint32_t zeroing_wait_time = (mic_privacy_get_dma_zeroing_wait_time() * 1000) /
100+
ADSP_RTC_FREQUENCY;
101+
102+
ret = copier_gain_set_params(dev, &mic_priv_data->mic_priv_gain_params,
103+
zeroing_wait_time, SOF_DAI_INTEL_NONE);
104+
if (ret != 0) {
105+
rfree(mic_priv_data);
106+
return ret;
107+
}
108+
109+
cd->mic_priv = mic_priv_data;
110+
111+
ret = notifier_register(cd->mic_priv, NULL, NOTIFIER_ID_MIC_PRIVACY_STATE_CHANGE,
112+
mic_privacy_event, 0);
113+
if (ret != 0)
114+
rfree(mic_priv_data);
115+
116+
return ret;
117+
}
118+
119+
static void mic_privacy_free(struct copier_data *cd)
120+
{
121+
if (cd->gtw_type == ipc4_gtw_dmic)
122+
mic_privacy_enable_dmic_irq(false);
123+
124+
notifier_unregister(cd->mic_priv, NULL, NOTIFIER_ID_MIC_PRIVACY_STATE_CHANGE);
125+
126+
rfree(cd->mic_priv);
127+
}
128+
#endif
129+
54130
static int copier_init(struct processing_module *mod)
55131
{
56132
union ipc4_connector_node_id node_id;
@@ -131,6 +207,16 @@ static int copier_init(struct processing_module *mod)
131207
comp_err(dev, "unable to create host");
132208
goto error;
133209
}
210+
#if CONFIG_INTEL_ADSP_MIC_PRIVACY
211+
if (cd->direction == SOF_IPC_STREAM_CAPTURE &&
212+
node_id.f.dma_type == ipc4_hda_host_output_class) {
213+
ret = mic_privacy_configure(dev, cd);
214+
if (ret < 0) {
215+
comp_err(dev, "unable to configure mic privacy");
216+
goto error;
217+
}
218+
}
219+
#endif
134220
break;
135221
case ipc4_hda_link_output_class:
136222
case ipc4_hda_link_input_class:
@@ -144,6 +230,15 @@ static int copier_init(struct processing_module *mod)
144230
comp_err(dev, "unable to create dai");
145231
goto error;
146232
}
233+
#if CONFIG_INTEL_ADSP_MIC_PRIVACY
234+
if (cd->direction == SOF_IPC_STREAM_CAPTURE) {
235+
ret = mic_privacy_configure(dev, cd);
236+
if (ret < 0) {
237+
comp_err(dev, "unable to configure mic privacy");
238+
goto error;
239+
}
240+
}
241+
#endif
147242
break;
148243
#if CONFIG_IPC4_GATEWAY
149244
case ipc4_ipc_output_class:
@@ -184,6 +279,10 @@ static int copier_free(struct processing_module *mod)
184279
struct copier_data *cd = module_get_private_data(mod);
185280
struct comp_dev *dev = mod->dev;
186281

282+
#if CONFIG_INTEL_ADSP_MIC_PRIVACY
283+
mic_privacy_free(cd);
284+
#endif
285+
187286
switch (dev->ipc_config.type) {
188287
case SOF_COMP_HOST:
189288
if (!cd->ipc_gtw)

src/audio/copier/copier.h

+7
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@
3232
#include <sof/compiler_attributes.h>
3333
#include <sof/audio/buffer.h>
3434
#include <sof/audio/pcm_converter.h>
35+
#if CONFIG_INTEL_ADSP_MIC_PRIVACY
36+
#include <sof/lib/notifier.h>
37+
#include <sof/audio/mic_privacy_manager.h>
38+
#endif
3539

3640
static const uint32_t INVALID_QUEUE_ID = 0xFFFFFFFF;
3741

@@ -270,6 +274,9 @@ struct copier_data {
270274
uint32_t channels[IPC4_ALH_MAX_NUMBER_OF_GTW];
271275
uint32_t chan_map[IPC4_ALH_MAX_NUMBER_OF_GTW];
272276
struct ipcgtw_data *ipcgtw_data;
277+
#if CONFIG_INTEL_ADSP_MIC_PRIVACY
278+
struct mic_privacy_data *mic_priv;
279+
#endif
273280
};
274281

275282
int apply_attenuation(struct comp_dev *dev, struct copier_data *cd,

src/audio/copier/copier_host.c

+4
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,10 @@ void copier_host_dma_cb(struct comp_dev *dev, size_t bytes)
271271

272272
buffer_stream_writeback(cd->hd->local_buffer, bytes);
273273
}
274+
#if CONFIG_INTEL_ADSP_MIC_PRIVACY
275+
if (cd->mic_priv)
276+
mic_privacy_process(dev, cd->mic_priv, cd->hd->local_buffer, bytes);
277+
#endif
274278
}
275279

276280
static void copier_notifier_cb(void *arg, enum notify_id type, void *data)

src/audio/dai-zephyr.c

+4-3
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ dai_dma_cb(struct dai_data *dd, struct comp_dev *dev, uint32_t bytes,
309309

310310
if (sink_dev && sink_dev->state == COMP_STATE_ACTIVE &&
311311
audio_buffer_hw_params_configured(&sink->audio_buffer)) {
312-
ret = stream_copy_from_no_consume(dd->local_buffer, sink,
312+
ret = stream_copy_from_no_consume(dev, dd->local_buffer, sink,
313313
converter[j], bytes, dd->chmap);
314314
}
315315
}
@@ -322,7 +322,8 @@ dai_dma_cb(struct dai_data *dd, struct comp_dev *dev, uint32_t bytes,
322322
* The PCM converter functions used during DMA buffer copy can never fail,
323323
* so no need to check the return value of stream_copy_from_no_consume().
324324
*/
325-
ret = stream_copy_from_no_consume(dd->dma_buffer, dd->local_buffer,
325+
326+
ret = stream_copy_from_no_consume(dev, dd->dma_buffer, dd->local_buffer,
326327
dd->process, bytes, dd->chmap);
327328
#if CONFIG_IPC_MAJOR_4
328329
/* Apply gain to the local buffer */
@@ -369,7 +370,7 @@ dai_dma_cb(struct dai_data *dd, struct comp_dev *dev, uint32_t bytes,
369370

370371
if (sink_dev && sink_dev->state == COMP_STATE_ACTIVE &&
371372
audio_buffer_hw_params_configured(&sink->audio_buffer))
372-
ret = stream_copy_from_no_consume(dd->dma_buffer,
373+
ret = stream_copy_from_no_consume(dev, dd->dma_buffer,
373374
sink, converter[j],
374375
bytes, dd->chmap);
375376
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# SPDX-License-Identifier: BSD-3-Clause
2+
3+
add_local_sources(sof mic_privacy_manager_intel.c)

0 commit comments

Comments
 (0)