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
59 changes: 58 additions & 1 deletion src/audio/kpb.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
#include <rtos/clk.h>
#include <rtos/init.h>
#include <sof/lib/memory.h>
#include <sof/lib/notifier.h>
#include <sof/lib/pm_runtime.h>
#include <sof/lib/uuid.h>
#include <sof/list.h>
Expand All @@ -47,6 +46,13 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#if CONFIG_AMS
#include <sof/lib/ams.h>
#include <sof/lib/ams_msg.h>
#include <ipc4/ams_helpers.h>
#else
#include <sof/lib/notifier.h>
#endif

static const struct comp_driver comp_kpb;

Expand Down Expand Up @@ -100,11 +106,17 @@ struct comp_data {
uint32_t num_of_in_channels;
uint32_t offsets[KPB_MAX_MICSEL_CHANNELS];
struct kpb_micselector_config mic_sel;

#if CONFIG_AMS
uint32_t kpd_uuid_id;
#endif
};

/*! KPB private functions */
#ifndef CONFIG_AMS
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 @@ -135,6 +147,25 @@ static uint64_t kpb_task_deadline(void *data)
return SOF_TASK_DEADLINE_ALMOST_IDLE;
}

#if CONFIG_AMS

/* Key-phrase detected message*/
static const ams_uuid_t ams_kpd_msg_uuid = AMS_KPD_MSG_UUID;

/* Key-phrase detected notification handler*/
static void kpb_ams_kpd_notification(const struct ams_message_payload *const ams_message_payload,
void *ctx)
{
struct kpb_client *cli_data = (struct kpb_client *)ams_message_payload->message;
struct comp_dev *dev = ctx;

comp_dbg(dev, "kpb_ams_kpd_notification()");

kpb_init_draining(dev, cli_data);
}

#endif /* CONFIG_AMS */

#ifdef __ZEPHYR__

static void kpb_lock(struct comp_data *kpb)
Expand Down Expand Up @@ -620,8 +651,18 @@ static void kpb_free(struct comp_dev *dev)

comp_info(dev, "kpb_free()");

#if CONFIG_AMS
/* Unregister KPB as AMS consumer */
int ret;

ret = ams_helper_unregister_consumer(dev, kpb->kpd_uuid_id,
kpb_ams_kpd_notification);
if (ret)
comp_err(dev, "kpb_free(): AMS unregister error %d", ret);
#else
/* Unregister KPB from notifications */
notifier_unregister(dev, NULL, NOTIFIER_ID_KPB_CLIENT_EVT);
#endif/* CONFIG_AMS */

/* Reclaim memory occupied by history buffer */
kpb_free_history_buffer(kpb->hd.c_hb);
Expand Down Expand Up @@ -697,6 +738,10 @@ static int kpb_params(struct comp_dev *dev,
kpb->host_period_size = params->host_period_bytes;
kpb->config.sampling_width = params->sample_container_bytes * 8;

#if CONFIG_AMS
kpb->kpd_uuid_id = AMS_INVALID_MSG_TYPE;
#endif

return 0;
}

Expand Down Expand Up @@ -772,9 +817,17 @@ static int kpb_prepare(struct comp_dev *dev)
kpb->clients[i].r_ptr = NULL;
}

#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 */
ret = notifier_register(dev, NULL, NOTIFIER_ID_KPB_CLIENT_EVT,
kpb_event_handler, 0);
#endif /* CONFIG_AMS */

if (ret < 0) {
kpb_free_history_buffer(kpb->hd.c_hb);
kpb->hd.c_hb = NULL;
Expand Down Expand Up @@ -917,8 +970,10 @@ static int kpb_reset(struct comp_dev *dev)
kpb_reset_history_buffer(kpb->hd.c_hb);
}

#ifndef CONFIG_AMS
/* Unregister KPB from notifications */
notifier_unregister(dev, NULL, NOTIFIER_ID_KPB_CLIENT_EVT);
#endif
Copy link
Collaborator

Choose a reason for hiding this comment

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

no need to unregister AMS 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.

No, there is no need to unregister AMS here. kpb_reset() is called during PIPELINE_RESET state. RESET on pipeline could be called in two cases:

  1. Init -> Reset -> Pause -> Running
  2. Pause -> Reset -> Delete

So calling ams_helper_unregister_consumer() in kpb_free() will be sufficient.

Copy link
Collaborator

Choose a reason for hiding this comment

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

then why is notifier_unregister() called both in reset and free? Is that superfluous?

/* Finally KPB is ready after reset */
kpb_change_state(kpb, KPB_STATE_PREPARING);

Expand Down Expand Up @@ -1422,6 +1477,7 @@ 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.
Expand Down Expand Up @@ -1501,6 +1557,7 @@ static int kpb_register_client(struct comp_data *kpb, struct kpb_client *cli)

return ret;
}
#endif /* CONFIG_AMS */

/**
* \brief Prepare history buffer for draining.
Expand Down
41 changes: 41 additions & 0 deletions src/include/ipc4/ams_helpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 2023 Intel Corporation
*
* Author: Ievgen Ganakov <ievgen.ganakov@intel.com>
*/

#ifndef __SOF_LIB_AMS_HELPERS_H__
#define __SOF_LIB_AMS_HELPERS_H__

#include <sof/lib/ams.h>
#include <sof/lib/ams_msg.h>
#include <stdint.h>

#if CONFIG_AMS

int ams_helper_register_producer(const struct comp_dev *dev,
uint32_t *ams_uuid_id,
const uint8_t *msg_uuid);

int ams_helper_unregister_producer(const struct comp_dev *dev,
uint32_t ams_uuid_id);

int ams_helper_register_consumer(struct comp_dev *dev,
uint32_t *ams_uuid_id,
const uint8_t *msg_uuid,
ams_msg_callback_fn callback);

int ams_helper_unregister_consumer(struct comp_dev *dev,
uint32_t ams_uuid_id,
ams_msg_callback_fn callback);

void ams_helper_prepare_payload(const struct comp_dev *dev,
struct ams_message_payload *payload,
uint32_t ams_uuid_id,
uint8_t *message,
size_t message_size);

#endif /* CONFIG_AMS */

#endif /* __SOF_LIB_AMS_HELPERS_H__ */
18 changes: 18 additions & 0 deletions src/include/sof/lib/ams_msg.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 2023 Intel Corporation
*
* Author: Ievgen Ganakov <ievgen.ganakov@intel.com>
*/

#ifndef __SOF_LIB_AMS_MSG_H__
#define __SOF_LIB_AMS_MSG_H__

/* AMS messages */
typedef uint8_t ams_uuid_t[16];

/* Key-phrase detected AMS message uuid: 80a11122-b36c-11ed-afa1-0242ac120002*/
#define AMS_KPD_MSG_UUID { 0x80, 0xa1, 0x11, 0x22, 0xb3, 0x6c, 0x11, 0xed, \
0xaf, 0xa1, 0x02, 0x42, 0xac, 0x12, 0x00, 0x02 }

#endif /* __SOF_LIB_AMS_MSG_H__ */
1 change: 1 addition & 0 deletions src/ipc/ipc4/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ add_local_sources(sof
helper.c
logging.c
notification.c
ams_helpers.c
)

target_include_directories(sof_options INTERFACE ${PROJECT_SOURCE_DIR}/rimage/src/include)
79 changes: 79 additions & 0 deletions src/ipc/ipc4/ams_helpers.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright(c) 2023 Intel Corporation. All rights reserved.
*
* Author: Ievgen Ganakov <ievgen.ganakov@intel.com>
*/

#include <ipc4/ams_helpers.h>
#include <sof/audio/component.h>

#if CONFIG_AMS

int ams_helper_register_producer(const struct comp_dev *dev,
uint32_t *ams_uuid_id,
const uint8_t *msg_uuid)
{
uint16_t mod_id = IPC4_MOD_ID(dev_comp_id(dev));
uint16_t inst_id = IPC4_INST_ID(dev_comp_id(dev));
int ret;

ret = ams_get_message_type_id(msg_uuid, ams_uuid_id);
if (ret)
return ret;

return ams_register_producer(*ams_uuid_id, mod_id, inst_id);
}

int ams_helper_unregister_producer(const struct comp_dev *dev,
uint32_t ams_uuid_id)
{
uint16_t mod_id = IPC4_MOD_ID(dev_comp_id(dev));
uint16_t inst_id = IPC4_INST_ID(dev_comp_id(dev));

return ams_unregister_producer(ams_uuid_id, mod_id, inst_id);
}

int ams_helper_register_consumer(struct comp_dev *dev,
uint32_t *ams_uuid_id,
const uint8_t *msg_uuid,
ams_msg_callback_fn callback)
{
uint16_t mod_id = IPC4_MOD_ID(dev_comp_id(dev));
uint16_t inst_id = IPC4_INST_ID(dev_comp_id(dev));
int ret;

ret = ams_get_message_type_id(msg_uuid, ams_uuid_id);
if (ret)
return ret;

return ams_register_consumer(*ams_uuid_id, mod_id, inst_id, callback, dev);
}

int ams_helper_unregister_consumer(struct comp_dev *dev,
uint32_t ams_uuid_id,
ams_msg_callback_fn callback)
{
uint16_t mod_id = IPC4_MOD_ID(dev_comp_id(dev));
uint16_t inst_id = IPC4_INST_ID(dev_comp_id(dev));

return ams_unregister_consumer(ams_uuid_id, mod_id, inst_id, callback);
}

void ams_helper_prepare_payload(const struct comp_dev *dev,
struct ams_message_payload *payload,
uint32_t ams_uuid_id,
uint8_t *message,
size_t message_size)
{
uint16_t mod_id = IPC4_MOD_ID(dev_comp_id(dev));
uint16_t inst_id = IPC4_INST_ID(dev_comp_id(dev));

payload->message_type_id = ams_uuid_id;
payload->producer_module_id = mod_id;
payload->producer_instance_id = inst_id;
payload->message_length = message_size;
payload->message = message;
}

#endif /* CONFIG_AMS */
1 change: 1 addition & 0 deletions src/platform/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ config HAVE_AGENT
config AMS
bool "Enable Async Messaging Service"
default n
depends on IPC_MAJOR_4
help
Enables Async Messaging Service.
Async messages are used to send messages between modules.
Expand Down
Loading