diff --git a/src/audio/kpb.c b/src/audio/kpb.c index 5bf77e08c7e6..b3af7cfbe70b 100644 --- a/src/audio/kpb.c +++ b/src/audio/kpb.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -47,6 +46,13 @@ #include #include #include +#if CONFIG_AMS +#include +#include +#include +#else +#include +#endif static const struct comp_driver comp_kpb; @@ -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, @@ -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) @@ -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); @@ -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; } @@ -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; @@ -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 /* Finally KPB is ready after reset */ kpb_change_state(kpb, KPB_STATE_PREPARING); @@ -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. @@ -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. diff --git a/src/include/ipc4/ams_helpers.h b/src/include/ipc4/ams_helpers.h new file mode 100644 index 000000000000..35c9557a733b --- /dev/null +++ b/src/include/ipc4/ams_helpers.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2023 Intel Corporation + * + * Author: Ievgen Ganakov + */ + +#ifndef __SOF_LIB_AMS_HELPERS_H__ +#define __SOF_LIB_AMS_HELPERS_H__ + +#include +#include +#include + +#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__ */ diff --git a/src/include/sof/lib/ams_msg.h b/src/include/sof/lib/ams_msg.h new file mode 100644 index 000000000000..9c1ad5ce6efb --- /dev/null +++ b/src/include/sof/lib/ams_msg.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2023 Intel Corporation + * + * Author: Ievgen Ganakov + */ + +#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__ */ diff --git a/src/ipc/ipc4/CMakeLists.txt b/src/ipc/ipc4/CMakeLists.txt index 536c3035822f..7f9d75f654be 100644 --- a/src/ipc/ipc4/CMakeLists.txt +++ b/src/ipc/ipc4/CMakeLists.txt @@ -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) diff --git a/src/ipc/ipc4/ams_helpers.c b/src/ipc/ipc4/ams_helpers.c new file mode 100644 index 000000000000..6f21ee3e3623 --- /dev/null +++ b/src/ipc/ipc4/ams_helpers.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Ievgen Ganakov + */ + +#include +#include + +#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 */ diff --git a/src/platform/Kconfig b/src/platform/Kconfig index 64a86a6d2d64..4ff8f624c7fb 100644 --- a/src/platform/Kconfig +++ b/src/platform/Kconfig @@ -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. diff --git a/src/samples/audio/detect_test.c b/src/samples/audio/detect_test.c index 0aeaa4299543..5c6903e07794 100644 --- a/src/samples/audio/detect_test.c +++ b/src/samples/audio/detect_test.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -41,6 +40,13 @@ #include #include #include +#if CONFIG_AMS +#include +#include +#include +#else +#include +#endif #define ACTIVATION_DEFAULT_SHIFT 3 #define ACTIVATION_DEFAULT_COEF 0.05 @@ -85,7 +91,6 @@ struct comp_data { uint32_t keyphrase_samples; /**< keyphrase length in samples */ uint32_t drain_req; /** defines draining size in bytes. */ uint16_t sample_valid_bytes; - struct kpb_event_data event_data; struct kpb_client client_data; #if CONFIG_KWD_NN_SAMPLE_KEYPHRASE @@ -98,6 +103,12 @@ struct comp_data { void (*detect_func)(struct comp_dev *dev, const struct audio_stream __sparse_cache *source, uint32_t frames); struct sof_ipc_comp_event event; + +#if CONFIG_AMS + uint32_t kpd_uuid_id; +#else + struct kpb_event_data event_data; +#endif /* CONFIG_AMS */ }; static inline bool detector_is_sample_width_supported(enum sof_ipc_frame sf) @@ -140,6 +151,31 @@ static void notify_host(const struct comp_dev *dev) #endif /* CONFIG_IPC_MAJOR_4 */ } +#if CONFIG_AMS + +/* Key-phrase detected message*/ +static const ams_uuid_t ams_kpd_msg_uuid = AMS_KPD_MSG_UUID; + +static int ams_notify_kpb(const struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + struct ams_message_payload ams_payload; + + cd->client_data.r_ptr = NULL; + cd->client_data.sink = NULL; + cd->client_data.id = 0; /**< TODO: acquire proper id from kpb */ + /* time in milliseconds */ + cd->client_data.drain_req = (cd->drain_req != 0) ? + cd->drain_req : + cd->config.drain_req; + + ams_helper_prepare_payload(dev, &ams_payload, cd->kpd_uuid_id, + (uint8_t *)&cd->client_data, + sizeof(struct kpb_client)); + + return ams_send(&ams_payload); +} +#else static void notify_kpb(const struct comp_dev *dev) { struct comp_data *cd = comp_get_drvdata(dev); @@ -160,11 +196,16 @@ static void notify_kpb(const struct comp_dev *dev) NOTIFIER_TARGET_CORE_ALL_MASK, &cd->event_data, sizeof(cd->event_data)); } +#endif /* CONFIG_AMS */ void detect_test_notify(const struct comp_dev *dev) { notify_host(dev); +#if CONFIG_AMS + ams_notify_kpb(dev); +#else notify_kpb(dev); +#endif } static void default_detect_test(struct comp_dev *dev, @@ -719,6 +760,15 @@ static void test_keyword_free(struct comp_dev *dev) comp_info(dev, "test_keyword_free()"); +#if CONFIG_AMS + int ret; + + /* Unregister KD as AMS producer */ + ret = ams_helper_unregister_producer(dev, cd->kpd_uuid_id); + if (ret) + comp_err(dev, "test_keyword_free(): unregister ams error %d", ret); +#endif + ipc_msg_free(cd->msg); comp_data_blob_handler_free(cd->model_handler); rfree(cd); @@ -796,6 +846,10 @@ static int test_keyword_params(struct comp_dev *dev, return err; } +#if CONFIG_AMS + cd->kpd_uuid_id = AMS_INVALID_MSG_TYPE; +#endif /* CONFIG_AMS */ + cd->config.activation_threshold = err; return 0; @@ -874,6 +928,7 @@ static int test_keyword_prepare(struct comp_dev *dev) struct comp_data *cd = comp_get_drvdata(dev); uint16_t valid_bits = cd->sample_valid_bytes * 8; uint16_t sample_width; + int ret; #if CONFIG_IPC_MAJOR_4 sample_width = cd->base_cfg.audio_fmt.depth; @@ -887,7 +942,7 @@ static int test_keyword_prepare(struct comp_dev *dev) /* Default threshold value has to be changed * according to host new format. */ - int ret = test_keyword_get_threshold(dev, valid_bits); + ret = test_keyword_get_threshold(dev, valid_bits); if (ret < 0) { comp_err(dev, "test_keyword_prepare(): unsupported sample width %u", @@ -902,6 +957,14 @@ static int test_keyword_prepare(struct comp_dev *dev) &cd->data_blob_size, &cd->data_blob_crc); +#if CONFIG_AMS + /* Register KD as AMS producer */ + ret = ams_helper_register_producer(dev, &cd->kpd_uuid_id, + ams_kpd_msg_uuid); + if (ret) + return ret; +#endif + return comp_set_state(dev, COMP_TRIGGER_PREPARE); } diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 2d7759bdee6f..0ac5c35476b7 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -721,6 +721,7 @@ zephyr_library_sources_ifdef(CONFIG_HAVE_AGENT zephyr_library_sources_ifdef(CONFIG_AMS ${SOF_LIB_PATH}/ams.c + ${SOF_IPC_PATH}/ipc4/ams_helpers.c ) zephyr_library_sources_ifdef(CONFIG_GDB_DEBUG