diff --git a/src/audio/CMakeLists.txt b/src/audio/CMakeLists.txt index 538048b1c..daa529e42 100644 --- a/src/audio/CMakeLists.txt +++ b/src/audio/CMakeLists.txt @@ -184,6 +184,7 @@ if(CONFIG_IPC_MAJOR_3) set(tdfb_sources tdfb/tdfb_ipc3.c) set(tdfb_sources multiband_drc/multiband_drc_ipc3.c) set(dcblock_sources dcblock/dcblock_ipc3.c) + set(mux_sources mux/mux_ipc3.c) elseif(CONFIG_IPC_MAJOR_4) set(volume_sources volume/volume.c volume/volume_generic.c volume/volume_ipc4.c) set(asrc_sources asrc/asrc_ipc4.c) @@ -193,6 +194,7 @@ elseif(CONFIG_IPC_MAJOR_4) set(tdfb_sources tdfb/tdfb_ipc4.c) set(tdfb_sources multiband_drc/multiband_drc_ipc4.c) set(dcblock_sources dcblock/dcblock_ipc4.c) + set(mux_sources mux/mux_ipc4.c) endif() set(mixer_sources ${mixer_src}) set(asrc_sources asrc/asrc.c asrc/asrc_farrow.c asrc/asrc_farrow_generic.c) diff --git a/src/audio/mux/CMakeLists.txt b/src/audio/mux/CMakeLists.txt index ff6bec28f..a7b890cb3 100644 --- a/src/audio/mux/CMakeLists.txt +++ b/src/audio/mux/CMakeLists.txt @@ -1,3 +1,10 @@ # SPDX-License-Identifier: BSD-3-Clause add_local_sources(sof mux.c mux_generic.c) + +if(CONFIG_IPC_MAJOR_3) + add_local_sources(sof mux_ipc3.c) +elseif(CONFIG_IPC_MAJOR_4) + add_local_sources(sof mux_ipc4.c) +endif() + diff --git a/src/audio/mux/mux.c b/src/audio/mux/mux.c index cf6bd43c4..05da3493e 100644 --- a/src/audio/mux/mux.c +++ b/src/audio/mux/mux.c @@ -33,28 +33,8 @@ #include "mux.h" -#define MUX_BLOB_STREAMS_SIZE (MUX_MAX_STREAMS * sizeof(struct mux_stream_data)) -#define MUX_BLOB_MAX_SIZE (sizeof(struct sof_mux_config) + MUX_BLOB_STREAMS_SIZE) - LOG_MODULE_REGISTER(muxdemux, CONFIG_SOF_LOG_LEVEL); -#if CONFIG_IPC_MAJOR_3 -/* c607ff4d-9cb6-49dc-b678-7da3c63ea557 */ -DECLARE_SOF_RT_UUID("mux", mux_uuid, 0xc607ff4d, 0x9cb6, 0x49dc, - 0xb6, 0x78, 0x7d, 0xa3, 0xc6, 0x3e, 0xa5, 0x57); -#else -/* 64ce6e35-857a-4878-ace8-e2a2f42e3069 */ -DECLARE_SOF_RT_UUID("mux", mux_uuid, 0x64ce6e35, 0x857a, 0x4878, - 0xac, 0xe8, 0xe2, 0xa2, 0xf4, 0x2e, 0x30, 0x69); -#endif -DECLARE_TR_CTX(mux_tr, SOF_UUID(mux_uuid), LOG_LEVEL_INFO); - -/* c4b26868-1430-470e-a089-15d1c77f851a */ -DECLARE_SOF_RT_UUID("demux", demux_uuid, 0xc4b26868, 0x1430, 0x470e, - 0xa0, 0x89, 0x15, 0xd1, 0xc7, 0x7f, 0x85, 0x1a); - -DECLARE_TR_CTX(demux_tr, SOF_UUID(demux_uuid), LOG_LEVEL_INFO); - /* * Check that we are not configuring routing matrix for mixing. * @@ -62,7 +42,7 @@ DECLARE_TR_CTX(demux_tr, SOF_UUID(demux_uuid), LOG_LEVEL_INFO); * have 1's in corresponding matrix indices. Also single stream matrix can't * have 1's in same column as that corresponds to mixing also. */ -static bool mux_mix_check(struct sof_mux_config *cfg) +bool mux_mix_check(struct sof_mux_config *cfg) { bool channel_set; int i; @@ -102,109 +82,6 @@ static bool mux_mix_check(struct sof_mux_config *cfg) return false; } -#if CONFIG_IPC_MAJOR_3 -static int mux_set_values(struct processing_module *mod) -{ - struct comp_data *cd = module_get_private_data(mod); - struct comp_dev *dev = mod->dev; - struct sof_mux_config *cfg = &cd->config; - unsigned int i; - unsigned int j; - - comp_dbg(dev, "mux_set_values()"); - - /* check if number of streams configured doesn't exceed maximum */ - if (cfg->num_streams > MUX_MAX_STREAMS) { - comp_err(dev, "mux_set_values(): configured number of streams (%u) exceeds maximum = " - META_QUOTE(MUX_MAX_STREAMS), cfg->num_streams); - return -EINVAL; - } - - /* check if all streams configured have distinct IDs */ - for (i = 0; i < cfg->num_streams; i++) { - for (j = i + 1; j < cfg->num_streams; j++) { - if (cfg->streams[i].pipeline_id == - cfg->streams[j].pipeline_id) { - comp_err(dev, "mux_set_values(): multiple configured streams have same pipeline ID = %u", - cfg->streams[i].pipeline_id); - return -EINVAL; - } - } - } - - for (i = 0; i < cfg->num_streams; i++) { - for (j = 0 ; j < PLATFORM_MAX_CHANNELS; j++) { - if (popcount(cfg->streams[i].mask[j]) > 1) { - comp_err(dev, "mux_set_values(): mux component is not able to mix channels"); - return -EINVAL; - } - } - } - - if (dev->ipc_config.type == SOF_COMP_MUX) { - if (mux_mix_check(cfg)) - comp_err(dev, "mux_set_values(): mux component is not able to mix channels"); - } - - for (i = 0; i < cfg->num_streams; i++) { - cd->config.streams[i].pipeline_id = cfg->streams[i].pipeline_id; - for (j = 0; j < PLATFORM_MAX_CHANNELS; j++) - cd->config.streams[i].mask[j] = cfg->streams[i].mask[j]; - } - - cd->config.num_streams = cfg->num_streams; - - if (dev->ipc_config.type == SOF_COMP_MUX) - mux_prepare_look_up_table(mod); - else - demux_prepare_look_up_table(mod); - - if (dev->state > COMP_STATE_INIT) { - if (dev->ipc_config.type == SOF_COMP_MUX) - cd->mux = mux_get_processing_function(mod); - else - cd->demux = demux_get_processing_function(mod); - } - - return 0; -} -#endif /* CONFIG_IPC_MAJOR_3 */ - -#if CONFIG_IPC_MAJOR_4 -static int build_config(struct processing_module *mod) -{ - struct comp_dev *dev = mod->dev; - struct comp_data *cd = module_get_private_data(mod); - int mask = 1; - int i; - - dev->ipc_config.type = SOF_COMP_MUX; - cd->config.num_streams = MUX_MAX_STREAMS; - - /* clear masks */ - for (i = 0; i < cd->config.num_streams; i++) - memset(cd->config.streams[i].mask, 0, sizeof(cd->config.streams[i].mask)); - - /* Setting masks for streams */ - for (i = 0; i < cd->md.base_cfg.audio_fmt.channels_count; i++) { - cd->config.streams[0].mask[i] = mask; - mask <<= 1; - } - - for (i = 0; i < cd->md.reference_format.channels_count; i++) { - cd->config.streams[1].mask[i] = mask; - mask <<= 1; - } - - /* validation of matrix mixing */ - if (mux_mix_check(&cd->config)) { - comp_err(dev, "build_config(): mux component is not able to mix channels"); - return -EINVAL; - } - return 0; -} -#endif - static int mux_demux_common_init(struct processing_module *mod) { struct module_data *module_data = &mod->priv; @@ -265,73 +142,6 @@ static int demux_init(struct processing_module *mod) return mux_demux_common_init(mod); } -#if CONFIG_IPC_MAJOR_4 -/* In ipc4 case param is figured out by module config so we need to first - * set up param then verify param. BTW for IPC3 path, the param is sent by - * host driver. - */ -static void set_mux_params(struct processing_module *mod) -{ - struct sof_ipc_stream_params *params = mod->stream_params; - struct comp_data *cd = module_get_private_data(mod); - struct comp_dev *dev = mod->dev; - struct comp_buffer *sink, *source; - struct list_item *source_list; - int j; - const uint32_t byte_align = 1; - const uint32_t frame_align_req = 1; - - params->direction = dev->direction; - params->channels = cd->md.base_cfg.audio_fmt.channels_count; - params->rate = cd->md.base_cfg.audio_fmt.sampling_frequency; - params->sample_container_bytes = cd->md.base_cfg.audio_fmt.depth / 8; - params->sample_valid_bytes = cd->md.base_cfg.audio_fmt.valid_bit_depth / 8; - params->buffer_fmt = cd->md.base_cfg.audio_fmt.interleaving_style; - params->buffer.size = cd->md.base_cfg.ibs; - params->no_stream_position = 1; - - /* There are two input pins and one output pin in the mux. - * For the first input we assign parameters from base_cfg, - * for the second from reference_format - * and for sink output_format. - */ - - /* update sink format */ - if (!list_is_empty(&dev->bsink_list)) { - sink = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); - audio_stream_init_alignment_constants(byte_align, frame_align_req, - &sink->stream); - - if (!sink->hw_params_configured) { - ipc4_update_buffer_format(sink, &cd->md.output_format); - params->frame_fmt = audio_stream_get_frm_fmt(&sink->stream); - } - } - - /* update each source format */ - if (!list_is_empty(&dev->bsource_list)) { - struct ipc4_audio_format *audio_fmt; - - list_for_item(source_list, &dev->bsource_list) - { - source = container_of(source_list, struct comp_buffer, sink_list); - audio_stream_init_alignment_constants(byte_align, frame_align_req, - &source->stream); - j = buf_get_id(source); - cd->config.streams[j].pipeline_id = source->pipeline_id; - if (j == BASE_CFG_QUEUED_ID) - audio_fmt = &cd->md.base_cfg.audio_fmt; - else - audio_fmt = &cd->md.reference_format; - - ipc4_update_buffer_format(source, audio_fmt); - } - } - - mux_prepare_look_up_table(mod); -} -#endif /* CONFIG_IPC_MAJOR_4 */ - static int mux_free(struct processing_module *mod) { @@ -583,18 +393,10 @@ static int mux_prepare(struct processing_module *mod, memcpy_s(&cd->config, MUX_BLOB_MAX_SIZE, config, blob_size); -#if CONFIG_IPC_MAJOR_4 - ret = build_config(mod); -#else - ret = mux_set_values(mod); -#endif + ret = mux_params(mod); if (ret < 0) return ret; -#if CONFIG_IPC_MAJOR_4 - set_mux_params(mod); -#endif - if (dev->ipc_config.type == SOF_COMP_MUX) cd->mux = mux_get_processing_function(mod); else diff --git a/src/audio/mux/mux.h b/src/audio/mux/mux.h index e8eb9bc9d..d4ff8e2de 100644 --- a/src/audio/mux/mux.h +++ b/src/audio/mux/mux.h @@ -16,11 +16,14 @@ #if CONFIG_COMP_MUX +#include #include #include #include #include +#include #include +#include #include #if CONFIG_IPC_MAJOR_4 #include @@ -210,6 +213,17 @@ void sys_comp_module_demux_interface_init(void); #endif /* UNIT_TEST */ +#define MUX_BLOB_STREAMS_SIZE (MUX_MAX_STREAMS * sizeof(struct mux_stream_data)) +#define MUX_BLOB_MAX_SIZE (sizeof(struct sof_mux_config) + MUX_BLOB_STREAMS_SIZE) + +extern const struct sof_uuid mux_uuid; +extern const struct sof_uuid demux_uuid; +extern struct tr_ctx mux_tr; +extern struct tr_ctx demux_tr; + +bool mux_mix_check(struct sof_mux_config *cfg); +int mux_params(struct processing_module *mod); + #endif /* CONFIG_COMP_MUX */ #endif /* __SOF_AUDIO_MUX_H__ */ diff --git a/src/audio/mux/mux_ipc3.c b/src/audio/mux/mux_ipc3.c new file mode 100644 index 000000000..77cb035a7 --- /dev/null +++ b/src/audio/mux/mux_ipc3.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood +// Artur Kloniecki + +#if CONFIG_COMP_MUX + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mux.h" + +LOG_MODULE_DECLARE(muxdemux, CONFIG_SOF_LOG_LEVEL); + +/* c607ff4d-9cb6-49dc-b678-7da3c63ea557 */ +DECLARE_SOF_RT_UUID("mux", mux_uuid, 0xc607ff4d, 0x9cb6, 0x49dc, + 0xb6, 0x78, 0x7d, 0xa3, 0xc6, 0x3e, 0xa5, 0x57); + +DECLARE_TR_CTX(mux_tr, SOF_UUID(mux_uuid), LOG_LEVEL_INFO); + +/* c4b26868-1430-470e-a089-15d1c77f851a */ +DECLARE_SOF_RT_UUID("demux", demux_uuid, 0xc4b26868, 0x1430, 0x470e, + 0xa0, 0x89, 0x15, 0xd1, 0xc7, 0x7f, 0x85, 0x1a); + +DECLARE_TR_CTX(demux_tr, SOF_UUID(demux_uuid), LOG_LEVEL_INFO); + +static int mux_set_values(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct sof_mux_config *cfg = &cd->config; + unsigned int i; + unsigned int j; + + comp_dbg(dev, "mux_set_values()"); + + /* check if number of streams configured doesn't exceed maximum */ + if (cfg->num_streams > MUX_MAX_STREAMS) { + comp_err(dev, "mux_set_values(): configured number of streams (%u) exceeds maximum = " + META_QUOTE(MUX_MAX_STREAMS), cfg->num_streams); + return -EINVAL; + } + + /* check if all streams configured have distinct IDs */ + for (i = 0; i < cfg->num_streams; i++) { + for (j = i + 1; j < cfg->num_streams; j++) { + if (cfg->streams[i].pipeline_id == + cfg->streams[j].pipeline_id) { + comp_err(dev, "mux_set_values(): multiple configured streams have same pipeline ID = %u", + cfg->streams[i].pipeline_id); + return -EINVAL; + } + } + } + + for (i = 0; i < cfg->num_streams; i++) { + for (j = 0 ; j < PLATFORM_MAX_CHANNELS; j++) { + if (popcount(cfg->streams[i].mask[j]) > 1) { + comp_err(dev, "mux_set_values(): mux component is not able to mix channels"); + return -EINVAL; + } + } + } + + if (dev->ipc_config.type == SOF_COMP_MUX) { + if (mux_mix_check(cfg)) + comp_err(dev, "mux_set_values(): mux component is not able to mix channels"); + } + + for (i = 0; i < cfg->num_streams; i++) { + cd->config.streams[i].pipeline_id = cfg->streams[i].pipeline_id; + for (j = 0; j < PLATFORM_MAX_CHANNELS; j++) + cd->config.streams[i].mask[j] = cfg->streams[i].mask[j]; + } + + cd->config.num_streams = cfg->num_streams; + + if (dev->ipc_config.type == SOF_COMP_MUX) + mux_prepare_look_up_table(mod); + else + demux_prepare_look_up_table(mod); + + if (dev->state > COMP_STATE_INIT) { + if (dev->ipc_config.type == SOF_COMP_MUX) + cd->mux = mux_get_processing_function(mod); + else + cd->demux = demux_get_processing_function(mod); + } + + return 0; +} + +int mux_params(struct processing_module *mod) +{ + return mux_set_values(mod); +} +#endif /* CONFIG_COMP_MUX */ diff --git a/src/audio/mux/mux_ipc4.c b/src/audio/mux/mux_ipc4.c new file mode 100644 index 000000000..ada22b273 --- /dev/null +++ b/src/audio/mux/mux_ipc4.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood +// Artur Kloniecki + +#if CONFIG_COMP_MUX + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mux.h" + +LOG_MODULE_DECLARE(muxdemux, CONFIG_SOF_LOG_LEVEL); + +/* 64ce6e35-857a-4878-ace8-e2a2f42e3069 */ +DECLARE_SOF_RT_UUID("mux", mux_uuid, 0x64ce6e35, 0x857a, 0x4878, + 0xac, 0xe8, 0xe2, 0xa2, 0xf4, 0x2e, 0x30, 0x69); + +DECLARE_TR_CTX(mux_tr, SOF_UUID(mux_uuid), LOG_LEVEL_INFO); + +/* c4b26868-1430-470e-a089-15d1c77f851a */ +DECLARE_SOF_RT_UUID("demux", demux_uuid, 0xc4b26868, 0x1430, 0x470e, + 0xa0, 0x89, 0x15, 0xd1, 0xc7, 0x7f, 0x85, 0x1a); + +DECLARE_TR_CTX(demux_tr, SOF_UUID(demux_uuid), LOG_LEVEL_INFO); + +static int build_config(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + struct comp_data *cd = module_get_private_data(mod); + int mask = 1; + int i; + + dev->ipc_config.type = SOF_COMP_MUX; + cd->config.num_streams = MUX_MAX_STREAMS; + + /* clear masks */ + for (i = 0; i < cd->config.num_streams; i++) + memset(cd->config.streams[i].mask, 0, sizeof(cd->config.streams[i].mask)); + + /* Setting masks for streams */ + for (i = 0; i < cd->md.base_cfg.audio_fmt.channels_count; i++) { + cd->config.streams[0].mask[i] = mask; + mask <<= 1; + } + + for (i = 0; i < cd->md.reference_format.channels_count; i++) { + cd->config.streams[1].mask[i] = mask; + mask <<= 1; + } + + /* validation of matrix mixing */ + if (mux_mix_check(&cd->config)) { + comp_err(dev, "build_config(): mux component is not able to mix channels"); + return -EINVAL; + } + return 0; +} + +/* In ipc4 case param is figured out by module config so we need to first + * set up param then verify param. BTW for IPC3 path, the param is sent by + * host driver. + */ +static void set_mux_params(struct processing_module *mod) +{ + struct sof_ipc_stream_params *params = mod->stream_params; + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct comp_buffer *sink, *source; + struct list_item *source_list; + int j; + const uint32_t byte_align = 1; + const uint32_t frame_align_req = 1; + + params->direction = dev->direction; + params->channels = cd->md.base_cfg.audio_fmt.channels_count; + params->rate = cd->md.base_cfg.audio_fmt.sampling_frequency; + params->sample_container_bytes = cd->md.base_cfg.audio_fmt.depth / 8; + params->sample_valid_bytes = cd->md.base_cfg.audio_fmt.valid_bit_depth / 8; + params->buffer_fmt = cd->md.base_cfg.audio_fmt.interleaving_style; + params->buffer.size = cd->md.base_cfg.ibs; + params->no_stream_position = 1; + + /* There are two input pins and one output pin in the mux. + * For the first input we assign parameters from base_cfg, + * for the second from reference_format + * and for sink output_format. + */ + + /* update sink format */ + if (!list_is_empty(&dev->bsink_list)) { + sink = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); + audio_stream_init_alignment_constants(byte_align, frame_align_req, + &sink->stream); + + if (!sink->hw_params_configured) { + ipc4_update_buffer_format(sink, &cd->md.output_format); + params->frame_fmt = audio_stream_get_frm_fmt(&sink->stream); + } + } + + /* update each source format */ + if (!list_is_empty(&dev->bsource_list)) { + struct ipc4_audio_format *audio_fmt; + + list_for_item(source_list, &dev->bsource_list) + { + source = container_of(source_list, struct comp_buffer, sink_list); + audio_stream_init_alignment_constants(byte_align, frame_align_req, + &source->stream); + j = buf_get_id(source); + cd->config.streams[j].pipeline_id = source->pipeline_id; + if (j == BASE_CFG_QUEUED_ID) + audio_fmt = &cd->md.base_cfg.audio_fmt; + else + audio_fmt = &cd->md.reference_format; + + ipc4_update_buffer_format(source, audio_fmt); + } + } + + mux_prepare_look_up_table(mod); +} + +int mux_params(struct processing_module *mod) +{ + int ret; + + ret = build_config(mod); + if (ret < 0) + return ret; + + set_mux_params(mod); + + return ret; +} +#endif /* CONFIG_COMP_MUX */ diff --git a/test/cmocka/src/audio/mux/CMakeLists.txt b/test/cmocka/src/audio/mux/CMakeLists.txt index 73451ba72..6f54cd5b4 100644 --- a/test/cmocka/src/audio/mux/CMakeLists.txt +++ b/test/cmocka/src/audio/mux/CMakeLists.txt @@ -10,6 +10,7 @@ add_library( audio_mux STATIC ${PROJECT_SOURCE_DIR}/src/audio/mux/mux.c + ${PROJECT_SOURCE_DIR}/src/audio/mux/mux_ipc3.c ${PROJECT_SOURCE_DIR}/src/audio/mux/mux_generic.c ${PROJECT_SOURCE_DIR}/src/audio/component.c ${PROJECT_SOURCE_DIR}/src/audio/data_blob.c @@ -48,3 +49,8 @@ cmocka_test( demux_copy demux_copy.c ) + +target_include_directories(audio_mux PRIVATE ${PROJECT_SOURCE_DIR}/src/audio) +target_include_directories(mux_get_processing_function PRIVATE ${PROJECT_SOURCE_DIR}/src/audio) +target_include_directories(mux_copy PRIVATE ${PROJECT_SOURCE_DIR}/src/audio) +target_include_directories(demux_copy PRIVATE ${PROJECT_SOURCE_DIR}/src/audio) diff --git a/test/cmocka/src/audio/mux/demux_copy.c b/test/cmocka/src/audio/mux/demux_copy.c index b9eff2dcb..857fe6a0b 100644 --- a/test/cmocka/src/audio/mux/demux_copy.c +++ b/test/cmocka/src/audio/mux/demux_copy.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/cmocka/src/audio/mux/mux_copy.c b/test/cmocka/src/audio/mux/mux_copy.c index d30e38eb6..3d41cb176 100644 --- a/test/cmocka/src/audio/mux/mux_copy.c +++ b/test/cmocka/src/audio/mux/mux_copy.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/cmocka/src/audio/mux/mux_get_processing_function.c b/test/cmocka/src/audio/mux/mux_get_processing_function.c index 1f9b744e6..6f1528839 100644 --- a/test/cmocka/src/audio/mux/mux_get_processing_function.c +++ b/test/cmocka/src/audio/mux/mux_get_processing_function.c @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index a53f1ae1b..783d5c7e4 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -812,6 +812,16 @@ zephyr_library_sources_ifdef(CONFIG_COMP_MUX ${SOF_AUDIO_PATH}/mux/mux_generic.c ) +if(CONFIG_IPC_MAJOR_3) + zephyr_library_sources_ifdef(CONFIG_COMP_MUX + ${SOF_AUDIO_PATH}/mux/mux_ipc3.c +) +elseif(CONFIG_IPC_MAJOR_4) + zephyr_library_sources_ifdef(CONFIG_COMP_MUX + ${SOF_AUDIO_PATH}/mux/mux_ipc4.c +) +endif() + zephyr_library_sources_ifdef(CONFIG_COMP_GOOGLE_HOTWORD_DETECT ${SOF_AUDIO_PATH}/google/google_hotword_detect.c )