Skip to content
Open
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
8 changes: 8 additions & 0 deletions src/audio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,14 @@ config KPB_CLI_Q
help
Use a Zephyr queue instead of SOF notifiers

config KPB_NOTIFIER
bool "Enable Notifier for KPB events"
default y
help
Enable KPB client events delivered through the SOF notifier API.
This transport can be enabled independently of the Async Messaging
Service (AMS), including together with AMS.

config KPB_FORCE_COPY_TYPE_NORMAL
bool "KPB force copy type normal"
default y
Expand Down
51 changes: 37 additions & 14 deletions src/audio/kpb.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@
#include <sof/lib/ams.h>
#include <sof/lib/ams_msg.h>
#include <ipc4/ams_helpers.h>
#else
#endif
#if CONFIG_KPB_NOTIFIER
#include <sof/lib/notifier.h>
#endif

Expand Down Expand Up @@ -120,10 +121,13 @@ struct comp_data {
static struct k_queue *kpb_q;
static struct k_thread kpb_thread;
K_KERNEL_STACK_DEFINE(kpb_stack, 4096);
#elif !CONFIG_AMS
#endif

#if CONFIG_KPB_NOTIFIER
static void kpb_event_handler(void *arg, enum notify_id type, void *event_data);
static int kpb_register_client(struct comp_data *kpb, struct kpb_client *cli);
#endif

static void kpb_init_draining(struct comp_dev *dev, struct kpb_client *cli);
static enum task_state kpb_draining_task(void *arg);
static int kpb_buffer_data(struct comp_dev *dev,
Expand Down Expand Up @@ -762,10 +766,12 @@ static void kpb_free(struct comp_dev *dev)
kpb_ams_kpd_notification);
if (ret)
comp_err(dev, "AMS unregister error %d", ret);
#else
#endif/* CONFIG_KPB_CLI_Q */

#if CONFIG_KPB_NOTIFIER
/* Unregister KPB from notifications */
notifier_unregister(dev, NULL, NOTIFIER_ID_KPB_CLIENT_EVT);
#endif/* CONFIG_KPB_CLI_Q */
#endif/* CONFIG_KPB_NOTIFIER */

/* Reclaim memory occupied by history buffer */
kpb_free_history_buffer(kpb->hd.c_hb);
Expand Down Expand Up @@ -930,23 +936,33 @@ static int kpb_prepare(struct comp_dev *dev)
kpb->clients[i].r_ptr = NULL;
}

#if CONFIG_KPB_NOTIFIER
/* Register KPB for notification *on the current core* */
ret = notifier_register(dev, NULL, NOTIFIER_ID_KPB_CLIENT_EVT, kpb_event_handler);
Comment thread
serhiy-katsyuba-intel marked this conversation as resolved.

if (ret < 0) {
kpb_free_history_buffer(kpb->hd.c_hb);
kpb->hd.c_hb = NULL;
return -ENOMEM;
}
#endif

#if !CONFIG_KPB_CLI_Q
#if CONFIG_AMS
/* AMS Register KPB for notification */
ret = ams_helper_register_consumer(dev, &kpb->kpd_uuid_id,
ams_kpd_msg_uuid,
kpb_ams_kpd_notification);
#else
/* Register KPB for notification *on the current core* */
ret = notifier_register(dev, NULL, NOTIFIER_ID_KPB_CLIENT_EVT, kpb_event_handler);
#endif /* CONFIG_AMS */
#endif

if (ret < 0) {
#if CONFIG_KPB_NOTIFIER
notifier_unregister(dev, NULL, NOTIFIER_ID_KPB_CLIENT_EVT);
#endif
kpb_free_history_buffer(kpb->hd.c_hb);
kpb->hd.c_hb = NULL;
return -ENOMEM;
}
#endif /* CONFIG_AMS */
#endif

#ifndef CONFIG_IPC_MAJOR_4
/* Search for KPB related sinks.
Expand Down Expand Up @@ -1072,7 +1088,7 @@ static int kpb_reset(struct comp_dev *dev)
kpb_reset_history_buffer(kpb->hd.c_hb);
}

#if !CONFIG_KPB_CLI_Q && !CONFIG_AMS
#if CONFIG_KPB_NOTIFIER
/* Unregister KPB from notifications */
notifier_unregister(dev, NULL, NOTIFIER_ID_KPB_CLIENT_EVT);
#endif
Expand Down Expand Up @@ -1576,14 +1592,14 @@ static int kpb_buffer_data(struct comp_dev *dev,
return ret;
}

#ifndef CONFIG_AMS
/**
* \brief Main event dispatcher.
* \param[in] arg - KPB component internal data.
* \param[in] type - notification type
* \param[in] event_data - event specific data.
* \return none.
*/
#if CONFIG_KPB_NOTIFIER
static void kpb_event_handler(void *arg, enum notify_id type, void *event_data)
{
struct comp_dev *dev = arg;
Expand All @@ -1599,7 +1615,14 @@ static void kpb_event_handler(void *arg, enum notify_id type, void *event_data)
kpb_register_client(kpb, cli);
break;
case KPB_EVENT_UNREGISTER_CLIENT:
/*TODO*/
if (!cli || cli->id >= KPB_MAX_NO_OF_CLIENTS ||
kpb->clients[cli->id].state == KPB_CLIENT_UNREGISTERED)
break;

kpb->clients[cli->id].state = KPB_CLIENT_UNREGISTERED;
kpb->clients[cli->id].r_ptr = NULL;
kpb->clients[cli->id].sink = NULL;
kpb->kpb_no_of_clients--;
break;
case KPB_EVENT_BEGIN_DRAINING:
kpb_init_draining(dev, cli);
Expand Down Expand Up @@ -1656,7 +1679,7 @@ static int kpb_register_client(struct comp_data *kpb, struct kpb_client *cli)

return ret;
}
#endif /* CONFIG_AMS */
#endif /* CONFIG_KPB_NOTIFIER */

/**
* \brief Prepare history buffer for draining.
Expand Down
6 changes: 6 additions & 0 deletions src/audio/module_adapter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ endif()
iadk/system_agent.cpp
library/native_system_service.c
)
if(CONFIG_INTEL_MODULES AND CONFIG_COMP_KPB)
zephyr_library_sources(
iadk/kpb_service.cpp
library/kpb_service_bridge.c
)
endif()

zephyr_library_sources_ifdef(CONFIG_SOF_USERSPACE_PROXY
library/userspace_proxy.c
Expand Down
1 change: 1 addition & 0 deletions src/audio/module_adapter/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ endif # Cadence
config INTEL_MODULES
bool "Intel modules"
depends on LIBRARY_MANAGER
select KPB_NOTIFIER if COMP_KPB
help
Select for a Intel modules API implementation.
This will cause module adapter component to include IADK module
Expand Down
147 changes: 147 additions & 0 deletions src/audio/module_adapter/iadk/kpb_service.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright 2026 Intel Corporation. All rights reserved.

#include <rtos/userspace_helper.h>
#include <sof/audio/module_adapter/iadk/iadk_kpb_service.h>
#include <sof/audio/module_adapter/iadk/kpb_interface.h>
#include <sof/audio/module_adapter/library/kpb_service.h>

namespace intel_adsp
{

struct KpbToken {
Comment thread
serhiy-katsyuba-intel marked this conversation as resolved.
const ModuleHandle *owner;
void *kpb_client;
};

/**
* \class KpbServiceV1
* \brief SOF implementation of the KPB service v1 interface.
*/
class KpbServiceV1 final : public KpbInterface {
public:
ErrorCode::Type RegisterKpbClient(const ModuleHandle& module_handle, KpbToken& token,
size_t current_history_depth, size_t max_history_depth,
uint32_t output_pin) const override
{
struct kpb_service_client *client;
AdspErrorCode error = kpb_service_register_client(
current_history_depth,
max_history_depth,
output_pin, &client);
Comment thread
serhiy-katsyuba-intel marked this conversation as resolved.

if (error == ADSP_NO_ERROR) {
token.owner = &module_handle;
token.kpb_client = client;
}

return error;
}

ErrorCode::Type SignalDetection(KpbToken& token, void* data) const override
{
if (!token.owner || !token.kpb_client || !data)
return ADSP_INVALID_PARAMETERS;

return kpb_service_signal_detection(
reinterpret_cast<struct kpb_service_client *>(token.kpb_client),
*static_cast<uint32_t *>(data));
}

ErrorCode::Type SignalVoiceDetection(KpbToken&, void*) const override
{
return ADSP_NO_ERROR;
}

ErrorCode::Type SignalSilenceDetection(KpbToken&, void*) const override
{
return ADSP_NO_ERROR;
}

ErrorCode::Type UnregisterKpbClient(KpbToken& token) const override
{
if (!token.kpb_client) {
token.owner = NULL;
return ADSP_NO_ERROR;
}

AdspErrorCode error = kpb_service_unregister_client(
reinterpret_cast<struct kpb_service_client *>(token.kpb_client));

if (error == ADSP_NO_ERROR) {
token.owner = NULL;
token.kpb_client = NULL;
}

return error;
}

ErrorCode::Type RegisterWovProducer(const ModuleHandle&) const override
{
return ADSP_NO_ERROR;
}

ErrorCode::Type RegisterKpbProducer(const ModuleHandle&) const override
{
return ADSP_NO_ERROR;
}

ErrorCode::Type RequestWovConsumer(const ModuleHandle&) const override
{
return ADSP_NO_ERROR;
}
};

/**
* \class KpbServiceV2
* \brief KPB service v2 implemented as the compatible subset of v1.
*/
class KpbServiceV2 final : public KpbInterfaceV2 {
public:
ErrorCode::Type RegisterKpbClient(const ModuleHandle& module_handle, KpbToken& token,
size_t current_history_depth, size_t max_history_depth,
uint32_t output_pin) const override
{
return v1_.RegisterKpbClient(module_handle, token, current_history_depth,
max_history_depth, output_pin);
}

ErrorCode::Type SignalDetection(KpbToken& token, void* data) const override
{
return v1_.SignalDetection(token, data);
}

ErrorCode::Type UnregisterKpbClient(KpbToken& token) const override
{
return v1_.UnregisterKpbClient(token);
}

ErrorCode::Type RegisterKpbProducer(const ModuleHandle& module_handle) const override
{
return v1_.RegisterKpbProducer(module_handle);
}

private:
KpbServiceV1 v1_;
};

static APP_TASK_DATA KpbServiceV1 kpb_service_v1;
static APP_TASK_DATA KpbServiceV2 kpb_service_v2;

AdspErrorCode GetKpbServiceInterface(uint32_t version, struct system_service_iface **iface)
{
switch (version) {
case INTERFACE_VERSION_KPB_SERVICE_V1:
*iface = reinterpret_cast<struct system_service_iface *>(&kpb_service_v1);
return ADSP_NO_ERROR;
case INTERFACE_VERSION_KPB_SERVICE_V2:
*iface = reinterpret_cast<struct system_service_iface *>(&kpb_service_v2);
return ADSP_NO_ERROR;
default:
*iface = NULL;
return ADSP_SERVICE_VERSION_UNAVAILABLE;
}
}

} /* namespace intel_adsp */
39 changes: 37 additions & 2 deletions src/audio/module_adapter/iadk/system_agent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <module_initial_settings_concrete.h>
#include <iadk_module_adapter.h>
#include <system_agent.h>
#include <sof/audio/module_adapter/iadk/iadk_kpb_service.h>
#include <sof/audio/module_adapter/library/native_system_service.h>
#include <sof/audio/module_adapter/library/native_system_agent.h>

Expand All @@ -37,6 +38,40 @@ namespace intel_adsp
{
namespace system
{
/* IADK interfaces are C++ objects, not ABI-compatible with native ones: no native fallback */
static AdspErrorCode iadk_system_service_get_interface(enum interface_id id,
struct system_service_iface **iface)
{
if (!iface)
return ADSP_INVALID_PARAMETERS;

*iface = NULL;

#if CONFIG_COMP_KPB
if (id == INTERFACE_ID_KPB_SERVICE)
return GetKpbServiceInterface(INTERFACE_VERSION_KPB_SERVICE_V1, iface);
#endif

return ADSP_SERVICE_UNAVAILABLE;
}

static AdspErrorCode iadk_system_service_get_interface_versioned(enum interface_id id,
uint32_t version,
struct system_service_iface **iface)
{
if (!iface)
return ADSP_INVALID_PARAMETERS;

*iface = NULL;

#if CONFIG_COMP_KPB
if (id == INTERFACE_ID_KPB_SERVICE)
return GetKpbServiceInterface(version, iface);
#endif

return ADSP_SERVICE_UNAVAILABLE;
}

/* Structure storing handles to system service operations */
const APP_TASK_DATA AdspSystemService SystemAgent::system_service_ = {
native_system_service_log_message,
Expand All @@ -45,8 +80,8 @@ const APP_TASK_DATA AdspSystemService SystemAgent::system_service_ = {
native_system_service_vec_memset,
native_system_service_create_notification,
native_system_service_send_notif_msg,
native_system_service_get_interface,
native_system_service_get_interface_versioned,
iadk_system_service_get_interface,
iadk_system_service_get_interface_versioned,
};

SystemAgent::SystemAgent(uint32_t module_id,
Expand Down
Loading
Loading