Skip to content

Commit 4eaf33b

Browse files
committed
audio: kpb: add a Zephyr-native notification mechanism
KPB currently can use SOF notifications and AMS for triggering, but neither of them is currently accessible from userspace. Use a Zephyr native queue API instead. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
1 parent b6c6a05 commit 4eaf33b

4 files changed

Lines changed: 92 additions & 9 deletions

File tree

‎src/audio/Kconfig‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,14 @@ config COMP_KPB
107107
default y
108108
help
109109
Select for KPB component
110+
110111
if COMP_KPB
111112

113+
config KPB_CLI_Q
114+
bool "Use a client queue for KPB"
115+
help
116+
Use a Zephyr queue instead of SOF notifiers
117+
112118
config KPB_FORCE_COPY_TYPE_NORMAL
113119
bool "KPB force copy type normal"
114120
default y

‎src/audio/kpb.c‎

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <rtos/alloc.h>
2727
#include <rtos/clk.h>
2828
#include <rtos/init.h>
29+
#include <rtos/symbol.h>
2930
#include <sof/lib/pm_runtime.h>
3031
#include <sof/lib/uuid.h>
3132
#include <sof/list.h>
@@ -107,13 +108,19 @@ struct comp_data {
107108
struct kpb_fmt_dev_list fmt_device_list;
108109
struct fast_mode_task fmt;
109110

110-
#if CONFIG_AMS
111+
#if CONFIG_AMS && !CONFIG_KPB_CLI_Q
111112
uint32_t kpd_uuid_id;
112113
#endif
113114
};
114115

115116
/*! KPB private functions */
116-
#ifndef CONFIG_AMS
117+
#if CONFIG_KPB_CLI_Q
118+
#include <zephyr/kernel.h>
119+
120+
static struct k_queue *kpb_q;
121+
static struct k_thread kpb_thread;
122+
K_KERNEL_STACK_DEFINE(kpb_stack, 4096);
123+
#elif !CONFIG_AMS
117124
static void kpb_event_handler(void *arg, enum notify_id type, void *event_data);
118125
static int kpb_register_client(struct comp_data *kpb, struct kpb_client *cli);
119126
#endif
@@ -176,7 +183,7 @@ static uint64_t kpb_task_deadline(void *data)
176183
#endif
177184
}
178185

179-
#if CONFIG_AMS
186+
#if CONFIG_AMS && !CONFIG_KPB_CLI_Q
180187

181188
/* Key-phrase detected message*/
182189
static const ams_uuid_t ams_kpd_msg_uuid = AMS_KPD_MSG_UUID;
@@ -456,6 +463,42 @@ static void kpb_set_params(struct comp_dev *dev,
456463

457464
static int kpb_params(struct comp_dev *dev, struct sof_ipc_stream_params *params);
458465

466+
#if CONFIG_KPB_CLI_Q
467+
static void kpb_thread_fn(void *p1, void *p2, void *p3)
468+
{
469+
struct k_queue *q = p1;
470+
471+
for (;;) {
472+
struct kpb_client *cli = k_queue_get(q, K_FOREVER);
473+
474+
kpb_init_draining(cli->dev, cli);
475+
}
476+
}
477+
478+
void kpb_notifier_schedule(struct kpb_client *cli)
479+
{
480+
k_queue_alloc_append(cli->queue, cli);
481+
}
482+
EXPORT_SYMBOL(kpb_notifier_schedule);
483+
484+
void z_impl_kpb_notifier_init(struct comp_dev *dev, struct kpb_client *cli)
485+
{
486+
comp_dbg(dev, "adding new client to %p", kpb_q);
487+
k_thread_access_grant(k_current_get(), kpb_q);
488+
cli->queue = kpb_q;
489+
cli->dev = dev;
490+
}
491+
492+
#include <zephyr/internal/syscall_handler.h>
493+
void z_vrfy_kpb_notifier_init(struct comp_dev *dev, struct kpb_client *cli)
494+
{
495+
K_OOPS(K_SYSCALL_MEMORY_WRITE(dev, sizeof(*dev)));
496+
K_OOPS(K_SYSCALL_MEMORY_WRITE(cli, sizeof(*cli)));
497+
z_impl_kpb_notifier_init(dev, cli);
498+
}
499+
#include <zephyr/syscalls/kpb_notifier_init_mrsh.c>
500+
#endif
501+
459502
/*
460503
* \brief Create a key phrase buffer component.
461504
* \param[in] config - generic ipc component pointer.
@@ -484,7 +527,7 @@ static struct comp_dev *kpb_new(const struct comp_driver *drv,
484527
struct comp_data *kpb;
485528
int ret;
486529

487-
comp_cl_info(&comp_kpb, "kpb_new()");
530+
comp_cl_info(&comp_kpb, "entry");
488531

489532
/* make sure data size is not bigger than config space */
490533
if (ipc_config_size > kpb_config_size) {
@@ -548,6 +591,21 @@ static struct comp_dev *kpb_new(const struct comp_driver *drv,
548591
}
549592
#endif
550593

594+
#if CONFIG_KPB_CLI_Q
595+
kpb_q = k_object_alloc(K_OBJ_QUEUE);
596+
if (!kpb_q) {
597+
comp_free_device(dev);
598+
return NULL;
599+
}
600+
601+
k_queue_init(kpb_q);
602+
k_thread_create(&kpb_thread, kpb_stack, 4096, kpb_thread_fn, kpb_q, NULL, NULL,
603+
1, 0, K_FOREVER);
604+
605+
k_thread_cpu_pin(&kpb_thread, cpu_get_id());
606+
k_thread_start(&kpb_thread);
607+
#endif
608+
551609
return dev;
552610
}
553611

@@ -693,7 +751,10 @@ static void kpb_free(struct comp_dev *dev)
693751

694752
comp_info(dev, "entry");
695753

696-
#if CONFIG_AMS
754+
#if CONFIG_KPB_CLI_Q
755+
k_thread_abort(&kpb_thread);
756+
k_object_free(kpb_q);
757+
#elif CONFIG_AMS
697758
/* Unregister KPB as AMS consumer */
698759
int ret;
699760

@@ -704,7 +765,7 @@ static void kpb_free(struct comp_dev *dev)
704765
#else
705766
/* Unregister KPB from notifications */
706767
notifier_unregister(dev, NULL, NOTIFIER_ID_KPB_CLIENT_EVT);
707-
#endif/* CONFIG_AMS */
768+
#endif/* CONFIG_KPB_CLI_Q */
708769

709770
/* Reclaim memory occupied by history buffer */
710771
kpb_free_history_buffer(kpb->hd.c_hb);
@@ -780,7 +841,7 @@ static int kpb_params(struct comp_dev *dev,
780841
kpb->host_period_size = params->host_period_bytes;
781842
kpb->config.sampling_width = params->sample_container_bytes * 8;
782843

783-
#if CONFIG_AMS
844+
#if !CONFIG_KPB_CLI_Q && CONFIG_AMS
784845
kpb->kpd_uuid_id = AMS_INVALID_MSG_TYPE;
785846
#endif
786847

@@ -869,16 +930,18 @@ static int kpb_prepare(struct comp_dev *dev)
869930
kpb->clients[i].r_ptr = NULL;
870931
}
871932

933+
#if !CONFIG_KPB_CLI_Q
872934
#if CONFIG_AMS
873935
/* AMS Register KPB for notification */
874936
ret = ams_helper_register_consumer(dev, &kpb->kpd_uuid_id,
875937
ams_kpd_msg_uuid,
876938
kpb_ams_kpd_notification);
877939
#else
878-
/* Register KPB for notification */
940+
/* Register KPB for notification *on the current core* */
879941
ret = notifier_register(dev, NULL, NOTIFIER_ID_KPB_CLIENT_EVT,
880942
kpb_event_handler, 0);
881943
#endif /* CONFIG_AMS */
944+
#endif
882945

883946
if (ret < 0) {
884947
kpb_free_history_buffer(kpb->hd.c_hb);
@@ -1010,7 +1073,7 @@ static int kpb_reset(struct comp_dev *dev)
10101073
kpb_reset_history_buffer(kpb->hd.c_hb);
10111074
}
10121075

1013-
#ifndef CONFIG_AMS
1076+
#if !CONFIG_KPB_CLI_Q && !CONFIG_AMS
10141077
/* Unregister KPB from notifications */
10151078
notifier_unregister(dev, NULL, NOTIFIER_ID_KPB_CLIENT_EVT);
10161079
#endif

‎src/include/sof/audio/kpb.h‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ enum kpb_client_state {
113113
};
114114

115115
struct kpb_client {
116+
struct comp_dev *dev;
117+
struct k_queue *queue;
116118
uint8_t id; /**< id associated with output sink */
117119
uint32_t drain_req; /**< normalized value of buffered bytes */
118120
enum kpb_client_state state; /**< current state of a client */
@@ -253,6 +255,17 @@ struct kpb_fmt_dev_list {
253255
struct comp_dev *kpb_mi_ptr;
254256
};
255257

258+
#if CONFIG_KPB_CLI_Q
259+
void kpb_notifier_schedule(struct kpb_client *cli);
260+
#if defined(__ZEPHYR__) && defined(CONFIG_SOF_FULL_ZEPHYR_APPLICATION)
261+
#include <sof/compiler_attributes.h>
262+
__syscall void kpb_notifier_init(struct comp_dev *dev, struct kpb_client *cli);
263+
#include <zephyr/syscalls/kpb.h>
264+
#else
265+
#define kpb_notifier_init z_impl_kpb_notifier_init
266+
#endif
267+
#endif
268+
256269
#ifdef UNIT_TEST
257270
void sys_comp_kpb_init(void);
258271
#endif

‎zephyr/CMakeLists.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,7 @@ zephyr_library_sources_ifdef(CONFIG_SHELL
623623
zephyr_syscall_header(include/sof/lib/cpu.h)
624624
zephyr_library_sources_ifdef(CONFIG_USERSPACE syscall/cpu.c)
625625
zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/audio/module_adapter/module/generic.h)
626+
zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/audio/kpb.h)
626627
zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/lib/fast-get.h)
627628
zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/ipc/ipc_reply.h)
628629
zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/schedule/dp_schedule.h)

0 commit comments

Comments
 (0)