diff options
Diffstat (limited to 'hifi/xaf/host-apf')
38 files changed, 7467 insertions, 0 deletions
diff --git a/hifi/xaf/host-apf/Android.mk b/hifi/xaf/host-apf/Android.mk new file mode 100644 index 00000000..28e71011 --- /dev/null +++ b/hifi/xaf/host-apf/Android.mk @@ -0,0 +1,66 @@ +LOCAL_PATH := $(call my-dir) +################################################################################ +# libxtensa_proxy library building +################################################################################ + +include $(CLEAR_VARS) +common_C_INCLUDES := \ + $(LOCAL_PATH)/include \ + $(LOCAL_PATH)/include/audio \ + $(LOCAL_PATH)/include/os/android \ + $(LOCAL_PATH)/include/sys/fio \ + $(LOCAL_PATH)/playback \ + $(LOCAL_PATH)/playback/tinyalsa \ + $(LOCAL_PATH)/utest/include + +LOCAL_SRC_FILES := \ + proxy/xf-proxy.c \ + proxy/xaf-api.c \ + proxy/xf-trace.c \ + proxy/xf-fio.c \ + playback/xa_playback.c \ + playback/tinyalsa/pcm.c \ + utest/xaf-utils-test.c \ + utest/xaf-mem-test.c + +C_FLAGS := -DXF_TRACE=0 -Wall -Werror -Wno-everything + +LOCAL_C_INCLUDES := $(common_C_INCLUDES) +LOCAL_CFLAGS := $(C_FLAGS) +LOCAL_MODULE := libxtensa_proxy +LOCAL_MODULE_TAGS := optional + +include $(BUILD_STATIC_LIBRARY) + +################################################################################ +# xaf-dec-test: fileinput->ogg/pcm decoder->speaker output +################################################################################ +include $(CLEAR_VARS) +LOCAL_MODULE := xaf-dec-test + +LOCAL_SRC_FILES := \ + utest/xaf-dec-test.c + +LOCAL_C_INCLUDES := $(common_C_INCLUDES) +LOCAL_CFLAGS := $(C_FLAGS) +LOCAL_STATIC_LIBRARIES := libxtensa_proxy +LOCAL_SHARED_LIBRARIES := liblog libcutils +LOCAL_MODULE_TAGS := optional +include $(BUILD_EXECUTABLE) + +################################################################################ +# xaf-dec-mix-test: fileinput->ogg orpcm decoder->Mixer->speaker output +################################################################################ +include $(CLEAR_VARS) +LOCAL_MODULE := xaf-dec-mix-test + +LOCAL_SRC_FILES := \ + utest/xaf-dec-mix-test.c + +LOCAL_C_INCLUDES := $(common_C_INCLUDES) +LOCAL_CFLAGS := $(C_FLAGS) +LOCAL_STATIC_LIBRARIES := libxtensa_proxy +LOCAL_SHARED_LIBRARIES := liblog libcutils +LOCAL_MODULE_TAGS := optional +include $(BUILD_EXECUTABLE) + diff --git a/hifi/xaf/host-apf/include/audio/xa-audio-decoder-api.h b/hifi/xaf/host-apf/include/audio/xa-audio-decoder-api.h new file mode 100644 index 00000000..f82544c8 --- /dev/null +++ b/hifi/xaf/host-apf/include/audio/xa-audio-decoder-api.h @@ -0,0 +1,46 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#ifndef __XA_ADEC_API_H__ +#define __XA_ADEC_API_H__ + +/* ...generic audio-decoder configuration parameters */ +enum xa_config_param_codec { + XA_CODEC_CONFIG_PARAM_CHANNELS = 0x10000 + 0, + XA_CODEC_CONFIG_PARAM_SAMPLE_RATE = 0x10000 + 1, + XA_CODEC_CONFIG_PARAM_PCM_WIDTH = 0x10000 + 2, + XA_CODEC_CONFIG_PARAM_PRODUCED = 0x10000 + 3 +}; + +/* ...ports indices */ +enum xa_codec_ports { + XA_CODEC_INPUT_PORT = 0, + XA_CODEC_OUTPUT_PORT = 1 +}; + +/* ...non-fatal execution errors */ +enum +{ + XA_CODEC_EXEC_NO_DATA = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_GENERIC, 0) +}; + +#endif diff --git a/hifi/xaf/host-apf/include/audio/xa-mixer-api.h b/hifi/xaf/host-apf/include/audio/xa-mixer-api.h new file mode 100644 index 00000000..c9695b40 --- /dev/null +++ b/hifi/xaf/host-apf/include/audio/xa-mixer-api.h @@ -0,0 +1,154 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#ifndef __XA_MIXER_API_H__ +#define __XA_MIXER_API_H__ + +/******************************************************************************* + * Includes + ******************************************************************************/ + +/* ...generic commands */ +#include "xa_apicmd_standards.h" + +/* ...generic error codes */ +#include "xa_error_standards.h" + +/* ...common types */ +#include "xa_type_def.h" + +/******************************************************************************* + * Constants definitions + ******************************************************************************/ + +/* ...mixer-specific configuration parameters */ +enum xa_config_param_mixer { + XA_MIXER_CONFIG_PARAM_INPUT_TRACKS = 0, + XA_MIXER_CONFIG_PARAM_PCM_WIDTH = 1, + XA_MIXER_CONFIG_PARAM_CHANNELS = 2, + XA_MIXER_CONFIG_PARAM_SAMPLE_RATE = 4, + XA_MIXER_CONFIG_PARAM_FRAME_SIZE = 5, + XA_MIXER_CONFIG_PARAM_BUFFER_SIZE = 6, + XA_MIXER_CONFIG_PARAM_VOLUME = 7, + XA_MIXER_CONFIG_PARAM_NUM = 8 +}; + +/* ...component identifier (informative) */ +#define XA_CODEC_MIXER 1 + +/* ...global limitation - maximal mixer track number */ +#define XA_MIXER_MAX_TRACK_NUMBER 4 + +/* ...volume representation */ +#define __XA_MIXER_VOLUME(v) \ + ({ u32 __v = (u32)((v) * (1 << 12)); (__v > 0xFFFF ? __v = 0xFFFF : 0); (u16)__v; }) + +/* ...mixer volume setting command encoding */ +#define XA_MIXER_VOLUME(track, channel, volume) \ + (__XA_MIXER_VOLUME(volume) | ((track) << 16) | ((channel) << 20)) + +/******************************************************************************* + * Class 0: API Errors + ******************************************************************************/ + +#define XA_MIXER_API_NONFATAL(e) \ + XA_ERROR_CODE(xa_severity_nonfatal, xa_class_api, XA_CODEC_MIXER, (e)) + +#define XA_MIXER_API_FATAL(e) \ + XA_ERROR_CODE(xa_severity_fatal, xa_class_api, XA_CODEC_MIXER, (e)) + +enum xa_error_nonfatal_api_mixer { + XA_MIXER_API_NONFATAL_MAX = XA_MIXER_API_NONFATAL(0) +}; + +enum xa_error_fatal_api_mixer { + XA_MIXER_API_FATAL_MAX = XA_MIXER_API_FATAL(0) +}; + +/******************************************************************************* + * Class 1: Configuration Errors + ******************************************************************************/ + +#define XA_MIXER_CONFIG_NONFATAL(e) \ + XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_CODEC_MIXER, (e)) + +#define XA_MIXER_CONFIG_FATAL(e) \ + XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_MIXER, (e)) + +enum xa_error_nonfatal_config_mixer { + XA_MIXER_CONFIG_NONFATAL_RANGE = XA_MIXER_CONFIG_NONFATAL(0), + XA_MIXER_CONFIG_NONFATAL_STATE = XA_MIXER_CONFIG_NONFATAL(1), + XA_MIXER_CONFIG_NONFATAL_MAX = XA_MIXER_CONFIG_NONFATAL(2) +}; + +enum xa_error_fatal_config_mixer { + XA_MIXER_CONFIG_FATAL_RANGE = XA_MIXER_CONFIG_FATAL(0), + XA_MIXER_CONFIG_FATAL_TRACK_STATE = XA_MIXER_CONFIG_FATAL(0 + XA_MIXER_CONFIG_NONFATAL_MAX), + XA_MIXER_CONFIG_FATAL_MAX = XA_MIXER_CONFIG_FATAL(1) +}; + +/******************************************************************************* + * Class 2: Execution Class Errors + ******************************************************************************/ + +#define XA_MIXER_EXEC_NONFATAL(e) \ + XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_MIXER, (e)) + +#define XA_MIXER_EXEC_FATAL(e) \ + XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_MIXER, (e)) + +enum xa_error_nonfatal_execute_mixer { + XA_MIXER_EXEC_NONFATAL_STATE = XA_MIXER_EXEC_NONFATAL(0), + XA_MIXER_EXEC_NONFATAL_NO_DATA = XA_MIXER_EXEC_NONFATAL(1), + XA_MIXER_EXEC_NONFATAL_INPUT = XA_MIXER_EXEC_NONFATAL(2), + XA_MIXER_EXEC_NONFATAL_OUTPUT = XA_MIXER_EXEC_NONFATAL(3), + XA_MIXER_EXEC_NONFATAL_MAX = XA_MIXER_EXEC_NONFATAL(4) +}; + +enum xa_error_fatal_execute_mixer { + XA_MIXER_EXEC_FATAL_STATE = XA_MIXER_EXEC_FATAL(0), + XA_MIXER_EXEC_FATAL_INPUT = XA_MIXER_EXEC_FATAL(1), + XA_MIXER_EXEC_FATAL_OUTPUT = XA_MIXER_EXEC_FATAL(2), + XA_MIXER_EXEC_FATAL_MAX = XA_MIXER_EXEC_FATAL(3) +}; + +/******************************************************************************* + * API function definition (tbd) + ******************************************************************************/ + +#if defined(USE_DLL) && defined(_WIN32) +#define DLL_SHARED __declspec(dllimport) +#elif defined (_WINDLL) +#define DLL_SHARED __declspec(dllexport) +#else +#define DLL_SHARED +#endif + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus */ +DLL_SHARED xa_codec_func_t xa_mixer; +#if defined(__cplusplus) +} +#endif /* __cplusplus */ + +#endif /* __XA_MIXER_API_H__ */ diff --git a/hifi/xaf/host-apf/include/audio/xa-pcm-api.h b/hifi/xaf/host-apf/include/audio/xa-pcm-api.h new file mode 100644 index 00000000..94fb1362 --- /dev/null +++ b/hifi/xaf/host-apf/include/audio/xa-pcm-api.h @@ -0,0 +1,138 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#ifndef __XA_PCM_API_H__ +#define __XA_PCM_API_H__ + +/******************************************************************************* + * Includes + ******************************************************************************/ + +#include "xa_type_def.h" +#include "xa_error_standards.h" +#include "xa_apicmd_standards.h" +#include "xa_memory_standards.h" + +/******************************************************************************* + * Constants definitions + ******************************************************************************/ + +/* ...codec-specific configuration parameters */ +enum xa_config_param_pcm { + XA_PCM_CONFIG_PARAM_SAMPLE_RATE = 0, + XA_PCM_CONFIG_PARAM_IN_PCM_WIDTH = 1, + XA_PCM_CONFIG_PARAM_IN_CHANNELS = 2, + XA_PCM_CONFIG_PARAM_OUT_PCM_WIDTH = 3, + XA_PCM_CONFIG_PARAM_OUT_CHANNELS = 4, + XA_PCM_CONFIG_PARAM_CHANROUTING = 5, + XA_PCM_CONFIG_PARAM_NUM = 6, +}; + +/* ...component identifier (informative) */ +#define XA_CODEC_PCM 16 + +/******************************************************************************* + * Class 0: API Errors + ******************************************************************************/ + +#define XA_PCM_API_NONFATAL(e) \ + XA_ERROR_CODE(xa_severity_nonfatal, xa_class_api, XA_CODEC_PCM, (e)) + +#define XA_PCM_API_FATAL(e) \ + XA_ERROR_CODE(xa_severity_fatal, xa_class_api, XA_CODEC_PCM, (e)) + +enum xa_error_nonfatal_api_pcm { + XA_PCM_API_NONFATAL_MAX = XA_PCM_API_NONFATAL(0) +}; + +enum xa_error_fatal_api_pcm { + XA_PCM_API_FATAL_MAX = XA_PCM_API_FATAL(0) +}; + +/******************************************************************************* + * Class 1: Configuration Errors + ******************************************************************************/ + +#define XA_PCM_CONFIG_NONFATAL(e) \ + XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_CODEC_PCM, (e)) + +#define XA_PCM_CONFIG_FATAL(e) \ + XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_PCM, (e)) + +enum xa_error_nonfatal_config_pcm { + XA_PCM_CONFIG_NONFATAL_RANGE = XA_PCM_CONFIG_NONFATAL(0), + XA_PCM_CONFIG_NONFATAL_STATE = XA_PCM_CONFIG_NONFATAL(1), + XA_PCM_CONFIG_NONFATAL_MAX = XA_PCM_CONFIG_NONFATAL(2) +}; + +enum xa_error_fatal_config_pcm { + XA_PCM_CONFIG_FATAL_RANGE = XA_PCM_CONFIG_FATAL(0), + XA_PCM_CONFIG_FATAL_MAX = XA_PCM_CONFIG_FATAL(1) +}; + +/******************************************************************************* + * Class 2: Execution Class Errors + ******************************************************************************/ + +#define XA_PCM_EXEC_NONFATAL(e) \ + XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_PCM, (e)) + +#define XA_PCM_EXEC_FATAL(e) \ + XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_PCM, (e)) + +enum xa_error_nonfatal_execute_pcm { + XA_PCM_EXEC_NONFATAL_STATE = XA_PCM_EXEC_NONFATAL(0), + XA_PCM_EXEC_NONFATAL_NO_DATA = XA_PCM_EXEC_NONFATAL(1), + XA_PCM_EXEC_NONFATAL_INPUT = XA_PCM_EXEC_NONFATAL(2), + XA_PCM_EXEC_NONFATAL_OUTPUT = XA_PCM_EXEC_NONFATAL(3), + XA_PCM_EXEC_NONFATAL_MAX = XA_PCM_EXEC_NONFATAL(4) +}; + +enum xa_error_fatal_execute_pcm { + XA_PCM_EXEC_FATAL_STATE = XA_PCM_EXEC_FATAL(0), + XA_PCM_EXEC_FATAL_INPUT = XA_PCM_EXEC_FATAL(1), + XA_PCM_EXEC_FATAL_OUTPUT = XA_PCM_EXEC_FATAL(2), + XA_PCM_EXEC_FATAL_MAX = XA_PCM_EXEC_FATAL(3) +}; + +/******************************************************************************* + * API function definition + ******************************************************************************/ + +#if defined(USE_DLL) && defined(_WIN32) +#define DLL_SHARED __declspec(dllimport) +#elif defined (_WINDLL) +#define DLL_SHARED __declspec(dllexport) +#else +#define DLL_SHARED +#endif + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus */ +DLL_SHARED xa_codec_func_t xa_pcm_codec; +#if defined(__cplusplus) +} +#endif /* __cplusplus */ + +#endif /* __XA_PCM_API_H__ */ + diff --git a/hifi/xaf/host-apf/include/audio/xa_apicmd_standards.h b/hifi/xaf/host-apf/include/audio/xa_apicmd_standards.h new file mode 100644 index 00000000..eb1b78e1 --- /dev/null +++ b/hifi/xaf/host-apf/include/audio/xa_apicmd_standards.h @@ -0,0 +1,107 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ +/******************************************************************************* +* +* NOTE, ANY CHANGES TO THIS FILE MAY AFFECT UNDERLYING AUDIO / SPEECH CODEC +* LIBRARY COMPONENT FROM CADENCE DESIGN SYSTEMS, INC. +* +******************************************************************************/ + + +#ifndef __XA_API_CMD_STANDARDS_H__ +#define __XA_API_CMD_STANDARDS_H__ + +/*****************************************************************************/ +/* Standard API commands */ +/*****************************************************************************/ + +enum xa_api_cmd_generic { + XA_API_CMD_GET_LIB_ID_STRINGS = 0x0001, + + XA_API_CMD_GET_API_SIZE = 0x0002, + XA_API_CMD_INIT = 0x0003, + + XA_API_CMD_SET_CONFIG_PARAM = 0x0004, + XA_API_CMD_GET_CONFIG_PARAM = 0x0005, + + XA_API_CMD_GET_MEMTABS_SIZE = 0x0006, + XA_API_CMD_SET_MEMTABS_PTR = 0x0007, + XA_API_CMD_GET_N_MEMTABS = 0x0008, + + XA_API_CMD_EXECUTE = 0x0009, + + XA_API_CMD_PUT_INPUT_QUERY = 0x000A, + XA_API_CMD_GET_CURIDX_INPUT_BUF = 0x000B, + XA_API_CMD_SET_INPUT_BYTES = 0x000C, + XA_API_CMD_GET_OUTPUT_BYTES = 0x000D, + XA_API_CMD_INPUT_OVER = 0x000E, + + XA_API_CMD_GET_MEM_INFO_SIZE = 0x0010, + XA_API_CMD_GET_MEM_INFO_ALIGNMENT = 0x0011, + XA_API_CMD_GET_MEM_INFO_TYPE = 0x0012, + XA_API_CMD_GET_MEM_INFO_PLACEMENT = 0x0013, + XA_API_CMD_GET_MEM_INFO_PRIORITY = 0x0014, + XA_API_CMD_SET_MEM_PTR = 0x0015, + XA_API_CMD_SET_MEM_INFO_SIZE = 0x0016, + XA_API_CMD_SET_MEM_PLACEMENT = 0x0017, + + XA_API_CMD_GET_N_TABLES = 0x0018, + XA_API_CMD_GET_TABLE_INFO_SIZE = 0x0019, + XA_API_CMD_GET_TABLE_INFO_ALIGNMENT = 0x001A, + XA_API_CMD_GET_TABLE_INFO_PRIORITY = 0x001B, + XA_API_CMD_SET_TABLE_PTR = 0x001C, + XA_API_CMD_GET_TABLE_PTR = 0x001D +}; + +/*****************************************************************************/ +/* Standard API command indices */ +/*****************************************************************************/ + +enum xa_cmd_type_generic { + /* XA_API_CMD_GET_LIB_ID_STRINGS indices */ + XA_CMD_TYPE_LIB_NAME = 0x0100, + XA_CMD_TYPE_LIB_VERSION = 0x0200, + XA_CMD_TYPE_API_VERSION = 0x0300, + + /* XA_API_CMD_INIT indices */ + XA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS = 0x0100, + XA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS = 0x0200, + XA_CMD_TYPE_INIT_PROCESS = 0x0300, + XA_CMD_TYPE_INIT_DONE_QUERY = 0x0400, + + /* XA_API_CMD_EXECUTE indices */ + XA_CMD_TYPE_DO_EXECUTE = 0x0100, + XA_CMD_TYPE_DONE_QUERY = 0x0200, + XA_CMD_TYPE_DO_RUNTIME_INIT = 0x0300 +}; + + +/*****************************************************************************/ +/* Standard API configuration parameters */ +/*****************************************************************************/ + +enum xa_config_param_generic { + XA_CONFIG_PARAM_CUR_INPUT_STREAM_POS = 0x0100, + XA_CONFIG_PARAM_GEN_INPUT_STREAM_POS = 0x0200, +}; + +#endif /* __XA_API_CMD_STANDARDS_H__ */ diff --git a/hifi/xaf/host-apf/include/audio/xa_error_standards.h b/hifi/xaf/host-apf/include/audio/xa_error_standards.h new file mode 100644 index 00000000..1b67b52f --- /dev/null +++ b/hifi/xaf/host-apf/include/audio/xa_error_standards.h @@ -0,0 +1,79 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ +/******************************************************************************* +* +* NOTE, ANY CHANGES TO THIS FILE MAY AFFECT UNDERLYING AUDIO / SPEECH CODEC +* LIBRARY COMPONENT FROM CADENCE DESIGN SYSTEMS, INC. +* +******************************************************************************/ + + +#ifndef __XA_ERROR_STANDARDS_H__ +#define __XA_ERROR_STANDARDS_H__ + +/*****************************************************************************/ +/* File includes */ +/* xa_type_def.h */ +/*****************************************************************************/ + +/*****************************************************************************/ +/* Constant hash defines */ +/*****************************************************************************/ +#define XA_NO_ERROR 0 +#define XA_FATAL_ERROR 0x80000000 + +enum xa_error_severity { + xa_severity_nonfatal = 0, + xa_severity_fatal = 0xffffffff +}; + +enum xa_error_class { + xa_class_api = 0, + xa_class_config = 1, + xa_class_execute = 2, + xa_class_proxy = 3 +}; + +#define XA_CODEC_GENERIC 0 + +#define XA_ERROR_CODE(severity, class, codec, index) ((severity << 15) | (class << 11) | (codec << 6) | index) +#define XA_ERROR_SEVERITY(code) (((code) & XA_FATAL_ERROR) != 0) +#define XA_ERROR_CLASS(code) (((code) >> 11) & 0x0f) +#define XA_ERROR_CODEC(code) (((code) >> 6) & 0x1f) +#define XA_ERROR_SUBCODE(code) (((code) >> 0) & 0x3f) + +/* Our convention is that only api-class errors can be generic ones. */ + +/*****************************************************************************/ +/* Class 0: API Errors */ +/*****************************************************************************/ +/* Non Fatal Errors */ +/* (none) */ +/* Fatal Errors */ +enum xa_error_fatal_api_generic { + XA_API_FATAL_MEM_ALLOC = XA_ERROR_CODE(xa_severity_fatal, xa_class_api, XA_CODEC_GENERIC, 0), + XA_API_FATAL_MEM_ALIGN = XA_ERROR_CODE(xa_severity_fatal, xa_class_api, XA_CODEC_GENERIC, 1), + XA_API_FATAL_INVALID_CMD = XA_ERROR_CODE(xa_severity_fatal, xa_class_api, XA_CODEC_GENERIC, 2), + XA_API_FATAL_INVALID_CMD_TYPE = XA_ERROR_CODE(xa_severity_fatal, xa_class_api, XA_CODEC_GENERIC, 3) +}; + +#endif /* __XA_ERROR_STANDARDS_H__ */ diff --git a/hifi/xaf/host-apf/include/audio/xa_memory_standards.h b/hifi/xaf/host-apf/include/audio/xa_memory_standards.h new file mode 100644 index 00000000..27ec455f --- /dev/null +++ b/hifi/xaf/host-apf/include/audio/xa_memory_standards.h @@ -0,0 +1,104 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ +/******************************************************************************* +* +* NOTE, ANY CHANGES TO THIS FILE MAY AFFECT UNDERLYING AUDIO / SPEECH CODEC +* LIBRARY COMPONENT FROM CADENCE DESIGN SYSTEMS, INC. +* +******************************************************************************/ + + +#ifndef __XA_MEMORY_STANDARDS_H__ +#define __XA_MEMORY_STANDARDS_H__ + +/*****************************************************************************/ +/* Constant hash defines */ +/*****************************************************************************/ +/* when you don't need alignment, pass this to memory library */ +#define XA_MEM_NO_ALIGN 0x01 + +/* standard memory types */ +/* to be used inter frames */ +#define XA_MEMTYPE_PERSIST 0x00 +/* read write, to be used intra frames */ +#define XA_MEMTYPE_SCRATCH 0x01 +/* read only memory, intra frame */ +#define XA_MEMTYPE_INPUT 0x02 +/* read-write memory, for usable output, intra frame */ +#define XA_MEMTYPE_OUTPUT 0x03 +/* readonly memory, inter frame */ +#define XA_MEMTYPE_TABLE 0x04 +/* input buffer before mem tabs allocation */ +#define XA_MEMTYPE_PRE_FRAME_INPUT 0x05 +/* input buffer before mem tabs allocation */ +#define XA_MEMTYPE_PRE_FRAME_SCRATCH 0x06 +/* for local variables */ +#define XA_MEMTYPE_AUTO_VAR 0x80 + +/* standard memory priorities */ +#define XA_MEMPRIORITY_ANYWHERE 0x00 +#define XA_MEMPRIORITY_LOWEST 0x01 +#define XA_MEMPRIORITY_LOW 0x02 +#define XA_MEMPRIORITY_NORM 0x03 +#define XA_MEMPRIORITY_ABOVE_NORM 0x04 +#define XA_MEMPRIORITY_HIGH 0x05 +#define XA_MEMPRIORITY_HIGHER 0x06 +#define XA_MEMPRIORITY_CRITICAL 0x07 + +/* standard memory placements */ +/* placement is defined by 64 bits */ + +#define XA_MEMPLACE_FAST_RAM_0 0x000001 +#define XA_MEMPLACE_FAST_RAM_1 0x000002 +#define XA_MEMPLACE_FAST_RAM_2 0x000004 +#define XA_MEMPLACE_FAST_RAM_3 0x000008 +#define XA_MEMPLACE_FAST_RAM_4 0x000010 +#define XA_MEMPLACE_FAST_RAM_5 0x000020 +#define XA_MEMPLACE_FAST_RAM_6 0x000040 +#define XA_MEMPLACE_FAST_RAM_7 0x000080 + +#define XA_MEMPLACE_INT_RAM_0 0x000100 +#define XA_MEMPLACE_INT_RAM_1 0x000200 +#define XA_MEMPLACE_INT_RAM_2 0x000400 +#define XA_MEMPLACE_INT_RAM_3 0x000800 +#define XA_MEMPLACE_INT_RAM_4 0x001000 +#define XA_MEMPLACE_INT_RAM_5 0x002000 +#define XA_MEMPLACE_INT_RAM_6 0x004000 +#define XA_MEMPLACE_INT_RAM_7 0x008000 + +#define XA_MEMPLACE_EXT_RAM_0 0x010000 +#define XA_MEMPLACE_EXT_RAM_1 0x020000 +#define XA_MEMPLACE_EXT_RAM_2 0x040000 +#define XA_MEMPLACE_EXT_RAM_3 0x080000 +#define XA_MEMPLACE_EXT_RAM_4 0x100000 +#define XA_MEMPLACE_EXT_RAM_5 0x200000 +#define XA_MEMPLACE_EXT_RAM_6 0x400000 +#define XA_MEMPLACE_EXT_RAM_7 0x800000 + +#define XA_MEMPLACE_DONTCARE_H 0xFFFFFFFF +#define XA_MEMPLACE_DONTCARE_L 0xFFFFFFFF + +/* the simple common PC RAM */ +#define XA_PC_RAM_H 0x00000000 +#define XA_PC_RAM_L XA_MEMPLACE_EXT_RAM_0 + +#endif /* __XA_MEMORY_STANDARDS_H__ */ diff --git a/hifi/xaf/host-apf/include/audio/xa_type_def.h b/hifi/xaf/host-apf/include/audio/xa_type_def.h new file mode 100644 index 00000000..e83cdd34 --- /dev/null +++ b/hifi/xaf/host-apf/include/audio/xa_type_def.h @@ -0,0 +1,98 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ +/******************************************************************************* +* +* NOTE, ANY CHANGES TO THIS FILE MAY AFFECT UNDERLYING AUDIO / SPEECH CODEC +* LIBRARY COMPONENT FROM CADENCE DESIGN SYSTEMS, INC. +* +******************************************************************************/ + + +#ifndef __XA_TYPE_DEF_H__ +#define __XA_TYPE_DEF_H__ + +/****************************************************************************/ +/* types type define prefix examples bytes */ +/************************ *********** ****** **************** ***** */ +typedef signed char WORD8 ;/* b WORD8 b_name 1 */ +typedef signed char * pWORD8 ;/* pb pWORD8 pb_nmae 1 */ +typedef unsigned char UWORD8 ;/* ub UWORD8 ub_count 1 */ +typedef unsigned char * pUWORD8 ;/* pub pUWORD8 pub_count 1 */ + +typedef signed short WORD16 ;/* s WORD16 s_count 2 */ +typedef signed short * pWORD16 ;/* ps pWORD16 ps_count 2 */ +typedef unsigned short UWORD16 ;/* us UWORD16 us_count 2 */ +typedef unsigned short * pUWORD16;/* pus pUWORD16 pus_count 2 */ + +typedef signed int WORD24 ;/* k WORD24 k_count 3 */ +typedef signed int * pWORD24 ;/* pk pWORD24 pk_count 3 */ +typedef unsigned int UWORD24 ;/* uk UWORD24 uk_count 3 */ +typedef unsigned int * pUWORD24;/* puk pUWORD24 puk_count 3 */ + +typedef signed int WORD32 ;/* i WORD32 i_count 4 */ +typedef signed int * pWORD32 ;/* pi pWORD32 pi_count 4 */ +typedef unsigned int UWORD32 ;/* ui UWORD32 ui_count 4 */ +typedef unsigned int * pUWORD32;/* pui pUWORD32 pui_count 4 */ + +typedef signed long long WORD40 ;/* m WORD40 m_count 5 */ +typedef signed long long * pWORD40 ;/* pm pWORD40 pm_count 5 */ +typedef unsigned long long UWORD40 ;/* um UWORD40 um_count 5 */ +typedef unsigned long long * pUWORD40;/* pum pUWORD40 pum_count 5 */ + +typedef signed long long WORD64 ;/* h WORD64 h_count 8 */ +typedef signed long long * pWORD64 ;/* ph pWORD64 ph_count 8 */ +typedef unsigned long long UWORD64 ;/* uh UWORD64 uh_count 8 */ +typedef unsigned long long * pUWORD64;/* puh pUWORD64 puh_count 8 */ + +typedef float FLOAT32 ;/* f FLOAT32 f_count 4 */ +typedef float * pFLOAT32;/* pf pFLOAT32 pf_count 4 */ +typedef double FLOAT64 ;/* d UFLOAT64 d_count 8 */ +typedef double * pFlOAT64;/* pd pFLOAT64 pd_count 8 */ + +typedef void VOID ;/* v VOID v_flag 4 */ +typedef void * pVOID ;/* pv pVOID pv_flag 4 */ + +/* variable size types: platform optimized implementation */ +//typedef signed int BOOL ;/* bool BOOL bool_true */ +//typedef unsigned int UBOOL ;/* ubool BOOL ubool_true */ +typedef signed int FLAG ;/* flag FLAG flag_false */ +typedef unsigned int UFLAG ;/* uflag FLAG uflag_false */ +typedef signed int LOOPIDX ;/* lp LOOPIDX lp_index */ +typedef unsigned int ULOOPIDX;/* ulp SLOOPIDX ulp_index */ +typedef signed int WORD ;/* lp LOOPIDX lp_index */ +typedef unsigned int UWORD ;/* ulp SLOOPIDX ulp_index */ + +typedef LOOPIDX LOOPINDEX; /* lp LOOPIDX lp_index */ +typedef ULOOPIDX ULOOPINDEX;/* ulp SLOOPIDX ulp_index */ + +#define PLATFORM_INLINE __inline + +typedef struct xa_codec_opaque { WORD32 _; } *xa_codec_handle_t; + +typedef int XA_ERRORCODE; + +typedef XA_ERRORCODE xa_codec_func_t(xa_codec_handle_t p_xa_module_obj, + WORD32 i_cmd, + WORD32 i_idx, + pVOID pv_value); + +#endif /* __XA_TYPE_DEF_H__ */ diff --git a/hifi/xaf/host-apf/include/audio/xa_vorbis_dec_api.h b/hifi/xaf/host-apf/include/audio/xa_vorbis_dec_api.h new file mode 100644 index 00000000..f99660f8 --- /dev/null +++ b/hifi/xaf/host-apf/include/audio/xa_vorbis_dec_api.h @@ -0,0 +1,121 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ +/******************************************************************************* +* +* NOTE, ANY CHANGES TO THIS FILE MAY AFFECT UNDERLYING AUDIO / SPEECH CODEC +* LIBRARY COMPONENT FROM CADENCE DESIGN SYSTEMS, INC. +* +******************************************************************************/ + + + +#ifndef __XA_VORBIS_DEC_API_H__ +#define __XA_VORBIS_DEC_API_H__ + +#include <xa_memory_standards.h> + +/* vorbis_dec-specific configuration parameters */ +enum xa_config_param_vorbis_dec +{ + XA_VORBISDEC_CONFIG_PARAM_SAMP_FREQ = 0, + XA_VORBISDEC_CONFIG_PARAM_NUM_CHANNELS = 1, + XA_VORBISDEC_CONFIG_PARAM_PCM_WDSZ = 2, + XA_VORBISDEC_CONFIG_PARAM_COMMENT_MEM_PTR = 3, + XA_VORBISDEC_CONFIG_PARAM_COMMENT_MEM_SIZE = 4, + XA_VORBISDEC_CONFIG_PARAM_GET_CUR_BITRATE = 5, + XA_VORBISDEC_CONFIG_PARAM_RAW_VORBIS_FILE_MODE = 6, + XA_VORBISDEC_CONFIG_PARAM_RAW_VORBIS_LAST_PKT_GRANULE_POS = 7, + XA_VORBISDEC_CONFIG_PARAM_OGG_MAX_PAGE_SIZE = 8, + XA_VORBISDEC_CONFIG_PARAM_RUNTIME_MEM = 9 +}; + +/* commands */ +#include <xa_apicmd_standards.h> + +/* vorbis_dec-specific command types */ +/* (none) */ + +/* error codes */ +#include <xa_error_standards.h> +#define XA_CODEC_VORBIS_DEC 7 + +/* vorbis_dec-specific error codes */ + +/*****************************************************************************/ +/* Class 1: Configuration Errors */ +/*****************************************************************************/ +/* Nonfatal Errors */ +enum xa_error_nonfatal_config_vorbis_dec +{ + XA_VORBISDEC_CONFIG_NONFATAL_GROUPED_STREAM = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_CODEC_VORBIS_DEC, 0), + XA_VORBISDEC_CONFIG_NONFATAL_BAD_PARAM = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_CODEC_VORBIS_DEC, 1) +}; + +/* Fatal Errors */ +enum xa_error_fatal_config_vorbis_dec +{ + XA_VORBISDEC_CONFIG_FATAL_BADHDR = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_VORBIS_DEC, 0), + XA_VORBISDEC_CONFIG_FATAL_NOTVORBIS = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_VORBIS_DEC, 1), + XA_VORBISDEC_CONFIG_FATAL_BADINFO = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_VORBIS_DEC, 2), + XA_VORBISDEC_CONFIG_FATAL_BADVERSION = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_VORBIS_DEC, 3), + XA_VORBISDEC_CONFIG_FATAL_BADBOOKS = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_VORBIS_DEC, 4), + XA_VORBISDEC_CONFIG_FATAL_CODEBOOK_DECODE = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_VORBIS_DEC, 5), + XA_VORBISDEC_CONFIG_FATAL_INVALID_PARAM = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_VORBIS_DEC, 6) +}; + +/*****************************************************************************/ +/* Class 2: Execution Errors */ +/*****************************************************************************/ +/* Nonfatal Errors */ +enum xa_error_nonfatal_execute_vorbis_dec +{ + XA_VORBISDEC_EXECUTE_NONFATAL_OV_HOLE = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 0), + XA_VORBISDEC_EXECUTE_NONFATAL_OV_NOTAUDIO = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 1), + XA_VORBISDEC_EXECUTE_NONFATAL_OV_BADPACKET = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 2), + XA_VORBISDEC_EXECUTE_NONFATAL_OV_RUNTIME_DECODE_FLUSH_IN_PROGRESS = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 3), + XA_VORBISDEC_EXECUTE_NONFATAL_OV_INVALID_STRM_POS = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 4), + XA_VORBISDEC_EXECUTE_NONFATAL_OV_INSUFFICIENT_DATA = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 5), + XA_VORBISDEC_EXECUTE_NONFATAL_OV_UNEXPECTED_IDENT_PKT_RECEIVED = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 6), + XA_VORBISDEC_EXECUTE_NONFATAL_OV_UNEXPECTED_HEADER_PKT_RECEIVED = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 7) +}; +/* Fatal Errors */ +enum xa_error_fatal_execute_vorbis_dec +{ + XA_VORBISDEC_EXECUTE_FATAL_PERSIST_ALLOC = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 0), + XA_VORBISDEC_EXECUTE_FATAL_SCRATCH_ALLOC = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 1), + XA_VORBISDEC_EXECUTE_FATAL_CORRUPT_STREAM = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 2), + XA_VORBISDEC_EXECUTE_FATAL_INSUFFICIENT_INP_BUF_SIZE = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 3) +}; + +#include "xa_type_def.h" + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + + xa_codec_func_t xa_vorbis_dec; + +#ifdef __cplusplus + } +#endif /* __cplusplus */ + +#endif /* __XA_VORBIS_DEC_API_H__ */ diff --git a/hifi/xaf/host-apf/include/os/android/xf-osal.h b/hifi/xaf/host-apf/include/os/android/xf-osal.h new file mode 100644 index 00000000..7d2f5a95 --- /dev/null +++ b/hifi/xaf/host-apf/include/os/android/xf-osal.h @@ -0,0 +1,215 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#ifndef __XF_H +#error "xf-osal.h mustn't be included directly" +#endif + +/******************************************************************************* + * Includes + ******************************************************************************/ + +#include <pthread.h> +#include <fcntl.h> +#include <limits.h> +#include <sys/mman.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <cutils/log.h> + +/******************************************************************************* + * Tracing primitive + ******************************************************************************/ + +#define __xf_puts(str) \ + ALOG(LOG_INFO, "PROXY", "%s", (str)) + +/******************************************************************************* + * Lock operation + ******************************************************************************/ + +/* ...lock definition */ +typedef pthread_mutex_t xf_lock_t; + +/* ...lock initialization */ +static inline void __xf_lock_init(xf_lock_t *lock) +{ + pthread_mutex_init(lock, NULL); +} + +/* ...lock acquisition */ +static inline void __xf_lock(xf_lock_t *lock) +{ + pthread_mutex_lock(lock); +} + +/* ...lock release */ +static inline void __xf_unlock(xf_lock_t *lock) +{ + pthread_mutex_unlock(lock); +} + +/******************************************************************************* + * Waiting object + ******************************************************************************/ + +/* ...waiting object handle */ +typedef struct __xf_wait +{ + /* ...conditional variable */ + pthread_cond_t wait; + + /* ...waiting mutex */ + pthread_mutex_t mutex; + +} xf_wait_t; + +/* ...initialize waiting object */ +static inline void __xf_wait_init(xf_wait_t *w) +{ + pthread_cond_init(&w->wait, NULL); + pthread_mutex_init(&w->mutex, NULL); +} + +/* ...prepare to waiting */ +static inline void __xf_wait_prepare(xf_wait_t *w) +{ + pthread_mutex_lock(&w->mutex); +} + +#define __xf_wait_prepare(w) \ +({ \ + TRACE(1, _x("prepare-wait")); \ + (__xf_wait_prepare)(w); \ +}) + +/* ...wait until event is signalled */ +static inline int __xf_wait(xf_wait_t *w, u32 timeout) +{ + struct timespec ts; + struct timeval tv; + int r; + + /* ...wait with or without timeout (communication mutex is taken) */ + if (!timeout) + { + r = -pthread_cond_wait(&w->wait, &w->mutex); + } + else + { + /* ...get current time */ + gettimeofday(&tv, NULL); + + /* ...set absolute timeout */ + ts.tv_sec = tv.tv_sec + timeout / 1000; + ts.tv_nsec = tv.tv_usec * 1000 + (timeout % 1000) * 1000000; + (ts.tv_nsec >= 1000000000 ? ts.tv_sec++, ts.tv_nsec -= 1000000000 : 0); + + /* ...wait conditionally with absolute timeout*/ + r = -pthread_cond_timedwait(&w->wait, &w->mutex, &ts); + } + + /* ...leave with communication mutex taken */ + return r; +} + +#define __xf_wait(w, timeout) \ +({ \ + int __r; \ + TRACE(1, _x("wait")); \ + __r = (__xf_wait)(w, timeout); \ + TRACE(1, _x("resume")); \ + __r; \ +}) + +/* ...wake up waiting handle */ +static inline void __xf_wakeup(xf_wait_t *w) +{ + /* ...take communication mutex before signaling */ + pthread_mutex_lock(&w->mutex); + + /* ...signalling will resume waiting thread */ + pthread_cond_signal(&w->wait); + + /* ...assure that waiting task will not resume until we say this - is that really needed? - tbd */ + pthread_mutex_unlock(&w->mutex); +} + +#define __xf_wakeup(w) \ +({ \ + TRACE(1, _x("wakeup")); \ + (__xf_wakeup)(w); \ +}) + +/* ...complete waiting operation */ +static inline void __xf_wait_complete(xf_wait_t *w) +{ + pthread_mutex_unlock(&w->mutex); +} + +#define __xf_wait_complete(w) \ +({ \ + TRACE(1, _x("wait-complete")); \ + (__xf_wait_complete)(w); \ +}) + +/******************************************************************************* + * Thread support + ******************************************************************************/ + +/* ...thread handle definition */ +typedef pthread_t xf_thread_t; + +/* ...thread creation */ +static inline int __xf_thread_create(xf_thread_t *thread, void * (*f)(void *), void *arg) +{ + pthread_attr_t attr; + int r; + + /* ...initialize thread attributes - joinable with minimal stack */ + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN); + + /* ...create proxy asynchronous thread managing SHMEM */ + r = -pthread_create(thread, &attr, f, arg); + + /* ...destroy thread attributes */ + pthread_attr_destroy(&attr); + + return r; +} + +/* ...terminate thread operation */ +static inline int __xf_thread_destroy(xf_thread_t *thread) +{ + void *r; + + /* ...tell the thread to terminate */ + pthread_kill(*thread,SIGUSR1); + + /* ...wait until thread terminates */ + pthread_join(*thread, &r); + + /* ...return final status */ + return (int)(intptr_t)r; +} diff --git a/hifi/xaf/host-apf/include/os/xos/xf-osal.h b/hifi/xaf/host-apf/include/os/xos/xf-osal.h new file mode 100644 index 00000000..c3468000 --- /dev/null +++ b/hifi/xaf/host-apf/include/os/xos/xf-osal.h @@ -0,0 +1,206 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#ifndef __XF_H +#error "xf-osal.h mustn't be included directly" +#endif + +/******************************************************************************* + * Includes + ******************************************************************************/ +#include "xos.h" + +/******************************************************************************* + * Tracing primitive + ******************************************************************************/ + +#define __xf_puts(str) \ + puts((str)) + +/******************************************************************************* + * Lock operation + ******************************************************************************/ + +/* ...lock definition */ +typedef XosMutex xf_lock_t; + +/* ...lock initialization */ +static inline void __xf_lock_init(xf_lock_t *lock) +{ + xos_mutex_create(lock, XOS_MUTEX_WAIT_PRIORITY, 0); +} + +/* ...lock acquisition */ +static inline void __xf_lock(xf_lock_t *lock) +{ + xos_mutex_lock(lock); +} + +/* ...lock release */ +static inline void __xf_unlock(xf_lock_t *lock) +{ + xos_mutex_unlock(lock); +} + +/******************************************************************************* + * Waiting object + ******************************************************************************/ + +#if 0 +/* ...waiting object handle */ +typedef struct __xf_wait +{ + /* ...conditional variable */ + pthread_cond_t wait; + + /* ...waiting mutex */ + pthread_mutex_t mutex; + +} xf_wait_t; + +/* ...initialize waiting object */ +static inline void __xf_wait_init(xf_wait_t *w) +{ + pthread_cond_init(&w->wait, NULL); + pthread_mutex_init(&w->mutex, NULL); +} + +/* ...prepare to waiting */ +static inline void __xf_wait_prepare(xf_wait_t *w) +{ + pthread_mutex_lock(&w->mutex); +} + +#define __xf_wait_prepare(w) \ +({ \ + TRACE(1, _x("prepare-wait")); \ + (__xf_wait_prepare)(w); \ +}) + +/* ...wait until event is signalled */ +static inline int __xf_wait(xf_wait_t *w, u32 timeout) +{ + struct timespec ts; + struct timeval tv; + int r; + + /* ...wait with or without timeout (communication mutex is taken) */ + if (!timeout) + { + r = -pthread_cond_wait(&w->wait, &w->mutex); + } + else + { + /* ...get current time */ + gettimeofday(&tv, NULL); + + /* ...set absolute timeout */ + ts.tv_sec = tv.tv_sec + timeout / 1000; + ts.tv_nsec = tv.tv_usec * 1000 + (timeout % 1000) * 1000000; + (ts.tv_nsec >= 1000000000 ? ts.tv_sec++, ts.tv_nsec -= 1000000000 : 0); + + /* ...wait conditionally with absolute timeout*/ + r = -pthread_cond_timedwait(&w->wait, &w->mutex, &ts); + } + + /* ...leave with communication mutex taken */ + return r; +} + +#define __xf_wait(w, timeout) \ +({ \ + int __r; \ + TRACE(1, _x("wait")); \ + __r = (__xf_wait)(w, timeout); \ + TRACE(1, _x("resume")); \ + __r; \ +}) + +/* ...wake up waiting handle */ +static inline void __xf_wakeup(xf_wait_t *w) +{ + /* ...take communication mutex before signaling */ + pthread_mutex_lock(&w->mutex); + + /* ...signalling will resume waiting thread */ + pthread_cond_signal(&w->wait); + + /* ...assure that waiting task will not resume until we say this - is that really needed? - tbd */ + pthread_mutex_unlock(&w->mutex); +} + +#define __xf_wakeup(w) \ +({ \ + TRACE(1, _x("wakeup")); \ + (__xf_wakeup)(w); \ +}) + +/* ...complete waiting operation */ +static inline void __xf_wait_complete(xf_wait_t *w) +{ + pthread_mutex_unlock(&w->mutex); +} + +#define __xf_wait_complete(w) \ +({ \ + TRACE(1, _x("wait-complete")); \ + (__xf_wait_complete)(w); \ +}) +#endif + +/******************************************************************************* + * Thread support + ******************************************************************************/ + +/* ...thread handle definition */ +typedef XosThread xf_thread_t; +typedef XosThreadFunc xf_entry_t; + +/* ...thread creation */ +static inline int __xf_thread_create(xf_thread_t *thread, xf_entry_t *f, + void *arg, const char *name, void * stack, + unsigned int stack_size, int priority) +{ + int r; + + /* ...create proxy asynchronous thread managing SHMEM */ + r = xos_thread_create(thread, 0, f, arg, name, stack, stack_size, priority, 0, 0); + + return r; +} + +/* ...terminate thread operation */ +static inline int __xf_thread_destroy(xf_thread_t *thread) +{ + int r; + + /* ...wait until thread terminates */ + /* v-tbd - avoid infinite wait for join */ + //xos_thread_join(thread, &r); + + /* ...delete thread, free up TCB, stack */ + r = xos_thread_delete(thread); + + /* ...return final status */ + return r; +} + diff --git a/hifi/xaf/host-apf/include/sys/fio/xf-config.h b/hifi/xaf/host-apf/include/sys/fio/xf-config.h new file mode 100644 index 00000000..2e1d4c61 --- /dev/null +++ b/hifi/xaf/host-apf/include/sys/fio/xf-config.h @@ -0,0 +1,36 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +/* ...number of DSP cores */ +#define XF_CFG_CORES_NUM 4 + +/* ...maximal number of clients supported by proxy */ +#define XF_CFG_PROXY_MAX_CLIENTS 256 + +/* ...size of the shared memory pool (in bytes) */ +#define XF_CFG_REMOTE_IPC_POOL_SIZE (256 << 10) + +/* ...size of the component(DSP) local memory pool (in bytes) */ +#define XF_CFG_LOCAL_POOL_SIZE (1024<< 10) + +/* ...alignment for shared buffers */ +#define XF_PROXY_ALIGNMENT 64 diff --git a/hifi/xaf/host-apf/include/sys/fio/xf-hal.h b/hifi/xaf/host-apf/include/sys/fio/xf-hal.h new file mode 100644 index 00000000..15a82b03 --- /dev/null +++ b/hifi/xaf/host-apf/include/sys/fio/xf-hal.h @@ -0,0 +1,34 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#ifndef __XF_H +#error "xf-hal.h mustn't be included directly" +#endif + +/******************************************************************************* + * Includes + ******************************************************************************/ + +/* ...primitive types */ +#include "xf-types.h" + +/* ...anything else? - tbd */ diff --git a/hifi/xaf/host-apf/include/sys/fio/xf-ipc.h b/hifi/xaf/host-apf/include/sys/fio/xf-ipc.h new file mode 100644 index 00000000..2ee859a8 --- /dev/null +++ b/hifi/xaf/host-apf/include/sys/fio/xf-ipc.h @@ -0,0 +1,127 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#ifndef __XF_H +#error "xf-ipc.h mustn't be included directly" +#endif + +/******************************************************************************* + * Types definitions + ******************************************************************************/ + +/* ...proxy IPC data */ +typedef struct xf_proxy_ipc_data +{ + /* ...shared memory buffer pointer */ + void *shmem; + + /* ...file descriptor */ + int fd; + + /* ...pipe for asynchronous response delivery */ + int pipe[2]; + +} xf_proxy_ipc_data_t; + +/******************************************************************************* + * Helpers for asynchronous response delivery + ******************************************************************************/ + +#define xf_proxy_ipc_response_put(ipc, msg) \ + (write((ipc)->pipe[1], (msg), sizeof(*(msg))) == sizeof(*(msg)) ? 0 : -errno) + +#define xf_proxy_ipc_response_get(ipc, msg) \ + (read((ipc)->pipe[0], (msg), sizeof(*(msg))) == sizeof(*(msg)) ? 0 : -errno) + +/******************************************************************************* + * Shared memory translation + ******************************************************************************/ + +/* ...translate proxy shared address into local virtual address */ +static inline void * xf_ipc_a2b(xf_proxy_ipc_data_t *ipc, u32 address) +{ + if (address < XF_CFG_REMOTE_IPC_POOL_SIZE) + return (unsigned char *) ipc->shmem + address; + else if (address == XF_PROXY_NULL) + return NULL; + else + return (void *) -1; +} + +/* ...translate local virtual address into shared proxy address */ +static inline u32 xf_ipc_b2a(xf_proxy_ipc_data_t *ipc, void *b) +{ + u32 a; + + if (b == NULL) + return XF_PROXY_NULL; + if ((a = (u32)((u8 *)b - (u8 *)ipc->shmem)) < XF_CFG_REMOTE_IPC_POOL_SIZE) + return a; + else + return XF_PROXY_BADADDR; +} + +/******************************************************************************* + * Component inter-process communication + ******************************************************************************/ + +typedef struct xf_ipc_data +{ + /* ...asynchronous response delivery pipe */ + int pipe[2]; + +} xf_ipc_data_t; + +/******************************************************************************* + * Helpers for asynchronous response delivery + ******************************************************************************/ + +#define xf_ipc_response_put(ipc, msg) \ + (write((ipc)->pipe[1], (msg), sizeof(*(msg))) == sizeof(*(msg)) ? 0 : -errno) + +#define xf_ipc_response_get(ipc, msg) \ + (read((ipc)->pipe[0], (msg), sizeof(*(msg))) == sizeof(*(msg)) ? 0 : -errno) + +#define xf_ipc_data_init(ipc) \ + (pipe((ipc)->pipe) == 0 ? 0 : -errno) + +#define xf_ipc_data_destroy(ipc) \ + (close((ipc)->pipe[0]), close((ipc)->pipe[1])) + +/******************************************************************************* +* API functions + ******************************************************************************/ + +/* ...send asynchronous command */ +extern int xf_ipc_send(xf_proxy_ipc_data_t *ipc, xf_proxy_msg_t *msg, void *b); + +/* ...wait for response from remote proxy */ +extern int xf_ipc_wait(xf_proxy_ipc_data_t *ipc, u32 timeout); + +/* ...receive response from IPC layer */ +extern int xf_ipc_recv(xf_proxy_ipc_data_t *ipc, xf_proxy_msg_t *msg, void **b); + +/* ...open proxy interface on proper DSP partition */ +extern int xf_ipc_open(xf_proxy_ipc_data_t *proxy, u32 core, void *p_shmem); + +/* ...close proxy handle */ +extern void xf_ipc_close(xf_proxy_ipc_data_t *proxy, u32 core); diff --git a/hifi/xaf/host-apf/include/sys/fio/xf-runtime.h b/hifi/xaf/host-apf/include/sys/fio/xf-runtime.h new file mode 100644 index 00000000..9cad95f4 --- /dev/null +++ b/hifi/xaf/host-apf/include/sys/fio/xf-runtime.h @@ -0,0 +1,35 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#ifndef __XF_H +#error "xf-runtime.h mustn't be included directly" +#endif + +/******************************************************************************* + * Includes + ******************************************************************************/ + +/* ...platform HAL layer */ +#include "xf-hal.h" + +/* ...OS abstraction layer */ +#include "xf-osal.h" diff --git a/hifi/xaf/host-apf/include/sys/fio/xf-types.h b/hifi/xaf/host-apf/include/sys/fio/xf-types.h new file mode 100644 index 00000000..a610c8e1 --- /dev/null +++ b/hifi/xaf/host-apf/include/sys/fio/xf-types.h @@ -0,0 +1,88 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#ifndef __XF_H +#error "xf-types.h mustn't be included directly" +#endif + +/******************************************************************************* + * Standard includes + ******************************************************************************/ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include <stdarg.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <assert.h> +#include <errno.h> + +#include <unistd.h> +#include <fcntl.h> +#include <pthread.h> +#include <signal.h> +#include <limits.h> +#include <sys/mman.h> +#include <sys/ioctl.h> +#include <sys/time.h> + +/******************************************************************************* + * Primitive types + ******************************************************************************/ + +typedef uint32_t u32; +typedef int32_t s32; +typedef uint16_t u16; +typedef int16_t s16; +typedef uint8_t u8; +typedef int8_t s8; + +/******************************************************************************* + * Macros definitions + ******************************************************************************/ + +/* ...NULL-address specification */ +#define XF_PROXY_NULL (~0U) + +/* ...invalid proxy address */ +#define XF_PROXY_BADADDR XF_CFG_REMOTE_IPC_POOL_SIZE + +/******************************************************************************* + * Auxiliary helpers + ******************************************************************************/ + +/* ...next power-of-two calculation */ +#define xf_next_power_of_two(v) __xf_power_of_two_1((v) - 1) +#define __xf_power_of_two_1(v) __xf_power_of_two_2((v) | ((v) >> 1)) +#define __xf_power_of_two_2(v) __xf_power_of_two_3((v) | ((v) >> 2)) +#define __xf_power_of_two_3(v) __xf_power_of_two_4((v) | ((v) >> 4)) +#define __xf_power_of_two_4(v) __xf_power_of_two_5((v) | ((v) >> 8)) +#define __xf_power_of_two_5(v) __xf_power_of_two_6((v) | ((v) >> 16)) +#define __xf_power_of_two_6(v) ((v) + 1) + +/* ...check if non-zero value is a power-of-two */ +#define xf_is_power_of_two(v) (((v) & ((v) - 1)) == 0) + diff --git a/hifi/xaf/host-apf/include/xaf-api.h b/hifi/xaf/host-apf/include/xaf-api.h new file mode 100644 index 00000000..5cebb430 --- /dev/null +++ b/hifi/xaf/host-apf/include/xaf-api.h @@ -0,0 +1,139 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + + +/* ...number of max input buffers */ +#define XAF_MAX_INBUFS 2 +#define XAF_INBUF_SIZE 8192 + +typedef enum { + XAF_DECODER = 0, + XAF_ENCODER = 1, + XAF_MIXER = 2, + XAF_PRE_PROC = 3, + XAF_POST_PROC = 4, +} xaf_comp_type; + +typedef enum { + XAF_STARTING = 0, + XAF_INIT_DONE = 1, + XAF_NEED_INPUT = 2, + XAF_OUTPUT_READY = 3, + XAF_EXEC_DONE = 4, +} xaf_comp_status; + +typedef enum { + XAF_START_FLAG = 1, + XAF_EXEC_FLAG = 2, + XAF_INPUT_OVER_FLAG = 3, + XAF_INPUT_READY_FLAG = 4, + XAF_NEED_OUTPUT_FLAG = 5, +} xaf_comp_flag; + +typedef enum { + XAF_NO_ERROR = 0, + XAF_PTR_ERROR = -1, + XAF_INVALID_VALUE = -2, + XAF_ROUTING_ERROR = -3, + /*XAF_XOS_ERROR = -4,*/ + XAF_API_ERR = -5, +} XAF_ERR_CODE; + +typedef enum { + XAF_MEM_ID_DEV = 0, + XAF_MEM_ID_COMP = 1, +} XAF_MEM_ID; + +/* structure for component memory sizes */ +typedef struct xaf_mem_size_s{ + u32 persist; + u32 scratch; + u32 input; + u32 output; +}xaf_mem_size_t; + +/* structure for host-side utility handles */ +typedef struct xaf_ap_utils_s{ + int xf_cfg_remote_ipc_pool_size; + xaf_mem_size_t mem_size; +}xaf_ap_utils_t; + +typedef struct xaf_format_s { + u32 sample_rate; + u32 channels; + u32 pcm_width; + u32 input_length; + u32 output_length; +} xaf_format_t; + +#ifndef XAF_HOSTLESS +typedef struct xaf_info_s { + void * buf; + u32 length; +} xaf_info_t; +#endif + +XAF_ERR_CODE xaf_adev_open(void **pp_adev, s32 audio_frmwk_buf_size, s32 audio_comp_buf_size, xaf_mem_malloc_fxn_t mm_malloc, xaf_mem_free_fxn_t mm_free); +XAF_ERR_CODE xaf_adev_close(void *adev_ptr, xaf_comp_flag flag); + +XAF_ERR_CODE xaf_comp_create(void* p_adev, void **p_comp, xf_id_t comp_id, u32 ninbuf, u32 noutbuf, void *pp_inbuf[], xaf_comp_type comp_type); +XAF_ERR_CODE xaf_comp_delete(void* p_comp); +XAF_ERR_CODE xaf_comp_set_config(void *p_comp, s32 num_param, s32 *p_param); +XAF_ERR_CODE xaf_comp_get_config(void *p_comp, s32 num_param, s32 *p_param); +XAF_ERR_CODE xaf_comp_process(void *p_adev, void *p_comp, void *p_buf, u32 length, xaf_comp_flag flag); +XAF_ERR_CODE xaf_connect(void *p_src, void *p_dest, s32 num_buf); + +/* Not available in this version yet. +XAF_ERR_CODE xaf_disconnect(xaf_comp_t *p_comp); +*/ + +XAF_ERR_CODE xaf_comp_get_status(void *p_adev, void *p_comp, xaf_comp_status *p_status, xaf_info_t *p_info); + +/* ...check null pointer */ +#define XAF_CHK_PTR(ptr) \ +({ \ + int __ret; \ + \ + if ((__ret = (int)(ptr)) == 0) \ + { \ + TRACE(ERROR, _x("Null pointer error: %d"), __ret); \ + return XAF_PTR_ERROR; \ + } \ + __ret; \ +}) + +/* ...check range */ +#define XAF_CHK_RANGE(val, min, max) \ +({ \ + int __ret = val; \ + \ + if ((__ret < (int)min) || (__ret > (int)max)) \ + { \ + TRACE(ERROR, _x("Invalid value: %d"), __ret); \ + return XAF_INVALID_VALUE; \ + } \ + __ret; \ +}) + + + + diff --git a/hifi/xaf/host-apf/include/xaf-structs.h b/hifi/xaf/host-apf/include/xaf-structs.h new file mode 100644 index 00000000..f632600a --- /dev/null +++ b/hifi/xaf/host-apf/include/xaf-structs.h @@ -0,0 +1,82 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +/* ...size of auxiliary pool for communication with HiFi */ +#define XAF_AUX_POOL_SIZE 32 + +/* ...length of auxiliary pool messages */ +#define XAF_AUX_POOL_MSG_LENGTH 128 +#define XAF_MAX_CONFIG_PARAMS (XAF_AUX_POOL_MSG_LENGTH >> 3) + +typedef struct xaf_comp xaf_comp_t; + +struct xaf_comp { + xf_handle_t handle; + + u32 inp_routed; + u32 out_routed; + u32 inp_ports; + u32 out_ports; + u32 init_done; + u32 pending_resp; + u32 expect_out_cmd; + u32 input_over; + + xaf_comp_type comp_type; + xaf_comp_status comp_status; + u32 start_cmd_issued; + u32 exec_cmd_issued; + void *start_buf; + + xaf_format_t inp_format; + xaf_format_t out_format; + + xf_pool_t *inpool; + xf_pool_t *outpool; + u32 noutbuf; + + xaf_comp_t *next; + + u32 ninbuf; + void *p_adev; + //xaf_comp_state comp_state; + void *comp_ptr; +}; + +typedef struct xaf_adev_s { + xf_proxy_t proxy; + xaf_comp_t *comp_chain; + + u32 n_comp; + void *adev_ptr; + void *p_dspMem; + void *p_apMem; + void *p_dspLocalBuff; + void *p_apSharedMem; + + xaf_ap_utils_t *p_ap_utils; //host-side utility structure handle + void *(*pxf_mem_malloc_fxn)(s32, s32); + void (*pxf_mem_free_fxn)(void *,s32); + //xaf_adev_state adev_state; + +} xaf_adev_t; + diff --git a/hifi/xaf/host-apf/include/xf-debug.h b/hifi/xaf/host-apf/include/xf-debug.h new file mode 100644 index 00000000..83172302 --- /dev/null +++ b/hifi/xaf/host-apf/include/xf-debug.h @@ -0,0 +1,194 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#ifndef __XF_H +#error "xf-debug.h mustn't be included directly" +#endif + +/******************************************************************************* + * Auxiliary macros (put into "xf-types.h"?) + ******************************************************************************/ + +#ifndef offset_of +#define offset_of(type, member) \ + ((int)(intptr_t)&(((const type *)(0))->member)) +#endif + +#ifndef container_of +#define container_of(ptr, type, member) \ + ((type *)((void *)(ptr) - offset_of(type, member))) +#endif + +/******************************************************************************* + * Bug check for constant conditions (file scope) + ******************************************************************************/ + +#define __C_BUG(n) __C_BUG2(n) +#define __C_BUG2(n) __c_bug_##n +#define C_BUG(expr) typedef char __C_BUG(__LINE__)[(expr) ? -1 : 1] + +/******************************************************************************* + * Compilation-time types control + ******************************************************************************/ + +#if XF_DEBUG +#define __C_TYPE_CONTROL(d, type) ((void) ((d) != (type*) 0)) +#else +#define __C_TYPE_CONTROL(d, type) ((void) 0) +#endif + +/******************************************************************************* + * Unused variable + ******************************************************************************/ + +#define C_UNUSED(v) (void)(0 ? (v) = (v), 1 : 0) + +/******************************************************************************* + * Auxiliary macros + ******************************************************************************/ + +/* ...define a stub for unused declarator */ +#define __xf_stub(tag, line) __xf_stub2(tag, line) +#define __xf_stub2(tag, line) typedef int __xf_##tag##_##line + +/* ...convert anything into string */ +#define __xf_string(x) __xf_string2(x) +#define __xf_string2(x) #x + +/******************************************************************************* + * Tracing facility + ******************************************************************************/ + +#if XF_TRACE + +/* ...tracing to communication processor */ +extern int xf_trace(const char *format, ...); + +/* ...tracing facility initialization */ +extern void xf_trace_init(const char *banner); + +/* ...initialize tracing facility */ +#define TRACE_INIT(banner) (xf_trace_init(banner)) + +/* ...trace tag definition */ +#define TRACE_TAG(tag, on) enum { __xf_trace_##tag = on } + +/* ...check if the trace tag is enabled */ +#define TRACE_CFG(tag) (__xf_trace_##tag) + +/* ...tagged tracing primitive */ +#define TRACE(tag, fmt, ...) (void)(__xf_trace_##tag ? __xf_trace(tag, __xf_format##fmt, ## __VA_ARGS__), 1 : 0) + +/******************************************************************************* + * Tagged tracing formats + ******************************************************************************/ + +/* ...tracing primitive */ +#define __xf_trace(tag, fmt, ...) \ + ({ __attribute__((unused)) const char *__xf_tag = #tag; xf_trace(fmt, ## __VA_ARGS__); }) + +/* ...just a format string */ +#define __xf_format_n(fmt) fmt + +/* ...module tag and trace tag shown */ +#define __xf_format_b(fmt) "[%s.%s] " fmt, __xf_string(MODULE_TAG), __xf_tag + +/* ...module tag, trace tag, file name and line shown */ +#define __xf_format_x(fmt) "[%s.%s] - %s@%d - " fmt, __xf_string(MODULE_TAG), __xf_tag, __FILE__, __LINE__ + +/******************************************************************************* + * Globally defined tags + ******************************************************************************/ + +/* ...unconditionally OFF */ +TRACE_TAG(0, 0); + +/* ...unconditionally ON */ +TRACE_TAG(1, 1); + +/* ...error output - on by default */ +TRACE_TAG(ERROR, 1); + +#else + +#define TRACE_INIT(banner) (void)0 +#define TRACE_TAG(tag, on) __xf_stub(trace_##tag, __LINE__) +#define TRACE(tag, fmt, ...) (void)0 +#define __xf_trace(tag, fmt, ...) (void)0 + +#endif /* XF_TRACE */ + +/******************************************************************************* + * Bugchecks + ******************************************************************************/ + +#if XF_DEBUG + +/* ...run-time bugcheck */ +#define BUG(cond, fmt, ...) \ +do \ +{ \ + if (cond) \ + { \ + /* ...output message */ \ + __xf_trace(BUG, __xf_format##fmt, ## __VA_ARGS__); \ + \ + /* ...and die */ \ + abort(); \ + } \ +} \ +while (0) + +#else +#define BUG(cond, fmt, ...) (void)0 +#endif /* XF_DEBUG */ + +/******************************************************************************* + * Run-time error processing + ******************************************************************************/ + +/* ...check the API call succeeds */ +#define XF_CHK_API(cond) \ +({ \ + int __ret; \ + \ + if ((__ret = (int)(cond)) < 0) \ + { \ + TRACE(ERROR, _x("API error: %d"), __ret); \ + return __ret; \ + } \ + __ret; \ +}) + +/* ...check the condition is true */ +#define XF_CHK_ERR(cond, error) \ +({ \ + intptr_t __ret; \ + \ + if (!(__ret = (intptr_t)(cond))) \ + { \ + TRACE(ERROR, _x("check failed")); \ + return (error); \ + } \ + (int)__ret; \ +}) + diff --git a/hifi/xaf/host-apf/include/xf-opcode.h b/hifi/xaf/host-apf/include/xf-opcode.h new file mode 100644 index 00000000..f585f5c2 --- /dev/null +++ b/hifi/xaf/host-apf/include/xf-opcode.h @@ -0,0 +1,297 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#ifndef __XF_H +#error "xf-opcode.h mustn't be included directly" +#endif + +/******************************************************************************* + * Message routing composition - move somewhere else - tbd + ******************************************************************************/ + +/* ...adjust IPC client of message going from user-space */ +#define XF_MSG_AP_FROM_USER(id, client) \ + (((id) & ~(0xF << 2)) | (client)) + +/* ...wipe out IPC client from message going to user-space */ +#define XF_MSG_AP_TO_USER(id) \ + ((id) & ~(0xF << 18)) + +/* ...port specification (12 bits) */ +#define __XF_PORT_SPEC(core, id, port) ((core) | ((id) << 2) | ((port) << 8)) +#define __XF_PORT_SPEC2(id, port) ((id) | ((port) << 8)) +#define XF_PORT_CORE(spec) ((spec) & 0x3) +#define XF_PORT_CLIENT(spec) (((spec) >> 2) & 0x3F) +#define XF_PORT_ID(spec) (((spec) >> 8) & 0xF) + +/* ...message id contains source and destination ports specification */ +#define __XF_MSG_ID(src, dst) (((src) & 0xFFFF) | (((dst) & 0xFFFF) << 16)) +#define XF_MSG_SRC(id) (((id) >> 0) & 0xFFFF) +#define XF_MSG_SRC_CORE(id) (((id) >> 0) & 0x3) +#define XF_MSG_SRC_CLIENT(id) (((id) >> 2) & 0x3F) +#define XF_MSG_SRC_ID(id) (((id) >> 0) & 0xFF) +#define XF_MSG_SRC_PORT(id) (((id) >> 8) & 0xF) +#define XF_MSG_SRC_PROXY(id) (((id) >> 15) & 0x1) +#define XF_MSG_DST(id) (((id) >> 16) & 0xFFFF) +#define XF_MSG_DST_CORE(id) (((id) >> 16) & 0x3) +#define XF_MSG_DST_CLIENT(id) (((id) >> 18) & 0x3F) +#define XF_MSG_DST_ID(id) (((id) >> 16) & 0xFF) +#define XF_MSG_DST_PORT(id) (((id) >> 24) & 0xF) +#define XF_MSG_DST_PROXY(id) (((id) >> 31) & 0x1) + +/* ...special treatment of AP-proxy destination field */ +#define XF_AP_IPC_CLIENT(id) (((id) >> 18) & 0xF) +#define XF_AP_CLIENT(id) (((id) >> 22) & 0x1FF) +#define __XF_AP_PROXY(core) ((core) | 0x8000) +#define __XF_DSP_PROXY(core) ((core) | 0x8000) +#define __XF_AP_CLIENT(core, client) ((core) | ((client) << 6) | 0x8000) + +/******************************************************************************* + * Opcode composition + ******************************************************************************/ + +/* ...opcode composition with command/response data tags */ +#define __XF_OPCODE(c, r, op) (((c) << 31) | ((r) << 30) | ((op) & 0x3F)) + +/* ...accessors */ +#define XF_OPCODE_CDATA(opcode) ((opcode) & (1 << 31)) +#define XF_OPCODE_RDATA(opcode) ((opcode) & (1 << 30)) +#define XF_OPCODE_TYPE(opcode) ((opcode) & (0x3F)) + +/******************************************************************************* + * Opcode types + ******************************************************************************/ + +/* ...unregister client */ +#define XF_UNREGISTER __XF_OPCODE(0, 0, 0) + +/* ...register client at proxy */ +#define XF_REGISTER __XF_OPCODE(1, 0, 1) + +/* ...port routing command */ +#define XF_ROUTE __XF_OPCODE(1, 0, 2) + +/* ...port unrouting command */ +#define XF_UNROUTE __XF_OPCODE(1, 0, 3) + +/* ...shared buffer allocation */ +#define XF_ALLOC __XF_OPCODE(0, 0, 4) + +/* ...shared buffer freeing */ +#define XF_FREE __XF_OPCODE(0, 0, 5) + +/* ...set component parameters */ +#define XF_SET_PARAM __XF_OPCODE(1, 0, 6) + +/* ...get component parameters */ +#define XF_GET_PARAM __XF_OPCODE(1, 1, 7) + +/* ...input buffer reception */ +#define XF_EMPTY_THIS_BUFFER __XF_OPCODE(1, 0, 8) + +/* ...output buffer reception */ +#define XF_FILL_THIS_BUFFER __XF_OPCODE(0, 1, 9) + +/* ...flush specific port */ +#define XF_FLUSH __XF_OPCODE(0, 0, 10) + +/* ...start component operation */ +#define XF_START __XF_OPCODE(0, 0, 11) + +/* ...stop component operation */ +#define XF_STOP __XF_OPCODE(0, 0, 12) + +/* ...pause component operation */ +#define XF_PAUSE __XF_OPCODE(0, 0, 13) + +/* ...resume component operation */ +#define XF_RESUME __XF_OPCODE(0, 0, 14) + +/* ...extended parameter setting function */ +#define XF_SET_PARAM_EXT __XF_OPCODE(1, 1, 15) + +/* ...extended parameter retrieval function */ +#define XF_GET_PARAM_EXT __XF_OPCODE(1, 1, 16) + +/* ...total amount of supported decoder commands */ +#define __XF_OP_NUM 17 + +/******************************************************************************* + * XF_START message definition + ******************************************************************************/ + +typedef struct xf_start_msg +{ + /* ...effective sample rate */ + u32 sample_rate; + + /* ...number of channels */ + u32 channels; + + /* ...sample width */ + u32 pcm_width; + + /* ...minimal size of intput buffer */ + u32 input_length; + + /* ...size of output buffer */ + u32 output_length; + +} __attribute__((__packed__)) xf_start_msg_t; + +/******************************************************************************* + * XF_GET_PARAM message + ******************************************************************************/ + +/* ...message body (command/response) */ +typedef union xf_get_param_msg +{ + /* ...command structure */ + struct + { + /* ...array of parameters requested */ + u32 id[0]; + + } __attribute__((__packed__)) c; + + /* ...response structure */ + struct + { + /* ...array of parameters values */ + u32 value[0]; + + } __attribute__((__packed__)) r; + +} xf_get_param_msg_t; + +/* ...length of the XF_GET_PARAM command/response */ +#define XF_GET_PARAM_CMD_LEN(params) (sizeof(u32) * (params)) +#define XF_GET_PARAM_RSP_LEN(params) (sizeof(u32) * (params)) + +/******************************************************************************* + * XF_SET_PARAM message + ******************************************************************************/ + +/* ...component initialization parameter */ +typedef struct xf_set_param_item +{ + /* ...index of parameter passed to SET_CONFIG_PARAM call */ + u32 id; + + /* ...value of parameter */ + u32 value; + +} __attribute__ ((__packed__)) xf_set_param_item_t; + +/* ...message body (no response message? - tbd) */ +typedef struct xf_set_param_msg +{ + /* ...command message */ + xf_set_param_item_t item[0]; + +} __attribute__ ((__packed__)) xf_set_param_msg_t; + +/* ...length of the command message */ +#define XF_SET_PARAM_CMD_LEN(params) (sizeof(xf_set_param_item_t) * (params)) + +/******************************************************************************* + * XF_SET_PARAM_EXT/XF_GET_PARAM_EXT message + ******************************************************************************/ + +/* ...extended parameter descriptor */ +typedef struct xf_ext_param_desc +{ + /* ...index of parameter passed to SET/GET_CONFIG_PARAM call (16-bits only) */ + u16 id; + + /* ...length of embedded input/output parameter data (in bytes) */ + u16 length; + +} __attribute__ ((__packed__, __aligned__(4))) xf_ext_param_desc_t; + +/* ...message body (no response message? - tbd) */ +typedef struct xf_ext_param_msg +{ + /* ...extended parameter descriptor */ + xf_ext_param_desc_t desc; + + /* ...parameter data (in the format expected by codec) */ + u8 data[0]; + +} __attribute__ ((__packed__)) xf_ext_param_msg_t; + +/* ...access macros */ + +#define xf_ext_param_first(e) \ + (&(e)->desc) + +#define xf_ext_param_next(d) \ + (xf_ext_param_desc_t *)(((xf_ext_param_msg_t *)(d))->data + (((d)->length + 3) & ~3)) + +#define xf_ext_param_length(e, d) \ + ((u32)((u8 *)(d) - (u8 *)(ext))) + +#define xf_ext_param_data(d, t) \ + ((t *)&(d)[1]) + +#define xf_ext_param_setup(d, i, t, s) \ + ((d)->id = (i), (d)->length = (s), xf_ext_param_data(d, t)) + + +/******************************************************************************* + * XF_ROUTE definition + ******************************************************************************/ + +/* ...port routing command */ +typedef struct xf_route_port_msg +{ + /* ...source port specification */ + u32 src; + + /* ...destination port specification */ + u32 dst; + + /* ...number of buffers to allocate */ + u32 alloc_number; + + /* ...length of buffer to allocate */ + u32 alloc_size; + + /* ...alignment restriction for a buffer */ + u32 alloc_align; + +} __attribute__((__packed__)) xf_route_port_msg_t; + +/******************************************************************************* + * XF_UNROUTE definition + ******************************************************************************/ + +/* ...port unrouting command */ +typedef struct xf_unroute_port_msg +{ + /* ...source port specification */ + u32 src; + + /* ...destination port specification */ + u32 dst; + +} __attribute__((__packed__)) xf_unroute_port_msg_t; diff --git a/hifi/xaf/host-apf/include/xf-proto.h b/hifi/xaf/host-apf/include/xf-proto.h new file mode 100644 index 00000000..095e353a --- /dev/null +++ b/hifi/xaf/host-apf/include/xf-proto.h @@ -0,0 +1,82 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#ifndef __XF_H +#error "xf-proto.h mustn't be included directly" +#endif + +/******************************************************************************* + * Forward types declarations + ******************************************************************************/ + +/* ...component string identifier */ +typedef const char *xf_id_t; + +/* ...handle to proxy data */ +typedef struct xf_proxy xf_proxy_t; + +/* ...handle to component data */ +typedef struct xf_handle xf_handle_t; + +/* ...buffer pool */ +typedef struct xf_pool xf_pool_t; + +/* ...individual buffer from pool */ +typedef struct xf_buffer xf_buffer_t; + +/* ...buffer pool type */ +typedef u32 xf_pool_type_t; + +/* ...user-message */ +typedef struct xf_user_msg xf_user_msg_t; + +/* ...proxy-message */ +typedef struct xf_proxy_msg xf_proxy_msg_t; + +/* ...response callback */ +typedef void (*xf_response_cb)(xf_handle_t *h, xf_user_msg_t *msg); + +typedef void* xaf_mem_malloc_fxn_t(s32 size, s32 id); +typedef void xaf_mem_free_fxn_t(void* ptr, s32 id); + +/******************************************************************************* + * High-level API functions + ******************************************************************************/ + +/* ...component operations */ +extern int xf_open(xf_proxy_t *proxy, xf_handle_t *handle, xf_id_t id, u32 core, xf_response_cb cb); +extern void xf_close(xf_handle_t *handle); +extern int xf_command(xf_handle_t *handle, u32 dst, u32 opcode, void *buf, u32 length); +extern int xf_route(xf_handle_t *src, u32 s_port, xf_handle_t *dst, u32 d_port, u32 num, u32 size, u32 align); +extern int xf_unroute(xf_handle_t *src, u32 s_port); + +/* ...shared buffers operations */ +extern int xf_pool_alloc(xf_proxy_t *proxy, u32 number, u32 length, xf_pool_type_t type, xf_pool_t **pool, s32 id, + xaf_mem_malloc_fxn_t, xaf_mem_free_fxn_t); +extern void xf_pool_free(xf_pool_t *pool, s32 id, xaf_mem_free_fxn_t); +extern xf_buffer_t * xf_buffer_get(xf_pool_t *pool); +extern void xf_buffer_put(xf_buffer_t *buffer); + +/* ...proxy operations */ +extern int xf_proxy_init(xf_proxy_t *proxy, u32 core, void *p_shmem); +extern void xf_proxy_close(xf_proxy_t *proxy); + diff --git a/hifi/xaf/host-apf/include/xf-proxy.h b/hifi/xaf/host-apf/include/xf-proxy.h new file mode 100644 index 00000000..90d70793 --- /dev/null +++ b/hifi/xaf/host-apf/include/xf-proxy.h @@ -0,0 +1,297 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#ifndef __XF_H +#error "xf-proxy.h mustn't be included directly" +#endif + +/******************************************************************************* + * User-message description - move from here to API - tbd + ******************************************************************************/ + +/* ...need that at all? hope no */ +struct xf_user_msg +{ + /* ...source component specification */ + u32 id; + + /* ...message opcode */ + u32 opcode; + + /* ...buffer length */ + u32 length; + + /* ...buffer pointer */ + void *buffer; +}; + +/* ...proxy message - bad placing of that thing here - tbd */ +struct xf_proxy_msg +{ + /* ...session-id field */ + uint32_t id; + + /* ...message opcode */ + uint32_t opcode; + + /* ...buffer length */ + uint32_t length; + + /* ...buffer pointer */ + uint64_t address; + uint64_t v_address; + +} __attribute__((__packed__)); + +typedef struct xf_proxy_msg_driv +{ + /* ...session ID */ + uint32_t id; + + /* ...proxy API command/reponse code */ + uint32_t opcode; + + /* ...length of attached buffer */ + uint32_t length; + + /* ...physical address of message buffer */ + uint64_t address; + uint64_t v_address; + +}__attribute__((__packed__)) xf_proxy_message_driv_t; +/******************************************************************************* + * Buffer pools + ******************************************************************************/ + +/* ...buffer pool type */ +enum xf_pool_type +{ + XF_POOL_AUX = 0, + XF_POOL_INPUT = 1, + XF_POOL_OUTPUT = 2 +}; + +/* ...buffer link pointer */ +typedef union xf_buffer_link +{ + /* ...pointer to next free buffer in a pool (for free buffer) */ + xf_buffer_t *next; + + /* ...reference to a buffer pool (for allocated buffer) */ + xf_pool_t *pool; + +} xf_buffer_link_t; + +/* ...buffer descriptor */ +struct xf_buffer +{ + /* ...virtual address of contiguous buffer */ + void *address; + + /* ...link pointer */ + xf_buffer_link_t link; +}; + +/* ...buffer pool */ +struct xf_pool +{ + /* ...reference to proxy data */ + xf_proxy_t *proxy; + + /* ...length of individual buffer in a pool */ + u32 length; + + /* ...number of buffers in a pool */ + u32 number; + + /* ...pointer to pool memory */ + void *p; + + /* ...pointer to first free buffer in a pool */ + xf_buffer_t *free; + + /* ...individual buffers */ + xf_buffer_t buffer[0]; +}; + +/* ...accessor to buffer data */ +static inline void * xf_buffer_data(xf_buffer_t *buffer) +{ + return buffer->address; +} + +/* ...length of buffer data */ +static inline size_t xf_buffer_length(xf_buffer_t *buffer) +{ + return buffer->link.pool->length; +} + +/******************************************************************************* + * Proxy handle definition + ******************************************************************************/ + +/* ...free clients list */ +typedef union xf_proxy_cmap_link +{ + /* ...index of next free client in the list */ + u32 next; + + /* ...pointer to allocated component handle */ + xf_handle_t *handle; + +} xf_proxy_cmap_link_t; + +/* ...proxy data structure */ +struct xf_proxy +{ + /* ...platform-specific IPC data */ + xf_proxy_ipc_data_t ipc; + + /* ...auxiliary buffer pool for clients */ + xf_pool_t *aux; + + /* ...global proxy lock */ + xf_lock_t lock; + + /* ...proxy thread handle */ + xf_thread_t thread; + + /* ...proxy identifier (core of remote DSP hosting SHMEM interface) */ + u32 core; + + /* ...client association map */ + xf_proxy_cmap_link_t cmap[XF_CFG_PROXY_MAX_CLIENTS]; +}; + +/******************************************************************************* + * Auxiliary proxy helpers + ******************************************************************************/ + +/* ...get proxy identifier */ +static inline u32 xf_proxy_id(xf_proxy_t *proxy) +{ + return proxy->core; +} + +/* ...lock proxy data */ +static inline void xf_proxy_lock(xf_proxy_t *proxy) +{ + __xf_lock(&proxy->lock); +} + +/* ...unlock proxy data */ +static inline void xf_proxy_unlock(xf_proxy_t *proxy) +{ + __xf_unlock(&proxy->lock); +} + +/* ...translate proxy shared address into local virtual address */ +static inline void * xf_proxy_a2b(xf_proxy_t *proxy, u32 address) +{ + return xf_ipc_a2b(&proxy->ipc, address); +} + +/* ...translate local virtual address into shared proxy address */ +static inline u32 xf_proxy_b2a(xf_proxy_t *proxy, void *b) +{ + return xf_ipc_b2a(&proxy->ipc, b); +} + +/* ...submit asynchronous response message */ +static inline int xf_proxy_response_put(xf_proxy_t *proxy, xf_proxy_msg_t *msg) +{ + return xf_proxy_ipc_response_put(&proxy->ipc, msg); +} + +/* ...retrieve asynchronous response message */ +static inline int xf_proxy_response_get(xf_proxy_t *proxy, xf_proxy_msg_t *msg) +{ + return xf_proxy_ipc_response_get(&proxy->ipc, msg); +} + +/******************************************************************************* + * Component handle definition + ******************************************************************************/ + +struct xf_handle +{ + /* ...platform-specific IPC data */ + xf_ipc_data_t ipc; + + /* ...reference to proxy data */ + xf_proxy_t *proxy; + + /* ...component lock */ + xf_lock_t lock; + + /* ...auxiliary control buffer for control transactions */ + xf_buffer_t *aux; + + /* ...global client-id of the component */ + u32 id; + + /* ...local client number (think about merging into "id" field - tbd) */ + u32 client; + + /* ...response processing hook */ + xf_response_cb response; +}; + +/******************************************************************************* + * Auxiliary component helpers + ******************************************************************************/ + +/* ...component client-id (global scope) */ +static inline u32 xf_handle_id(xf_handle_t *handle) +{ + return handle->id; +} + +/* ...pointer to auxiliary buffer */ +static inline void * xf_handle_aux(xf_handle_t *handle) +{ + return xf_buffer_data(handle->aux); +} + +/* ...acquire component lock */ +static inline void xf_lock(xf_handle_t *handle) +{ + __xf_lock(&handle->lock); +} + +/* ...release component lock */ +static inline void xf_unlock(xf_handle_t *handle) +{ + __xf_unlock(&handle->lock); +} + +/* ...put asynchronous response into local IPC */ +static inline int xf_response_put(xf_handle_t *handle, xf_user_msg_t *msg) +{ + return xf_ipc_response_put(&handle->ipc, msg); +} + +/* ...get asynchronous response from local IPC */ +static inline int xf_response_get(xf_handle_t *handle, xf_user_msg_t *msg) +{ + return xf_ipc_response_get(&handle->ipc, msg); +} diff --git a/hifi/xaf/host-apf/include/xf.h b/hifi/xaf/host-apf/include/xf.h new file mode 100644 index 00000000..6af69ce6 --- /dev/null +++ b/hifi/xaf/host-apf/include/xf.h @@ -0,0 +1,53 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#ifdef __XF_H +#error "xf.h included more than once" +#endif + +#define __XF_H + +/******************************************************************************* + * Common runtime framework + ******************************************************************************/ + +/* ...target configuration */ +#include "xf-config.h" + +/* ...platform run-time */ +#include "xf-runtime.h" + +/* ...debugging facility */ +#include "xf-debug.h" + +/* ...API prototypes */ +#include "xf-proto.h" + +/* ...standard opcodes */ +#include "xf-opcode.h" + +/* ...platform-specific IPC layer */ +#include "xf-ipc.h" + +/* ...proxy definitions */ +#include "xf-proxy.h" + diff --git a/hifi/xaf/host-apf/playback/tinyalsa/asoundlib.h b/hifi/xaf/host-apf/playback/tinyalsa/asoundlib.h new file mode 100644 index 00000000..753a996b --- /dev/null +++ b/hifi/xaf/host-apf/playback/tinyalsa/asoundlib.h @@ -0,0 +1,314 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#ifndef ASOUNDLIB_H +#define ASOUNDLIB_H + +#include <sys/time.h> +#include <stddef.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * PCM API + */ + +struct pcm; + +#define PCM_OUT 0x00000000 +#define PCM_IN 0x10000000 +#define PCM_MMAP 0x00000001 +#define PCM_NOIRQ 0x00000002 +#define PCM_NORESTART 0x00000004 /* PCM_NORESTART - when set, calls to + * pcm_write for a playback stream will not + * attempt to restart the stream in the case + * of an underflow, but will return -EPIPE + * instead. After the first -EPIPE error, the + * stream is considered to be stopped, and a + * second call to pcm_write will attempt to + * restart the stream. + */ +#define PCM_MONOTONIC 0x00000008 /* see pcm_get_htimestamp */ + +/* PCM runtime states */ +#define PCM_STATE_OPEN 0 +#define PCM_STATE_SETUP 1 +#define PCM_STATE_PREPARED 2 +#define PCM_STATE_RUNNING 3 +#define PCM_STATE_XRUN 4 +#define PCM_STATE_DRAINING 5 +#define PCM_STATE_PAUSED 6 +#define PCM_STATE_SUSPENDED 7 +#define PCM_STATE_DISCONNECTED 8 + +/* TLV header size*/ +#define TLV_HEADER_SIZE (2 * sizeof(unsigned int)) + +/* Bit formats */ +enum pcm_format { + PCM_FORMAT_INVALID = -1, + PCM_FORMAT_S16_LE = 0, /* 16-bit signed */ + PCM_FORMAT_S32_LE, /* 32-bit signed */ + PCM_FORMAT_S8, /* 8-bit signed */ + PCM_FORMAT_S24_LE, /* 24-bits in 4-bytes */ + PCM_FORMAT_S24_3LE, /* 24-bits in 3-bytes */ + + PCM_FORMAT_MAX, +}; + +/* Bitmask has 256 bits (32 bytes) in asound.h */ +struct pcm_mask { + unsigned int bits[32 / sizeof(unsigned int)]; +}; + +/* Configuration for a stream */ +struct pcm_config { + unsigned int channels; + unsigned int rate; + unsigned int period_size; + unsigned int period_count; + enum pcm_format format; + + /* Values to use for the ALSA start, stop and silence thresholds, and + * silence size. Setting any one of these values to 0 will cause the + * default tinyalsa values to be used instead. + * Tinyalsa defaults are as follows. + * + * start_threshold : period_count * period_size + * stop_threshold : period_count * period_size + * silence_threshold : 0 + * silence_size : 0 + */ + unsigned int start_threshold; + unsigned int stop_threshold; + unsigned int silence_threshold; + unsigned int silence_size; + + /* Minimum number of frames available before pcm_mmap_write() will actually + * write into the kernel buffer. Only used if the stream is opened in mmap mode + * (pcm_open() called with PCM_MMAP flag set). Use 0 for default. + */ + int avail_min; +}; + +/* PCM parameters */ +enum pcm_param +{ + /* mask parameters */ + PCM_PARAM_ACCESS, + PCM_PARAM_FORMAT, + PCM_PARAM_SUBFORMAT, + /* interval parameters */ + PCM_PARAM_SAMPLE_BITS, + PCM_PARAM_FRAME_BITS, + PCM_PARAM_CHANNELS, + PCM_PARAM_RATE, + PCM_PARAM_PERIOD_TIME, + PCM_PARAM_PERIOD_SIZE, + PCM_PARAM_PERIOD_BYTES, + PCM_PARAM_PERIODS, + PCM_PARAM_BUFFER_TIME, + PCM_PARAM_BUFFER_SIZE, + PCM_PARAM_BUFFER_BYTES, + PCM_PARAM_TICK_TIME, +}; + +/* Mixer control types */ +enum mixer_ctl_type { + MIXER_CTL_TYPE_BOOL, + MIXER_CTL_TYPE_INT, + MIXER_CTL_TYPE_ENUM, + MIXER_CTL_TYPE_BYTE, + MIXER_CTL_TYPE_IEC958, + MIXER_CTL_TYPE_INT64, + MIXER_CTL_TYPE_UNKNOWN, + + MIXER_CTL_TYPE_MAX, +}; + +/* Open and close a stream */ +struct pcm *pcm_open(unsigned int card, unsigned int device, + unsigned int flags, struct pcm_config *config); +int pcm_close(struct pcm *pcm); +int pcm_is_ready(struct pcm *pcm); + +/* Obtain the parameters for a PCM */ +struct pcm_params *pcm_params_get(unsigned int card, unsigned int device, + unsigned int flags); +void pcm_params_free(struct pcm_params *pcm_params); + +struct pcm_mask *pcm_params_get_mask(struct pcm_params *pcm_params, + enum pcm_param param); +unsigned int pcm_params_get_min(struct pcm_params *pcm_params, + enum pcm_param param); +void pcm_params_set_min(struct pcm_params *pcm_params, + enum pcm_param param, unsigned int val); +unsigned int pcm_params_get_max(struct pcm_params *pcm_params, + enum pcm_param param); +void pcm_params_set_max(struct pcm_params *pcm_params, + enum pcm_param param, unsigned int val); + +/* Converts the pcm parameters to a human readable string. + * The string parameter is a caller allocated buffer of size bytes, + * which is then filled up to size - 1 and null terminated, + * if size is greater than zero. + * The return value is the number of bytes copied to string + * (not including null termination) if less than size; otherwise, + * the number of bytes required for the buffer. + */ +int pcm_params_to_string(struct pcm_params *params, char *string, unsigned int size); + +/* Returns 1 if the pcm_format is present (format bit set) in + * the pcm_params structure; 0 otherwise, or upon unrecognized format. + */ +int pcm_params_format_test(struct pcm_params *params, enum pcm_format format); + +/* Set and get config */ +int pcm_get_config(struct pcm *pcm, struct pcm_config *config); +int pcm_set_config(struct pcm *pcm, struct pcm_config *config); + +/* Returns a human readable reason for the last error */ +const char *pcm_get_error(struct pcm *pcm); + +/* Returns the sample size in bits for a PCM format. + * As with ALSA formats, this is the storage size for the format, whereas the + * format represents the number of significant bits. For example, + * PCM_FORMAT_S24_LE uses 32 bits of storage. + */ +unsigned int pcm_format_to_bits(enum pcm_format format); + +/* Returns the buffer size (int frames) that should be used for pcm_write. */ +unsigned int pcm_get_buffer_size(struct pcm *pcm); +unsigned int pcm_frames_to_bytes(struct pcm *pcm, unsigned int frames); +unsigned int pcm_bytes_to_frames(struct pcm *pcm, unsigned int bytes); + +/* Returns the pcm latency in ms */ +unsigned int pcm_get_latency(struct pcm *pcm); + +/* Returns available frames in pcm buffer and corresponding time stamp. + * The clock is CLOCK_MONOTONIC if flag PCM_MONOTONIC was specified in pcm_open, + * otherwise the clock is CLOCK_REALTIME. + * For an input stream, frames available are frames ready for the + * application to read. + * For an output stream, frames available are the number of empty frames available + * for the application to write. + */ +int pcm_get_htimestamp(struct pcm *pcm, unsigned int *avail, + struct timespec *tstamp); + +/* Returns the subdevice on which the pcm has been opened */ +unsigned int pcm_get_subdevice(struct pcm *pcm); + +/* Write data to the fifo. + * Will start playback on the first write or on a write that + * occurs after a fifo underrun. + */ +int pcm_write(struct pcm *pcm, const void *data, unsigned int count); +int pcm_read(struct pcm *pcm, void *data, unsigned int count); + +/* + * mmap() support. + */ +int pcm_mmap_write(struct pcm *pcm, const void *data, unsigned int count); +int pcm_mmap_read(struct pcm *pcm, void *data, unsigned int count); +int pcm_mmap_begin(struct pcm *pcm, void **areas, unsigned int *offset, + unsigned int *frames); +int pcm_mmap_commit(struct pcm *pcm, unsigned int offset, unsigned int frames); +int pcm_mmap_avail(struct pcm *pcm); + +/* Prepare the PCM substream to be triggerable */ +int pcm_prepare(struct pcm *pcm); +/* Start and stop a PCM channel that doesn't transfer data */ +int pcm_start(struct pcm *pcm); +int pcm_stop(struct pcm *pcm); + +/* ioctl function for PCM driver */ +int pcm_ioctl(struct pcm *pcm, int request, ...); + +/* Interrupt driven API */ +int pcm_wait(struct pcm *pcm, int timeout); +int pcm_get_poll_fd(struct pcm *pcm); + +/* Change avail_min after the stream has been opened with no need to stop the stream. + * Only accepted if opened with PCM_MMAP and PCM_NOIRQ flags + */ +int pcm_set_avail_min(struct pcm *pcm, int avail_min); + +/* + * MIXER API + */ + +struct mixer; +struct mixer_ctl; + +/* Open and close a mixer */ +struct mixer *mixer_open(unsigned int card); +void mixer_close(struct mixer *mixer); + +/* Get info about a mixer */ +const char *mixer_get_name(struct mixer *mixer); + +/* Obtain mixer controls */ +unsigned int mixer_get_num_ctls(struct mixer *mixer); +struct mixer_ctl *mixer_get_ctl(struct mixer *mixer, unsigned int id); +struct mixer_ctl *mixer_get_ctl_by_name(struct mixer *mixer, const char *name); + +/* Get info about mixer controls */ +const char *mixer_ctl_get_name(struct mixer_ctl *ctl); +enum mixer_ctl_type mixer_ctl_get_type(struct mixer_ctl *ctl); +const char *mixer_ctl_get_type_string(struct mixer_ctl *ctl); +unsigned int mixer_ctl_get_num_values(struct mixer_ctl *ctl); +unsigned int mixer_ctl_get_num_enums(struct mixer_ctl *ctl); +const char *mixer_ctl_get_enum_string(struct mixer_ctl *ctl, + unsigned int enum_id); + +/* Some sound cards update their controls due to external events, + * such as HDMI EDID byte data changing when an HDMI cable is + * connected. This API allows the count of elements to be updated. + */ +void mixer_ctl_update(struct mixer_ctl *ctl); + +/* Set and get mixer controls */ +int mixer_ctl_get_percent(struct mixer_ctl *ctl, unsigned int id); +int mixer_ctl_set_percent(struct mixer_ctl *ctl, unsigned int id, int percent); + +int mixer_ctl_get_value(struct mixer_ctl *ctl, unsigned int id); +int mixer_ctl_is_access_tlv_rw(struct mixer_ctl *ctl); +int mixer_ctl_get_array(struct mixer_ctl *ctl, void *array, size_t count); +int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value); +int mixer_ctl_set_array(struct mixer_ctl *ctl, const void *array, size_t count); +int mixer_ctl_set_enum_by_string(struct mixer_ctl *ctl, const char *string); + +/* Determe range of integer mixer controls */ +int mixer_ctl_get_range_min(struct mixer_ctl *ctl); +int mixer_ctl_get_range_max(struct mixer_ctl *ctl); + +int mixer_subscribe_events(struct mixer *mixer, int subscribe); +int mixer_wait_event(struct mixer *mixer, int timeout); + +#if defined(__cplusplus) +} /* extern "C" */ +#endif + +#endif diff --git a/hifi/xaf/host-apf/playback/tinyalsa/pcm.c b/hifi/xaf/host-apf/playback/tinyalsa/pcm.c new file mode 100644 index 00000000..e0dc7bb7 --- /dev/null +++ b/hifi/xaf/host-apf/playback/tinyalsa/pcm.c @@ -0,0 +1,1311 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <poll.h> + +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/time.h> +#include <limits.h> + +#include <linux/ioctl.h> +#define __force +//#define __bitwise +#define __user +#include <sound/asound.h> + +#include <tinyalsa/asoundlib.h> + +#define PARAM_MAX SNDRV_PCM_HW_PARAM_LAST_INTERVAL + +/* Logs information into a string; follows snprintf() in that + * offset may be greater than size, and though no characters are copied + * into string, characters are still counted into offset. */ +#define STRLOG(string, offset, size, ...) \ + do { int temp, clipoffset = offset > size ? size : offset; \ + temp = snprintf(string + clipoffset, size - clipoffset, __VA_ARGS__); \ + if (temp > 0) offset += temp; } while (0) + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#endif + +/* refer to SNDRV_PCM_ACCESS_##index in sound/asound.h. */ +static const char * const access_lookup[] = { + "MMAP_INTERLEAVED", + "MMAP_NONINTERLEAVED", + "MMAP_COMPLEX", + "RW_INTERLEAVED", + "RW_NONINTERLEAVED", +}; + +/* refer to SNDRV_PCM_FORMAT_##index in sound/asound.h. */ +static const char * const format_lookup[] = { + /*[0] =*/ "S8", + "U8", + "S16_LE", + "S16_BE", + "U16_LE", + "U16_BE", + "S24_LE", + "S24_BE", + "U24_LE", + "U24_BE", + "S32_LE", + "S32_BE", + "U32_LE", + "U32_BE", + "FLOAT_LE", + "FLOAT_BE", + "FLOAT64_LE", + "FLOAT64_BE", + "IEC958_SUBFRAME_LE", + "IEC958_SUBFRAME_BE", + "MU_LAW", + "A_LAW", + "IMA_ADPCM", + "MPEG", + /*[24] =*/ "GSM", + /* gap */ + [31] = "SPECIAL", + "S24_3LE", + "S24_3BE", + "U24_3LE", + "U24_3BE", + "S20_3LE", + "S20_3BE", + "U20_3LE", + "U20_3BE", + "S18_3LE", + "S18_3BE", + "U18_3LE", + /*[43] =*/ "U18_3BE", +#if 0 + /* recent additions, may not be present on local asound.h */ + "G723_24", + "G723_24_1B", + "G723_40", + "G723_40_1B", + "DSD_U8", + "DSD_U16_LE", +#endif +}; + +/* refer to SNDRV_PCM_SUBFORMAT_##index in sound/asound.h. */ +static const char * const subformat_lookup[] = { + "STD", +}; + +static inline int param_is_mask(int p) +{ + return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) && + (p <= SNDRV_PCM_HW_PARAM_LAST_MASK); +} + +static inline int param_is_interval(int p) +{ + return (p >= SNDRV_PCM_HW_PARAM_FIRST_INTERVAL) && + (p <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL); +} + +static inline struct snd_interval *param_to_interval(struct snd_pcm_hw_params *p, int n) +{ + return &(p->intervals[n - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]); +} + +static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n) +{ + return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]); +} + +static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned int bit) +{ + if (bit >= SNDRV_MASK_MAX) + return; + if (param_is_mask(n)) { + struct snd_mask *m = param_to_mask(p, n); + m->bits[0] = 0; + m->bits[1] = 0; + m->bits[bit >> 5] |= (1 << (bit & 31)); + } +} + +static void param_set_min(struct snd_pcm_hw_params *p, int n, unsigned int val) +{ + if (param_is_interval(n)) { + struct snd_interval *i = param_to_interval(p, n); + i->min = val; + } +} + +static unsigned int param_get_min(struct snd_pcm_hw_params *p, int n) +{ + if (param_is_interval(n)) { + struct snd_interval *i = param_to_interval(p, n); + return i->min; + } + return 0; +} + +static void param_set_max(struct snd_pcm_hw_params *p, int n, unsigned int val) +{ + if (param_is_interval(n)) { + struct snd_interval *i = param_to_interval(p, n); + i->max = val; + } +} + +static unsigned int param_get_max(struct snd_pcm_hw_params *p, int n) +{ + if (param_is_interval(n)) { + struct snd_interval *i = param_to_interval(p, n); + return i->max; + } + return 0; +} + +static void param_set_int(struct snd_pcm_hw_params *p, int n, unsigned int val) +{ + if (param_is_interval(n)) { + struct snd_interval *i = param_to_interval(p, n); + i->min = val; + i->max = val; + i->integer = 1; + } +} + +static unsigned int param_get_int(struct snd_pcm_hw_params *p, int n) +{ + if (param_is_interval(n)) { + struct snd_interval *i = param_to_interval(p, n); + if (i->integer) + return i->max; + } + return 0; +} + +static void param_init(struct snd_pcm_hw_params *p) +{ + int n; + + memset(p, 0, sizeof(*p)); + for (n = SNDRV_PCM_HW_PARAM_FIRST_MASK; + n <= SNDRV_PCM_HW_PARAM_LAST_MASK; n++) { + struct snd_mask *m = param_to_mask(p, n); + m->bits[0] = ~0; + m->bits[1] = ~0; + } + for (n = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; + n <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; n++) { + struct snd_interval *i = param_to_interval(p, n); + i->min = 0; + i->max = ~0; + } + p->rmask = ~0U; + p->cmask = 0; + p->info = ~0U; +} + +#define PCM_ERROR_MAX 128 + +struct pcm { + int fd; + unsigned int flags; + int running:1; + int prepared:1; + int underruns; + unsigned int buffer_size; + unsigned int boundary; + char error[PCM_ERROR_MAX]; + struct pcm_config config; + struct snd_pcm_mmap_status *mmap_status; + struct snd_pcm_mmap_control *mmap_control; + struct snd_pcm_sync_ptr *sync_ptr; + void *mmap_buffer; + unsigned int noirq_frames_per_msec; + int wait_for_avail_min; + unsigned int subdevice; +}; + +unsigned int pcm_get_buffer_size(struct pcm *pcm) +{ + return pcm->buffer_size; +} + +const char* pcm_get_error(struct pcm *pcm) +{ + return pcm->error; +} + +unsigned int pcm_get_subdevice(struct pcm *pcm) +{ + return pcm->subdevice; +} + +static int oops(struct pcm *pcm, int e, const char *fmt, ...) +{ + va_list ap; + int sz; + + va_start(ap, fmt); + vsnprintf(pcm->error, PCM_ERROR_MAX, fmt, ap); + va_end(ap); + sz = strlen(pcm->error); + + if (errno) + snprintf(pcm->error + sz, PCM_ERROR_MAX - sz, + ": %s", strerror(e)); + return -1; +} + +static unsigned int pcm_format_to_alsa(enum pcm_format format) +{ + switch (format) { + case PCM_FORMAT_S32_LE: + return SNDRV_PCM_FORMAT_S32_LE; + case PCM_FORMAT_S8: + return SNDRV_PCM_FORMAT_S8; + case PCM_FORMAT_S24_3LE: + return SNDRV_PCM_FORMAT_S24_3LE; + case PCM_FORMAT_S24_LE: + return SNDRV_PCM_FORMAT_S24_LE; + default: + case PCM_FORMAT_S16_LE: + return SNDRV_PCM_FORMAT_S16_LE; + }; +} + +unsigned int pcm_format_to_bits(enum pcm_format format) +{ + switch (format) { + case PCM_FORMAT_S32_LE: + case PCM_FORMAT_S24_LE: + return 32; + case PCM_FORMAT_S24_3LE: + return 24; + default: + case PCM_FORMAT_S16_LE: + return 16; + }; +} + +unsigned int pcm_bytes_to_frames(struct pcm *pcm, unsigned int bytes) +{ + return bytes / (pcm->config.channels * + (pcm_format_to_bits(pcm->config.format) >> 3)); +} + +unsigned int pcm_frames_to_bytes(struct pcm *pcm, unsigned int frames) +{ + return frames * pcm->config.channels * + (pcm_format_to_bits(pcm->config.format) >> 3); +} + +static int pcm_sync_ptr(struct pcm *pcm, int flags) { + if (pcm->sync_ptr) { + pcm->sync_ptr->flags = flags; + if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SYNC_PTR, pcm->sync_ptr) < 0) + return -1; + } + return 0; +} + +static int pcm_hw_mmap_status(struct pcm *pcm) { + + if (pcm->sync_ptr) + return 0; + + int page_size = sysconf(_SC_PAGE_SIZE); + pcm->mmap_status = mmap(NULL, page_size, PROT_READ, MAP_FILE | MAP_SHARED, + pcm->fd, SNDRV_PCM_MMAP_OFFSET_STATUS); + if (pcm->mmap_status == MAP_FAILED) + pcm->mmap_status = NULL; + if (!pcm->mmap_status) + goto mmap_error; + + pcm->mmap_control = mmap(NULL, page_size, PROT_READ | PROT_WRITE, + MAP_FILE | MAP_SHARED, pcm->fd, SNDRV_PCM_MMAP_OFFSET_CONTROL); + if (pcm->mmap_control == MAP_FAILED) + pcm->mmap_control = NULL; + if (!pcm->mmap_control) { + munmap(pcm->mmap_status, page_size); + pcm->mmap_status = NULL; + goto mmap_error; + } + if (pcm->flags & PCM_MMAP) + pcm->mmap_control->avail_min = pcm->config.avail_min; + else + pcm->mmap_control->avail_min = 1; + + return 0; + +mmap_error: + + pcm->sync_ptr = calloc(1, sizeof(*pcm->sync_ptr)); + if (!pcm->sync_ptr) + return -ENOMEM; + pcm->mmap_status = &pcm->sync_ptr->s.status; + pcm->mmap_control = &pcm->sync_ptr->c.control; + if (pcm->flags & PCM_MMAP) + pcm->mmap_control->avail_min = pcm->config.avail_min; + else + pcm->mmap_control->avail_min = 1; + + pcm_sync_ptr(pcm, 0); + + return 0; +} + +static void pcm_hw_munmap_status(struct pcm *pcm) { + if (pcm->sync_ptr) { + free(pcm->sync_ptr); + pcm->sync_ptr = NULL; + } else { + int page_size = sysconf(_SC_PAGE_SIZE); + if (pcm->mmap_status) + munmap(pcm->mmap_status, page_size); + if (pcm->mmap_control) + munmap(pcm->mmap_control, page_size); + } + pcm->mmap_status = NULL; + pcm->mmap_control = NULL; +} + +static int pcm_areas_copy(struct pcm *pcm, unsigned int pcm_offset, + char *buf, unsigned int src_offset, + unsigned int frames) +{ + int size_bytes = pcm_frames_to_bytes(pcm, frames); + int pcm_offset_bytes = pcm_frames_to_bytes(pcm, pcm_offset); + int src_offset_bytes = pcm_frames_to_bytes(pcm, src_offset); + + /* interleaved only atm */ + if (pcm->flags & PCM_IN) + memcpy(buf + src_offset_bytes, + (char*)pcm->mmap_buffer + pcm_offset_bytes, + size_bytes); + else + memcpy((char*)pcm->mmap_buffer + pcm_offset_bytes, + buf + src_offset_bytes, + size_bytes); + return 0; +} + +static int pcm_mmap_transfer_areas(struct pcm *pcm, char *buf, + unsigned int offset, unsigned int size) +{ + void *pcm_areas; + int commit; + unsigned int pcm_offset, frames, count = 0; + + while (size > 0) { + frames = size; + pcm_mmap_begin(pcm, &pcm_areas, &pcm_offset, &frames); + pcm_areas_copy(pcm, pcm_offset, buf, offset, frames); + commit = pcm_mmap_commit(pcm, pcm_offset, frames); + if (commit < 0) { + oops(pcm, commit, "failed to commit %d frames\n", frames); + return commit; + } + + offset += commit; + count += commit; + size -= commit; + } + return count; +} + +int pcm_get_htimestamp(struct pcm *pcm, unsigned int *avail, + struct timespec *tstamp) +{ + int frames; + int rc; + snd_pcm_uframes_t hw_ptr; + + if (!pcm_is_ready(pcm)) + return -1; + + rc = pcm_sync_ptr(pcm, SNDRV_PCM_SYNC_PTR_APPL|SNDRV_PCM_SYNC_PTR_HWSYNC); + if (rc < 0) + return -1; + + if ((pcm->mmap_status->state != PCM_STATE_RUNNING) && + (pcm->mmap_status->state != PCM_STATE_DRAINING)) + return -1; + + *tstamp = pcm->mmap_status->tstamp; + if (tstamp->tv_sec == 0 && tstamp->tv_nsec == 0) + return -1; + + hw_ptr = pcm->mmap_status->hw_ptr; + if (pcm->flags & PCM_IN) + frames = hw_ptr - pcm->mmap_control->appl_ptr; + else + frames = hw_ptr + pcm->buffer_size - pcm->mmap_control->appl_ptr; + + if (frames < 0) + frames += pcm->boundary; + else if (frames > (int)pcm->boundary) + frames -= pcm->boundary; + + *avail = (unsigned int)frames; + + return 0; +} + +int pcm_write(struct pcm *pcm, const void *data, unsigned int count) +{ + struct snd_xferi x; + + if (pcm->flags & PCM_IN) + return -EINVAL; + + x.buf = (void*)data; + x.frames = count / (pcm->config.channels * + pcm_format_to_bits(pcm->config.format) / 8); + + for (;;) { + if (!pcm->running) { + int prepare_error = pcm_prepare(pcm); + if (prepare_error) + return prepare_error; + if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) + return oops(pcm, errno, "cannot write initial data"); + pcm->running = 1; + return 0; + } + if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) { + pcm->prepared = 0; + pcm->running = 0; + if (errno == EPIPE) { + /* we failed to make our window -- try to restart if we are + * allowed to do so. Otherwise, simply allow the EPIPE error to + * propagate up to the app level */ + pcm->underruns++; + if (pcm->flags & PCM_NORESTART) + return -EPIPE; + continue; + } + return oops(pcm, errno, "cannot write stream data"); + } + return 0; + } +} + +int pcm_read(struct pcm *pcm, void *data, unsigned int count) +{ + struct snd_xferi x; + + if (!(pcm->flags & PCM_IN)) + return -EINVAL; + + x.buf = data; + x.frames = count / (pcm->config.channels * + pcm_format_to_bits(pcm->config.format) / 8); + + for (;;) { + if (!pcm->running) { + if (pcm_start(pcm) < 0) { + fprintf(stderr, "start error"); + return -errno; + } + } + if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_READI_FRAMES, &x)) { + pcm->prepared = 0; + pcm->running = 0; + if (errno == EPIPE) { + /* we failed to make our window -- try to restart */ + pcm->underruns++; + continue; + } + return oops(pcm, errno, "cannot read stream data"); + } + return 0; + } +} + +static struct pcm bad_pcm = { + .fd = -1, +}; + +struct pcm_params *pcm_params_get(unsigned int card, unsigned int device, + unsigned int flags) +{ + struct snd_pcm_hw_params *params; + char fn[256]; + int fd; + + snprintf(fn, sizeof(fn), "/dev/snd/pcmC%uD%u%c", card, device, + flags & PCM_IN ? 'c' : 'p'); + + fd = open(fn, O_RDWR); + if (fd < 0) { + fprintf(stderr, "cannot open device '%s'\n", fn); + goto err_open; + } + + params = calloc(1, sizeof(struct snd_pcm_hw_params)); + if (!params) + goto err_calloc; + + param_init(params); + if (ioctl(fd, SNDRV_PCM_IOCTL_HW_REFINE, params)) { + fprintf(stderr, "SNDRV_PCM_IOCTL_HW_REFINE error (%d)\n", errno); + goto err_hw_refine; + } + + close(fd); + + return (struct pcm_params *)params; + +err_hw_refine: + free(params); +err_calloc: + close(fd); +err_open: + return NULL; +} + +void pcm_params_free(struct pcm_params *pcm_params) +{ + struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params; + + if (params) + free(params); +} + +static int pcm_param_to_alsa(enum pcm_param param) +{ + switch (param) { + case PCM_PARAM_ACCESS: + return SNDRV_PCM_HW_PARAM_ACCESS; + case PCM_PARAM_FORMAT: + return SNDRV_PCM_HW_PARAM_FORMAT; + case PCM_PARAM_SUBFORMAT: + return SNDRV_PCM_HW_PARAM_SUBFORMAT; + case PCM_PARAM_SAMPLE_BITS: + return SNDRV_PCM_HW_PARAM_SAMPLE_BITS; + break; + case PCM_PARAM_FRAME_BITS: + return SNDRV_PCM_HW_PARAM_FRAME_BITS; + break; + case PCM_PARAM_CHANNELS: + return SNDRV_PCM_HW_PARAM_CHANNELS; + break; + case PCM_PARAM_RATE: + return SNDRV_PCM_HW_PARAM_RATE; + break; + case PCM_PARAM_PERIOD_TIME: + return SNDRV_PCM_HW_PARAM_PERIOD_TIME; + break; + case PCM_PARAM_PERIOD_SIZE: + return SNDRV_PCM_HW_PARAM_PERIOD_SIZE; + break; + case PCM_PARAM_PERIOD_BYTES: + return SNDRV_PCM_HW_PARAM_PERIOD_BYTES; + break; + case PCM_PARAM_PERIODS: + return SNDRV_PCM_HW_PARAM_PERIODS; + break; + case PCM_PARAM_BUFFER_TIME: + return SNDRV_PCM_HW_PARAM_BUFFER_TIME; + break; + case PCM_PARAM_BUFFER_SIZE: + return SNDRV_PCM_HW_PARAM_BUFFER_SIZE; + break; + case PCM_PARAM_BUFFER_BYTES: + return SNDRV_PCM_HW_PARAM_BUFFER_BYTES; + break; + case PCM_PARAM_TICK_TIME: + return SNDRV_PCM_HW_PARAM_TICK_TIME; + break; + + default: + return -1; + } +} + +struct pcm_mask *pcm_params_get_mask(struct pcm_params *pcm_params, + enum pcm_param param) +{ + int p; + struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params; + if (params == NULL) { + return NULL; + } + + p = pcm_param_to_alsa(param); + if (p < 0 || !param_is_mask(p)) { + return NULL; + } + + return (struct pcm_mask *)param_to_mask(params, p); +} + +unsigned int pcm_params_get_min(struct pcm_params *pcm_params, + enum pcm_param param) +{ + struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params; + int p; + + if (!params) + return 0; + + p = pcm_param_to_alsa(param); + if (p < 0) + return 0; + + return param_get_min(params, p); +} + +void pcm_params_set_min(struct pcm_params *pcm_params, + enum pcm_param param, unsigned int val) +{ + struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params; + int p; + + if (!params) + return; + + p = pcm_param_to_alsa(param); + if (p < 0) + return; + + param_set_min(params, p, val); +} + +unsigned int pcm_params_get_max(struct pcm_params *pcm_params, + enum pcm_param param) +{ + struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params; + int p; + + if (!params) + return 0; + + p = pcm_param_to_alsa(param); + if (p < 0) + return 0; + + return param_get_max(params, p); +} + +void pcm_params_set_max(struct pcm_params *pcm_params, + enum pcm_param param, unsigned int val) +{ + struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params; + int p; + + if (!params) + return; + + p = pcm_param_to_alsa(param); + if (p < 0) + return; + + param_set_max(params, p, val); +} + +static int pcm_mask_test(struct pcm_mask *m, unsigned int index) +{ + const unsigned int bitshift = 5; /* for 32 bit integer */ + const unsigned int bitmask = (1 << bitshift) - 1; + unsigned int element; + + element = index >> bitshift; + if (element >= ARRAY_SIZE(m->bits)) + return 0; /* for safety, but should never occur */ + return (m->bits[element] >> (index & bitmask)) & 1; +} + +static int pcm_mask_to_string(struct pcm_mask *m, char *string, unsigned int size, + char *mask_name, + const char * const *bit_array_name, size_t bit_array_size) +{ + unsigned int i; + unsigned int offset = 0; + + if (m == NULL) + return 0; + if (bit_array_size < 32) { + STRLOG(string, offset, size, "%12s:\t%#08x\n", mask_name, m->bits[0]); + } else { /* spans two or more bitfields, print with an array index */ + for (i = 0; i < (bit_array_size + 31) >> 5; ++i) { + STRLOG(string, offset, size, "%9s[%d]:\t%#08x\n", + mask_name, i, m->bits[i]); + } + } + for (i = 0; i < bit_array_size; ++i) { + if (pcm_mask_test(m, i)) { + STRLOG(string, offset, size, "%12s \t%s\n", "", bit_array_name[i]); + } + } + return offset; +} + +int pcm_params_to_string(struct pcm_params *params, char *string, unsigned int size) +{ + struct pcm_mask *m; + unsigned int min, max; + unsigned int clipoffset, offset; + + m = pcm_params_get_mask(params, PCM_PARAM_ACCESS); + offset = pcm_mask_to_string(m, string, size, + "Access", access_lookup, ARRAY_SIZE(access_lookup)); + m = pcm_params_get_mask(params, PCM_PARAM_FORMAT); + clipoffset = offset > size ? size : offset; + offset += pcm_mask_to_string(m, string + clipoffset, size - clipoffset, + "Format", format_lookup, ARRAY_SIZE(format_lookup)); + m = pcm_params_get_mask(params, PCM_PARAM_SUBFORMAT); + clipoffset = offset > size ? size : offset; + offset += pcm_mask_to_string(m, string + clipoffset, size - clipoffset, + "Subformat", subformat_lookup, ARRAY_SIZE(subformat_lookup)); + min = pcm_params_get_min(params, PCM_PARAM_RATE); + max = pcm_params_get_max(params, PCM_PARAM_RATE); + STRLOG(string, offset, size, " Rate:\tmin=%uHz\tmax=%uHz\n", min, max); + min = pcm_params_get_min(params, PCM_PARAM_CHANNELS); + max = pcm_params_get_max(params, PCM_PARAM_CHANNELS); + STRLOG(string, offset, size, " Channels:\tmin=%u\t\tmax=%u\n", min, max); + min = pcm_params_get_min(params, PCM_PARAM_SAMPLE_BITS); + max = pcm_params_get_max(params, PCM_PARAM_SAMPLE_BITS); + STRLOG(string, offset, size, " Sample bits:\tmin=%u\t\tmax=%u\n", min, max); + min = pcm_params_get_min(params, PCM_PARAM_PERIOD_SIZE); + max = pcm_params_get_max(params, PCM_PARAM_PERIOD_SIZE); + STRLOG(string, offset, size, " Period size:\tmin=%u\t\tmax=%u\n", min, max); + min = pcm_params_get_min(params, PCM_PARAM_PERIODS); + max = pcm_params_get_max(params, PCM_PARAM_PERIODS); + STRLOG(string, offset, size, "Period count:\tmin=%u\t\tmax=%u\n", min, max); + return offset; +} + +int pcm_params_format_test(struct pcm_params *params, enum pcm_format format) +{ + unsigned int alsa_format = pcm_format_to_alsa(format); + + if (alsa_format == SNDRV_PCM_FORMAT_S16_LE && format != PCM_FORMAT_S16_LE) + return 0; /* caution: format not recognized is equivalent to S16_LE */ + return pcm_mask_test(pcm_params_get_mask(params, PCM_PARAM_FORMAT), alsa_format); +} + +int pcm_close(struct pcm *pcm) +{ + if (pcm == &bad_pcm) + return 0; + + pcm_hw_munmap_status(pcm); + + if (pcm->flags & PCM_MMAP) { + pcm_stop(pcm); + munmap(pcm->mmap_buffer, pcm_frames_to_bytes(pcm, pcm->buffer_size)); + } + + if (pcm->fd >= 0) + close(pcm->fd); + pcm->prepared = 0; + pcm->running = 0; + pcm->buffer_size = 0; + pcm->fd = -1; + free(pcm); + return 0; +} + +struct pcm *pcm_open(unsigned int card, unsigned int device, + unsigned int flags, struct pcm_config *config) +{ + struct pcm *pcm; + struct snd_pcm_info info; + struct snd_pcm_hw_params params; + struct snd_pcm_sw_params sparams; + char fn[256]; + int rc; + + pcm = calloc(1, sizeof(struct pcm)); + if (!pcm || !config) + return &bad_pcm; /* TODO: could support default config here */ + + pcm->config = *config; + + snprintf(fn, sizeof(fn), "/dev/snd/pcmC%uD%u%c", card, device, + flags & PCM_IN ? 'c' : 'p'); + + pcm->flags = flags; + pcm->fd = open(fn, O_RDWR|O_NONBLOCK); + if (pcm->fd < 0) { + oops(pcm, errno, "cannot open device '%s'", fn); + return pcm; + } + + if (fcntl(pcm->fd, F_SETFL, fcntl(pcm->fd, F_GETFL) & + ~O_NONBLOCK) < 0) { + oops(pcm, errno, "failed to reset blocking mode '%s'", fn); + goto fail_close; + } + + if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_INFO, &info)) { + oops(pcm, errno, "cannot get info"); + goto fail_close; + } + pcm->subdevice = info.subdevice; + + param_init(¶ms); + param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_FORMAT, + pcm_format_to_alsa(config->format)); + param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_SUBFORMAT, + SNDRV_PCM_SUBFORMAT_STD); + param_set_min(¶ms, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, config->period_size); + param_set_int(¶ms, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, + pcm_format_to_bits(config->format)); + param_set_int(¶ms, SNDRV_PCM_HW_PARAM_FRAME_BITS, + pcm_format_to_bits(config->format) * config->channels); + param_set_int(¶ms, SNDRV_PCM_HW_PARAM_CHANNELS, + config->channels); + param_set_int(¶ms, SNDRV_PCM_HW_PARAM_PERIODS, config->period_count); + param_set_int(¶ms, SNDRV_PCM_HW_PARAM_RATE, config->rate); + + if (flags & PCM_NOIRQ) { + if (!(flags & PCM_MMAP)) { + oops(pcm, -EINVAL, "noirq only currently supported with mmap()."); + goto fail_close; + } + + params.flags |= SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP; + pcm->noirq_frames_per_msec = config->rate / 1000; + } + + if (flags & PCM_MMAP) + param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_ACCESS, + SNDRV_PCM_ACCESS_MMAP_INTERLEAVED); + else + param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_ACCESS, + SNDRV_PCM_ACCESS_RW_INTERLEAVED); + + if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_PARAMS, ¶ms)) { + oops(pcm, errno, "cannot set hw params"); + goto fail_close; + } + + /* get our refined hw_params */ + config->period_size = param_get_int(¶ms, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); + config->period_count = param_get_int(¶ms, SNDRV_PCM_HW_PARAM_PERIODS); + pcm->buffer_size = config->period_count * config->period_size; + + if (flags & PCM_MMAP) { + pcm->mmap_buffer = mmap(NULL, pcm_frames_to_bytes(pcm, pcm->buffer_size), + PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, pcm->fd, 0); + if (pcm->mmap_buffer == MAP_FAILED) { + oops(pcm, -errno, "failed to mmap buffer %d bytes\n", + pcm_frames_to_bytes(pcm, pcm->buffer_size)); + goto fail_close; + } + } + + memset(&sparams, 0, sizeof(sparams)); + sparams.tstamp_mode = SNDRV_PCM_TSTAMP_ENABLE; + sparams.period_step = 1; + + if (!config->start_threshold) { + if (pcm->flags & PCM_IN) + pcm->config.start_threshold = sparams.start_threshold = 1; + else + pcm->config.start_threshold = sparams.start_threshold = + config->period_count * config->period_size / 2; + } else + sparams.start_threshold = config->start_threshold; + + /* pick a high stop threshold - todo: does this need further tuning */ + if (!config->stop_threshold) { + if (pcm->flags & PCM_IN) + pcm->config.stop_threshold = sparams.stop_threshold = + config->period_count * config->period_size * 10; + else + pcm->config.stop_threshold = sparams.stop_threshold = + config->period_count * config->period_size; + } + else + sparams.stop_threshold = config->stop_threshold; + + if (!pcm->config.avail_min) { + if (pcm->flags & PCM_MMAP) + pcm->config.avail_min = sparams.avail_min = pcm->config.period_size; + else + pcm->config.avail_min = sparams.avail_min = 1; + } else + sparams.avail_min = config->avail_min; + + sparams.xfer_align = config->period_size / 2; /* needed for old kernels */ + sparams.silence_threshold = config->silence_threshold; + sparams.silence_size = config->silence_size; + pcm->boundary = sparams.boundary = pcm->buffer_size; + + while (pcm->boundary * 2 <= INT_MAX - pcm->buffer_size) + pcm->boundary *= 2; + + if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sparams)) { + oops(pcm, errno, "cannot set sw params"); + goto fail; + } + + rc = pcm_hw_mmap_status(pcm); + if (rc < 0) { + oops(pcm, rc, "mmap status failed"); + goto fail; + } + +#ifdef SNDRV_PCM_IOCTL_TTSTAMP + if (pcm->flags & PCM_MONOTONIC) { + int arg = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC; + rc = ioctl(pcm->fd, SNDRV_PCM_IOCTL_TTSTAMP, &arg); + if (rc < 0) { + oops(pcm, rc, "cannot set timestamp type"); + goto fail; + } + } +#endif + + pcm->underruns = 0; + return pcm; + +fail: + if (flags & PCM_MMAP) + munmap(pcm->mmap_buffer, pcm_frames_to_bytes(pcm, pcm->buffer_size)); +fail_close: + close(pcm->fd); + pcm->fd = -1; + return pcm; +} + +int pcm_is_ready(struct pcm *pcm) +{ + return pcm->fd >= 0; +} + +int pcm_prepare(struct pcm *pcm) +{ + if (pcm->prepared) + return 0; + + if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE) < 0) + return oops(pcm, errno, "cannot prepare channel"); + + pcm->prepared = 1; + return 0; +} + +int pcm_start(struct pcm *pcm) +{ + int prepare_error = pcm_prepare(pcm); + if (prepare_error) + return prepare_error; + + if (pcm->flags & PCM_MMAP) + pcm_sync_ptr(pcm, 0); + + if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START) < 0) + return oops(pcm, errno, "cannot start channel"); + + pcm->running = 1; + return 0; +} + +int pcm_stop(struct pcm *pcm) +{ + if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_DROP) < 0) + return oops(pcm, errno, "cannot stop channel"); + + pcm->prepared = 0; + pcm->running = 0; + return 0; +} + +static inline int pcm_mmap_playback_avail(struct pcm *pcm) +{ + int avail; + + avail = pcm->mmap_status->hw_ptr + pcm->buffer_size - pcm->mmap_control->appl_ptr; + + if (avail < 0) + avail += pcm->boundary; + else if (avail > (int)pcm->boundary) + avail -= pcm->boundary; + + return avail; +} + +static inline int pcm_mmap_capture_avail(struct pcm *pcm) +{ + int avail = pcm->mmap_status->hw_ptr - pcm->mmap_control->appl_ptr; + if (avail < 0) + avail += pcm->boundary; + return avail; +} + +int pcm_mmap_avail(struct pcm *pcm) +{ + pcm_sync_ptr(pcm, SNDRV_PCM_SYNC_PTR_HWSYNC); + if (pcm->flags & PCM_IN) + return pcm_mmap_capture_avail(pcm); + else + return pcm_mmap_playback_avail(pcm); +} + +static void pcm_mmap_appl_forward(struct pcm *pcm, int frames) +{ + unsigned int appl_ptr = pcm->mmap_control->appl_ptr; + appl_ptr += frames; + + /* check for boundary wrap */ + if (appl_ptr > pcm->boundary) + appl_ptr -= pcm->boundary; + pcm->mmap_control->appl_ptr = appl_ptr; +} + +int pcm_mmap_begin(struct pcm *pcm, void **areas, unsigned int *offset, + unsigned int *frames) +{ + unsigned int continuous, copy_frames, avail; + + /* return the mmap buffer */ + *areas = pcm->mmap_buffer; + + /* and the application offset in frames */ + *offset = pcm->mmap_control->appl_ptr % pcm->buffer_size; + + avail = pcm_mmap_avail(pcm); + if (avail > pcm->buffer_size) + avail = pcm->buffer_size; + continuous = pcm->buffer_size - *offset; + + /* we can only copy frames if the are availabale and continuos */ + copy_frames = *frames; + if (copy_frames > avail) + copy_frames = avail; + if (copy_frames > continuous) + copy_frames = continuous; + *frames = copy_frames; + + return 0; +} + +int pcm_mmap_commit(struct pcm *pcm, unsigned int offset __attribute__((unused)), unsigned int frames) +{ + /* update the application pointer in userspace and kernel */ + pcm_mmap_appl_forward(pcm, frames); + pcm_sync_ptr(pcm, 0); + + return frames; +} + +int pcm_avail_update(struct pcm *pcm) +{ + pcm_sync_ptr(pcm, 0); + return pcm_mmap_avail(pcm); +} + +int pcm_state(struct pcm *pcm) +{ + int err = pcm_sync_ptr(pcm, 0); + if (err < 0) + return err; + + return pcm->mmap_status->state; +} + +int pcm_set_avail_min(struct pcm *pcm, int avail_min) +{ + if ((~pcm->flags) & (PCM_MMAP | PCM_NOIRQ)) + return -ENOSYS; + + pcm->config.avail_min = avail_min; + return 0; +} + +int pcm_wait(struct pcm *pcm, int timeout) +{ + struct pollfd pfd; + int err; + + pfd.fd = pcm->fd; + pfd.events = POLLOUT | POLLERR | POLLNVAL; + + do { + /* let's wait for avail or timeout */ + err = poll(&pfd, 1, timeout); + if (err < 0) + return -errno; + + /* timeout ? */ + if (err == 0) + return 0; + + /* have we been interrupted ? */ + if (errno == -EINTR) + continue; + + /* check for any errors */ + if (pfd.revents & (POLLERR | POLLNVAL)) { + switch (pcm_state(pcm)) { + case PCM_STATE_XRUN: + return -EPIPE; + case PCM_STATE_SUSPENDED: + return -ESTRPIPE; + case PCM_STATE_DISCONNECTED: + return -ENODEV; + default: + return -EIO; + } + } + /* poll again if fd not ready for IO */ + } while (!(pfd.revents & (POLLIN | POLLOUT))); + + return 1; +} + +int pcm_get_poll_fd(struct pcm *pcm) +{ + return pcm->fd; +} + +int pcm_mmap_transfer(struct pcm *pcm, const void *buffer, unsigned int bytes) +{ + int err = 0, frames, avail; + unsigned int offset = 0, count; + + if (bytes == 0) + return 0; + + count = pcm_bytes_to_frames(pcm, bytes); + + while (count > 0) { + + /* get the available space for writing new frames */ + avail = pcm_avail_update(pcm); + if (avail < 0) { + fprintf(stderr, "cannot determine available mmap frames"); + return err; + } + + /* start the audio if we reach the threshold */ + if (!pcm->running && + (pcm->buffer_size - avail) >= pcm->config.start_threshold) { + if (pcm_start(pcm) < 0) { + fprintf(stderr, "start error: hw 0x%x app 0x%x avail 0x%x\n", + (unsigned int)pcm->mmap_status->hw_ptr, + (unsigned int)pcm->mmap_control->appl_ptr, + avail); + return -errno; + } + pcm->wait_for_avail_min = 0; + } + + /* sleep until we have space to write new frames */ + if (pcm->running) { + /* enable waiting for avail_min threshold when less frames than we have to write + * are available. */ + if (!pcm->wait_for_avail_min && (count > (unsigned int)avail)) + pcm->wait_for_avail_min = 1; + + if (pcm->wait_for_avail_min && (avail < pcm->config.avail_min)) { + int time = -1; + + /* disable waiting for avail_min threshold to allow small amounts of data to be + * written without waiting as long as there is enough room in buffer. */ + pcm->wait_for_avail_min = 0; + + if (pcm->flags & PCM_NOIRQ) + time = (pcm->config.avail_min - avail) / pcm->noirq_frames_per_msec; + + err = pcm_wait(pcm, time); + if (err < 0) { + pcm->prepared = 0; + pcm->running = 0; + oops(pcm, err, "wait error: hw 0x%x app 0x%x avail 0x%x\n", + (unsigned int)pcm->mmap_status->hw_ptr, + (unsigned int)pcm->mmap_control->appl_ptr, + avail); + pcm->mmap_control->appl_ptr = 0; + return err; + } + continue; + } + } + + frames = count; + if (frames > avail) + frames = avail; + + if (!frames) + break; + + /* copy frames from buffer */ + frames = pcm_mmap_transfer_areas(pcm, (void *)buffer, offset, frames); + if (frames < 0) { + fprintf(stderr, "write error: hw 0x%x app 0x%x avail 0x%x\n", + (unsigned int)pcm->mmap_status->hw_ptr, + (unsigned int)pcm->mmap_control->appl_ptr, + avail); + return frames; + } + + offset += frames; + count -= frames; + } + + return 0; +} + +int pcm_mmap_write(struct pcm *pcm, const void *data, unsigned int count) +{ + if ((~pcm->flags) & (PCM_OUT | PCM_MMAP)) + return -ENOSYS; + + return pcm_mmap_transfer(pcm, (void *)data, count); +} + +int pcm_mmap_read(struct pcm *pcm, void *data, unsigned int count) +{ + if ((~pcm->flags) & (PCM_IN | PCM_MMAP)) + return -ENOSYS; + + return pcm_mmap_transfer(pcm, data, count); +} + +int pcm_ioctl(struct pcm *pcm, int request, ...) +{ + va_list ap; + void * arg; + + if (!pcm_is_ready(pcm)) + return -1; + + va_start(ap, request); + arg = va_arg(ap, void *); + va_end(ap); + + return ioctl(pcm->fd, request, arg); +} diff --git a/hifi/xaf/host-apf/playback/xa_playback.c b/hifi/xaf/host-apf/playback/xa_playback.c new file mode 100644 index 00000000..2a8eefdf --- /dev/null +++ b/hifi/xaf/host-apf/playback/xa_playback.c @@ -0,0 +1,366 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#define MODULE_TAG PLYBK + +#include <tinyalsa/asoundlib.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <signal.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> + +#include "xf.h" +#include "xa_playback.h" + +#if 0 +#define ID_RIFF 0x46464952 +#define ID_WAVE 0x45564157 +#define ID_FMT 0x20746d66 +#define ID_DATA 0x61746164 + +#define HIFI_MISC_IOCTL_PCM_GAIN _IOW('A', 0x7b, struct misc_io_pcm_buf_param) +#define HIFI_DSP_MISC_DRIVER "/dev/hifi_misc" +struct misc_io_pcm_buf_param { + uint64_t buf; + uint32_t buf_size; +}; + +struct riff_wave_header { + uint32_t riff_id; + uint32_t riff_sz; + uint32_t wave_id; +}; + +struct chunk_header { + uint32_t id; + uint32_t sz; +}; + +struct chunk_fmt { + uint16_t audio_format; + uint16_t num_channels; + uint32_t sample_rate; + uint32_t byte_rate; + uint16_t block_align; + uint16_t bits_per_sample; +}; + +static int s_close = 0; + +void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned int channels, + unsigned int rate, unsigned int bits, unsigned int period_size, + unsigned int period_count); + +void stream_close(int sig) +{ + /* allow the stream to be closed gracefully */ + signal(sig, SIG_IGN); + s_close = 1; +} +#endif + +#if 0 +int main(int argc, char **argv) +{ + FILE *file; + struct riff_wave_header riff_wave_header; + struct chunk_header chunk_header; + struct chunk_fmt chunk_fmt; + unsigned int device = 0; + unsigned int card = 0; + unsigned int period_size = 1024; + unsigned int period_count = 4; + char *filename; + int more_chunks = 1; + + if (argc < 2) { + fprintf(stderr, "Usage: %s file.wav [-D card] [-d device] [-p period_size]" + " [-n n_periods] \n", argv[0]); + return 1; + } + + filename = argv[1]; + file = fopen(filename, "rb"); + if (!file) { + fprintf(stderr, "Unable to open file '%s'\n", filename); + return 1; + } + + fread(&riff_wave_header, sizeof(riff_wave_header), 1, file); + if ((riff_wave_header.riff_id != ID_RIFF) || + (riff_wave_header.wave_id != ID_WAVE)) { + fprintf(stderr, "Error: '%s' is not a riff/wave file\n", filename); + fclose(file); + return 1; + } + + do { + fread(&chunk_header, sizeof(chunk_header), 1, file); + + switch (chunk_header.id) { + case ID_FMT: + fread(&chunk_fmt, sizeof(chunk_fmt), 1, file); + /* If the format header is larger, skip the rest */ + if (chunk_header.sz > sizeof(chunk_fmt)) + fseek(file, chunk_header.sz - sizeof(chunk_fmt), SEEK_CUR); + break; + case ID_DATA: + /* Stop looking for chunks */ + more_chunks = 0; + break; + default: + /* Unknown chunk, skip bytes */ + fseek(file, chunk_header.sz, SEEK_CUR); + } + } while (more_chunks); + + /* parse command line arguments */ + argv += 2; + while (*argv) { + if (strcmp(*argv, "-d") == 0) { + argv++; + if (*argv) + device = atoi(*argv); + } + if (strcmp(*argv, "-p") == 0) { + argv++; + if (*argv) + period_size = atoi(*argv); + } + if (strcmp(*argv, "-n") == 0) { + argv++; + if (*argv) + period_count = atoi(*argv); + } + if (strcmp(*argv, "-D") == 0) { + argv++; + if (*argv) + card = atoi(*argv); + } + if (*argv) + argv++; + } + + play_sample(file, card, device, chunk_fmt.num_channels, chunk_fmt.sample_rate, + chunk_fmt.bits_per_sample, period_size, period_count); + + fclose(file); + + return 0; +} +#endif + +static int check_param(struct pcm_params *params, unsigned int param, unsigned int value, + char *param_name, char *param_unit) +{ + unsigned int min; + unsigned int max; + int is_within_bounds = 1; + + min = pcm_params_get_min(params, param); + if (value < min) { + TRACE(ERROR, _x("%s is %u%s, device only supports >= %u%s\n"), param_name, value, + param_unit, min, param_unit); + is_within_bounds = 0; + } + + max = pcm_params_get_max(params, param); + if (value > max) { + TRACE(ERROR, _x("%s is %u%s, device only supports <= %u%s\n"), param_name, value, + param_unit, max, param_unit); + is_within_bounds = 0; + } + + return is_within_bounds; +} + +static int sample_is_playable(unsigned int card, unsigned int device, unsigned int channels, + unsigned int rate, unsigned int bits, unsigned int period_size, + unsigned int period_count) +{ + struct pcm_params *params; + int can_play; + + params = pcm_params_get(card, device, PCM_OUT); + if (params == NULL) { + TRACE(ERROR, _x("Unable to open PCM device %u.\n"), device); + return 0; + } + + can_play = check_param(params, PCM_PARAM_RATE, rate, "Sample rate", "Hz"); + can_play &= check_param(params, PCM_PARAM_CHANNELS, channels, "Sample", " channels"); + can_play &= check_param(params, PCM_PARAM_SAMPLE_BITS, bits, "Bitrate", " bits"); + can_play &= check_param(params, PCM_PARAM_PERIOD_SIZE, period_size, "Period size", "Hz"); + can_play &= check_param(params, PCM_PARAM_PERIODS, period_count, "Period count", "Hz"); + + pcm_params_free(params); + + return can_play; +} + +void *xa_playback_open(unsigned int card, + unsigned int device, + unsigned int channels, + unsigned int rate, + unsigned int bits, + unsigned int period_size, + unsigned int period_count) +{ + struct pcm_config config; + struct pcm *pcm; + + memset(&config, 0, sizeof(config)); + config.channels = channels; + config.rate = rate; + config.period_size = period_size; + config.period_count = period_count; + if (bits == 32) + config.format = PCM_FORMAT_S32_LE; + else if (bits == 16) + config.format = PCM_FORMAT_S16_LE; + config.start_threshold = 0; + config.stop_threshold = 0; + config.silence_threshold = 0; + + if (!sample_is_playable(card, device, channels, rate, bits, period_size, period_count)) { + return NULL; + } + + pcm = pcm_open(card, device, PCM_OUT, &config); + if (!pcm || !pcm_is_ready(pcm)) { + TRACE(ERROR, _x("Unable to open PCM device %u (%s)\n"), + device, pcm_get_error(pcm)); + return NULL; + } + + return pcm; +} + +int xa_playback_buf(void *handle, + const void *data, + unsigned int nbytes) +{ + int err; + + if (!handle || !data) + return XA_PLAYBACK_INVALID_PARAM; + + if (nbytes > 0) { + err = pcm_write(handle, data, nbytes); + + if (err == -EINVAL) return XA_PLAYBACK_INVALID_PARAM; + if (err == -EPIPE ) return XA_PLAYBACK_UNDERRUN; + } + + return XA_PLAYBACK_OK; +} + +int xa_playback_close(void *handle) +{ + return pcm_close(handle); +} + +#if 0 +void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned int channels, + unsigned int rate, unsigned int bits, unsigned int period_size, + unsigned int period_count) +{ + struct pcm_config config; + struct pcm *pcm; + char *buffer; + int size; + int num_read; + int hifi_dsp_fd; + struct misc_io_pcm_buf_param pcmbuf; + + hifi_dsp_fd = open(HIFI_DSP_MISC_DRIVER, O_RDWR, 0); + if(hifi_dsp_fd < 0){ + printf("Error opening hifi dsp device %d", errno); + } + + memset(&config, 0, sizeof(config)); + config.channels = channels; + config.rate = rate; + config.period_size = period_size; + config.period_count = period_count; + if (bits == 32) + config.format = PCM_FORMAT_S32_LE; + else if (bits == 16) + config.format = PCM_FORMAT_S16_LE; + config.start_threshold = 0; + config.stop_threshold = 0; + config.silence_threshold = 0; + + if (!sample_is_playable(card, device, channels, rate, bits, period_size, period_count)) { + return; + } + + pcm = pcm_open(card, device, PCM_OUT, &config); + if (!pcm || !pcm_is_ready(pcm)) { + fprintf(stderr, "Unable to open PCM device %u (%s)\n", + device, pcm_get_error(pcm)); + return; + } + + size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm)); + buffer = malloc(size); + if (!buffer) { + fprintf(stderr, "Unable to allocate %d bytes\n", size); + free(buffer); + pcm_close(pcm); + return; + } + + printf("Playing sample: %u ch, %u hz, %u bit\n", channels, rate, bits); + + /* catch ctrl-c to shutdown cleanly */ + signal(SIGINT, stream_close); + + do { + num_read = fread(buffer, 1, size, file); + + pcmbuf.buf =(uint64_t) buffer; + pcmbuf.buf_size = num_read; + if(hifi_dsp_fd) { + // printf("ioctl send \n"); + ioctl(hifi_dsp_fd,HIFI_MISC_IOCTL_PCM_GAIN, &pcmbuf); + // printf("ioctl complete \n"); + } + + if (num_read > 0) { + if (pcm_write(pcm, buffer, num_read)) { + fprintf(stderr, "Error playing sample\n"); + break; + } + } + } while (!s_close && num_read > 0); + + free(buffer); + pcm_close(pcm); + close(hifi_dsp_fd); +} +#endif diff --git a/hifi/xaf/host-apf/playback/xa_playback.h b/hifi/xaf/host-apf/playback/xa_playback.h new file mode 100644 index 00000000..8e4b3c63 --- /dev/null +++ b/hifi/xaf/host-apf/playback/xa_playback.h @@ -0,0 +1,42 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +enum xa_playback_error { + XA_PLAYBACK_OK = 0, + XA_PLAYBACK_INVALID_PARAM = -1, + XA_PLAYBACK_UNDERRUN = -2, +}; + +void *xa_playback_open(unsigned int card, + unsigned int device, + unsigned int channels, + unsigned int rate, + unsigned int bits, + unsigned int period_size, + unsigned int period_count); + +int xa_playback_buf(void *handle, + const void *data, + unsigned int nbytes); + +int xa_playback_close(void *handle); + diff --git a/hifi/xaf/host-apf/proxy/xaf-api.c b/hifi/xaf/host-apf/proxy/xaf-api.c new file mode 100644 index 00000000..6b5862df --- /dev/null +++ b/hifi/xaf/host-apf/proxy/xaf-api.c @@ -0,0 +1,597 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ +#include "xf.h" +#include "xaf-api.h" +#include "xaf-structs.h" + +#ifdef XAF_HOSTLESS +#include "xos-msgq-if.h" +#endif +#define MODULE_TAG DEVAPI + +/******************************************************************************* + * Tracing configuration + ******************************************************************************/ + +TRACE_TAG(INIT, 1); +TRACE_TAG(DEBUG, 1); +TRACE_TAG(INFO, 1); + +#define XAF_4BYTE_ALIGN 4 +#define XAF_8BYTE_ALIGN 8 +#define XAF_32BYTE_ALIGN 32 + + +static void xaf_comp_response(xf_handle_t *h, xf_user_msg_t *msg) +{ + if (msg->opcode == XF_UNREGISTER) + { + /* ...component execution failed unexpectedly; die */ + BUG(1, _x("[%p] Abnormal termination"), h); + } + else + { + /* ...submit response to asynchronous delivery queue */ + xf_response_put(h, msg); + } +} + +static XAF_ERR_CODE xaf_comp_add(xaf_comp_t **pp_comp_chain, xaf_comp_t *p_comp) +{ + XAF_CHK_PTR(pp_comp_chain); + XAF_CHK_PTR(p_comp); + + p_comp->next = *pp_comp_chain; + *pp_comp_chain = p_comp; + + return XAF_NO_ERROR; +} + +static XAF_ERR_CODE xaf_comp_post_init_config(xaf_adev_t *p_adev, xaf_comp_t *p_comp, void *p_msg) +{ + xf_proxy_t *p_proxy = &p_adev->proxy; + xf_start_msg_t *smsg = p_msg; + + p_comp->out_format.sample_rate = smsg->sample_rate; + p_comp->out_format.channels = smsg->channels; + p_comp->out_format.pcm_width = smsg->pcm_width; + p_comp->out_format.input_length = smsg->input_length; + p_comp->out_format.output_length = smsg->output_length; + + TRACE(INFO, _b("Component[%x] Params: f=%d, c=%d, w=%d i=%d o=%d"), p_comp->handle.id, smsg->sample_rate, smsg->channels, smsg->pcm_width, smsg->input_length, smsg->output_length); + + if (p_comp->noutbuf) + { + XF_CHK_API(xf_pool_alloc(p_proxy, p_comp->noutbuf, smsg->output_length, XF_POOL_OUTPUT, &p_comp->outpool, XAF_MEM_ID_COMP, + p_adev->pxf_mem_malloc_fxn, p_adev->pxf_mem_free_fxn)); + } + + p_comp->init_done = 1; + p_comp->comp_status = XAF_INIT_DONE; + + return XAF_NO_ERROR; +} + +#ifdef XAF_HOSTLESS +XAF_ERR_CODE xaf_xos_start() +{ +#if defined BOARD + xos_set_clock_freq(xtbsp_clock_freq_hz()); +#else + xos_set_clock_freq(XOS_CLOCK_FREQ); +#endif + + xos_start("main", 7, 0); +#if XCHAL_NUM_TIMERS > 0 + xos_start_system_timer(0, TICK_CYCLES); +#endif + + return XAF_NO_ERROR; +} +#endif + +XAF_ERR_CODE xaf_adev_open(void** pp_adev, s32 audio_frmwk_buf_size, s32 audio_comp_buf_size, xaf_mem_malloc_fxn_t mem_malloc, xaf_mem_free_fxn_t mem_free) +{ + int size; + void * pTmp; + xaf_adev_t *p_adev; + xf_proxy_t *p_proxy; + + XAF_CHK_PTR(pp_adev); + XAF_CHK_PTR(mem_malloc); + XAF_CHK_PTR(mem_free); + + /* ...unused arg */ + (void) audio_comp_buf_size; + + //Memory allocation for adev struct pointer + size = (sizeof(xaf_adev_t) +(XAF_4BYTE_ALIGN-1)); + pTmp = mem_malloc(size, XAF_MEM_ID_DEV); + XAF_CHK_PTR(pTmp); + memset(pTmp, 0, size); + + p_adev = (xaf_adev_t *) (((unsigned long)pTmp + (XAF_4BYTE_ALIGN-1))& ~(XAF_4BYTE_ALIGN-1)); + p_adev->adev_ptr = pTmp; + *pp_adev = (void *)p_adev; + + p_proxy = &p_adev->proxy; + + // Host side Memory allocation (BSS) + p_adev->pxf_mem_malloc_fxn = mem_malloc; + p_adev->pxf_mem_free_fxn = mem_free; + + size = sizeof(xaf_ap_utils_t)+(XAF_8BYTE_ALIGN-1); + p_adev->p_ap_utils = mem_malloc(size, XAF_MEM_ID_DEV); + XAF_CHK_PTR(p_adev->p_ap_utils); + //reset memory size stats + memset(p_adev->p_ap_utils, 0, sizeof(xaf_ap_utils_t)); + + // shmmem Memory allocation + p_adev->p_ap_utils->xf_cfg_remote_ipc_pool_size = audio_frmwk_buf_size; //minimum size 256 KB, mmap multiple is 0x1000 + + //DSP localbuf allocation is done in the DSP core; nothing to be done here + + /* ...open DSP proxy - specify "DSP#0" */ + XF_CHK_API(xf_proxy_init(p_proxy, 0, (void *)&p_adev->p_ap_utils->xf_cfg_remote_ipc_pool_size)); + + /* ...create auxiliary buffers pool for control commands */ + XF_CHK_API(xf_pool_alloc(p_proxy, XAF_AUX_POOL_SIZE, XAF_AUX_POOL_MSG_LENGTH, XF_POOL_AUX, &p_proxy->aux, XAF_MEM_ID_DEV, + p_adev->pxf_mem_malloc_fxn, p_adev->pxf_mem_free_fxn)); + + return XAF_NO_ERROR; +} + +XAF_ERR_CODE xaf_adev_close(void* adev_ptr, xaf_comp_flag flag) +{ + xaf_adev_t *p_adev; + xf_proxy_t *p_proxy; + + XAF_CHK_PTR(adev_ptr); + p_adev = (xaf_adev_t *)adev_ptr; + + /* ...unused arg */ + (void) flag; + + p_proxy = &p_adev->proxy; + if(p_proxy->aux != NULL) + { + xf_pool_free(p_proxy->aux, XAF_MEM_ID_DEV, p_adev->pxf_mem_free_fxn); + } + + xf_proxy_close(p_proxy); + + p_adev->pxf_mem_free_fxn(p_adev->p_ap_utils, XAF_MEM_ID_DEV); + p_adev->p_ap_utils = NULL; + p_adev->pxf_mem_free_fxn(p_adev->adev_ptr, XAF_MEM_ID_DEV); + p_adev->adev_ptr = NULL; + + p_adev->pxf_mem_malloc_fxn = NULL; + p_adev->pxf_mem_free_fxn = NULL; + + return XAF_NO_ERROR; +} + +XAF_ERR_CODE xaf_comp_create(void *adev_ptr, void **pp_comp, xf_id_t comp_id, u32 ninbuf, u32 noutbuf, void *pp_inbuf[], xaf_comp_type comp_type) +{ + xf_handle_t *p_handle; + void * pTmp; + int size; + + xaf_adev_t *p_adev; + p_adev = (xaf_adev_t *)adev_ptr; + xaf_comp_t *p_comp; + + XAF_CHK_PTR(p_adev); + XAF_CHK_PTR(pp_comp); + XAF_CHK_PTR(comp_id); + if (ninbuf) XAF_CHK_PTR(pp_inbuf); + + XAF_CHK_RANGE(ninbuf, 0, XAF_MAX_INBUFS); + XAF_CHK_RANGE(noutbuf, 0, 1); + XAF_CHK_RANGE(comp_type, XAF_DECODER, XAF_POST_PROC); + + //Memory allocation for component struct pointer + size = (sizeof(xaf_comp_t) + (XAF_4BYTE_ALIGN-1)); + pTmp = p_adev->pxf_mem_malloc_fxn(size, XAF_MEM_ID_COMP); + XAF_CHK_PTR(pTmp); + memset(pTmp, 0, size); + p_comp = (xaf_comp_t *) (((unsigned long)pTmp + (XAF_4BYTE_ALIGN-1))& ~(XAF_4BYTE_ALIGN-1)); + + p_comp->comp_ptr = pTmp; + *pp_comp = (void*)p_comp; + + memset(p_comp, 0, sizeof(xaf_comp_t)); + p_handle = &p_comp->handle; + + /* ...create component instance (select core-0) */ + XF_CHK_API(xf_open(&p_adev->proxy, p_handle, comp_id, 0, xaf_comp_response)); + + xaf_comp_add(&p_adev->comp_chain, p_comp); + + // Temporary solution in place of component chain handling + p_comp->p_adev = p_adev; + p_adev->n_comp += 1; + p_comp->ninbuf = ninbuf; + + /* ...allocate input buffer */ + if (ninbuf) + { + xf_buffer_t *buf; + u32 i; + XF_CHK_API(xf_pool_alloc(&p_adev->proxy, ninbuf, XAF_INBUF_SIZE, XF_POOL_INPUT, &p_comp->inpool, XAF_MEM_ID_COMP, + p_adev->pxf_mem_malloc_fxn, p_adev->pxf_mem_free_fxn)); + + for (i=0; i<ninbuf; i++) + { + buf = xf_buffer_get(p_comp->inpool); + pp_inbuf[i] = xf_buffer_data(buf); + } + + } + p_comp->noutbuf = noutbuf; + + p_comp->comp_type = comp_type; + p_comp->comp_status = XAF_STARTING; + + switch (comp_type) + { + case XAF_DECODER: + case XAF_ENCODER: + case XAF_PRE_PROC: + case XAF_POST_PROC: + p_comp->inp_ports = 1; p_comp->out_ports = 1; + break; + case XAF_MIXER: + p_comp->inp_ports = 4; p_comp->out_ports = 1; + break; + } + + return XAF_NO_ERROR; +} + +XAF_ERR_CODE xaf_comp_delete(void *comp_ptr) +{ + xaf_adev_t *p_adev; + + xaf_comp_t *p_comp; + p_comp = (xaf_comp_t *)comp_ptr; + + XAF_CHK_PTR(p_comp); + + // Temporary solution in place of component chain handling + p_adev = (xaf_adev_t *)(p_comp->p_adev); + XF_CHK_ERR((p_adev->n_comp > 0), XAF_API_ERR); + p_adev->n_comp -= 1; + + + if (p_comp->inpool) xf_pool_free(p_comp->inpool, XAF_MEM_ID_COMP, p_adev->pxf_mem_free_fxn); + if (p_comp->outpool) xf_pool_free(p_comp->outpool, XAF_MEM_ID_COMP, p_adev->pxf_mem_free_fxn); + + xf_close(&p_comp->handle); + + /* ...tbd - remove from chain */ + p_adev->pxf_mem_free_fxn(p_comp->comp_ptr, XAF_MEM_ID_COMP); + p_comp->comp_ptr = NULL; + + return XAF_NO_ERROR; +} + +XAF_ERR_CODE xaf_comp_set_config(void *comp_ptr, s32 num_param, s32 *p_param) +{ + xaf_comp_t *p_comp; + xf_user_msg_t rmsg; + xf_set_param_msg_t *smsg; + xf_handle_t *p_handle; + s32 i, j; + + p_comp = (xaf_comp_t *)comp_ptr; + + XAF_CHK_PTR(p_comp); + XAF_CHK_PTR(p_param); + XAF_CHK_RANGE(num_param, 1, XAF_MAX_CONFIG_PARAMS); + + p_handle = &p_comp->handle; + XAF_CHK_PTR(p_handle); + + /* ...set persistent stream characteristics */ + smsg = xf_buffer_data(p_handle->aux); + + j = 0; + for (i=0; i<num_param; i++) + { + smsg->item[i].id = p_param[j++]; + smsg->item[i].value = p_param[j++]; + } + + /* ...pass command to the component */ + /* ...tbd - command goes port 0 always, check if okay */ + XF_CHK_API(xf_command(p_handle, 0, XF_SET_PARAM, smsg, sizeof(xf_set_param_item_t)*num_param)); + + /* ...wait until result is delivered */ + XF_CHK_API(xf_response_get(p_handle, &rmsg)); + + /* ...make sure response is expected */ + XF_CHK_ERR(rmsg.opcode == (u32) XF_SET_PARAM && rmsg.buffer == smsg, XAF_API_ERR); + + return XAF_NO_ERROR; +} + +XAF_ERR_CODE xaf_comp_get_config(void *comp_ptr, s32 num_param, s32 *p_param) +{ + xaf_comp_t *p_comp; + xf_user_msg_t rmsg; + xf_get_param_msg_t *smsg; + xf_handle_t *p_handle; + s32 i; + + p_comp = (xaf_comp_t *)comp_ptr; + + XAF_CHK_PTR(p_comp); + XAF_CHK_PTR(p_param); + XAF_CHK_RANGE(num_param, 1, XAF_MAX_CONFIG_PARAMS); + + p_handle = &p_comp->handle; + XAF_CHK_PTR(p_handle); + + /* ...set persistent stream characteristics */ + smsg = xf_buffer_data(p_handle->aux); + + for (i=0; i<num_param; i++) + { + smsg->c.id[i] = p_param[i]; + } + + /* ...pass command to the component */ + /* ...tbd - command goes port 0 always, check if okay */ + XF_CHK_API(xf_command(p_handle, 0, XF_GET_PARAM, smsg, XF_GET_PARAM_CMD_LEN(num_param))); + + /* ...wait until result is delivered */ + XF_CHK_API(xf_response_get(p_handle, &rmsg)); + + /* ...make sure response is expected */ + XF_CHK_ERR(rmsg.opcode == (u32) XF_GET_PARAM && rmsg.buffer == smsg, XAF_API_ERR); + + for (i=0; i<num_param; i++) + { + p_param[i] = smsg->r.value[i]; + } + + return XAF_NO_ERROR; +} +#ifdef XAF_HOSTLESS +XAF_ERR_CODE xaf_comp_get_status(xaf_adev_t *p_adev, xaf_comp_t *p_comp, xaf_comp_status *p_status, void *p_info) +#else +XAF_ERR_CODE xaf_comp_get_status(void *adev_ptr, void *comp_ptr, xaf_comp_status *p_status, xaf_info_t *p_info) +#endif +{ + xaf_adev_t *p_adev; + xaf_comp_t *p_comp; + xf_handle_t *p_handle; + + p_adev = (xaf_adev_t *)adev_ptr; + p_comp = (xaf_comp_t *)comp_ptr; + + XAF_CHK_PTR(p_comp); + XAF_CHK_PTR(p_status); + XAF_CHK_PTR(p_info); + if (!p_comp->init_done) XAF_CHK_PTR(p_adev); + + p_handle = &p_comp->handle; + + if (p_comp->pending_resp) + { + xf_user_msg_t rmsg; + /* ...wait until result is delivered */ + XF_CHK_API(xf_response_get(p_handle, &rmsg)); + + if (rmsg.opcode == XF_FILL_THIS_BUFFER) + { + if (rmsg.buffer == p_comp->start_buf) + { + XF_CHK_API(xaf_comp_post_init_config(p_adev, p_comp, p_comp->start_buf)); + } + else + { +#ifdef XAF_HOSTLESS + s32 *p_buf = (s32 *) p_info; + p_buf[0] = (s32) rmsg.buffer; + p_buf[1] = (s32) rmsg.length; +#else + p_info->buf = (void*) rmsg.buffer; + p_info->length = (s32) rmsg.length; +#endif + if (!p_comp->inpool && p_comp->outpool) p_comp->pending_resp--; + + if (!rmsg.length) p_comp->comp_status = XAF_EXEC_DONE; + else + { + p_comp->comp_status = XAF_OUTPUT_READY; + p_comp->expect_out_cmd++; + } + } + } + else + { + /* ...make sure response is expected */ + XF_CHK_ERR(rmsg.opcode == (u32) XF_EMPTY_THIS_BUFFER, XAF_API_ERR); +#ifdef XAF_HOSTLESS + s32 *p_buf = (s32 *) p_info; + p_buf[0] = (s32) rmsg.buffer; + p_buf[1] = (s32) rmsg.length; +#else + p_info->buf = (void*) rmsg.buffer; + p_info->length = (s32) rmsg.length; +#endif + p_comp->pending_resp--; + + if (p_comp->input_over && rmsg.buffer == NULL) p_comp->comp_status = XAF_EXEC_DONE; + else p_comp->comp_status = XAF_NEED_INPUT; + } + } + else if ((p_comp->comp_status == XAF_STARTING && p_comp->start_cmd_issued) || + (p_comp->comp_status == XAF_INIT_DONE && p_comp->exec_cmd_issued)) + { + if (p_comp->inpool) p_comp->comp_status = XAF_NEED_INPUT; + } + + *p_status = p_comp->comp_status; + + return XAF_NO_ERROR; +} + +XAF_ERR_CODE xaf_comp_process(void *adev_ptr, void *comp_ptr, void *p_buf, u32 length, xaf_comp_flag flag) +{ + xaf_adev_t *p_adev; + xaf_comp_t *p_comp; + xf_handle_t *p_handle; + + p_adev = (xaf_adev_t *)adev_ptr; + p_comp = (xaf_comp_t *)comp_ptr; + + XAF_CHK_PTR(p_comp); + if (!p_comp->init_done) XAF_CHK_PTR(p_adev); + XAF_CHK_RANGE(flag, XAF_START_FLAG, XAF_NEED_OUTPUT_FLAG); + if (flag == XAF_INPUT_READY_FLAG) XAF_CHK_RANGE(length, 0, XAF_INBUF_SIZE); + + p_handle = &p_comp->handle; + + switch (flag) + { + case XAF_START_FLAG: + if (p_comp->start_cmd_issued) + break; + else + { + p_comp->start_buf = xf_buffer_data(p_handle->aux); + XF_CHK_API(xf_command(p_handle, (p_comp->inp_ports), XF_FILL_THIS_BUFFER, p_comp->start_buf, 0)); + p_comp->start_cmd_issued = 1; + + if(p_comp->comp_type != XAF_DECODER) + { + xf_user_msg_t rmsg; + /* ...wait until result is delivered */ + XF_CHK_API(xf_response_get(p_handle, &rmsg)); + + /* ...make sure response is expected */ + XF_CHK_ERR(rmsg.opcode == XF_FILL_THIS_BUFFER && rmsg.buffer == p_comp->start_buf, XAF_API_ERR); + + XF_CHK_API(xaf_comp_post_init_config(p_adev, p_comp, p_comp->start_buf)); + } + } + break; + + case XAF_EXEC_FLAG: + if (!p_comp->init_done || p_comp->exec_cmd_issued) + break; + p_comp->exec_cmd_issued = 1; + if (p_comp->outpool) + { + u32 i; + xf_buffer_t *p_buf; + void *p_data; + + for (i=0; i<p_comp->noutbuf; i++) + { + p_buf = xf_buffer_get(p_comp->outpool); + p_data = xf_buffer_data(p_buf); + + XF_CHK_API(xf_command(&p_comp->handle, (p_comp->inp_ports), XF_FILL_THIS_BUFFER, p_data, p_comp->out_format.output_length)); + } + + if (!p_comp->inpool) p_comp->pending_resp = p_comp->noutbuf; + } + break; + + case XAF_INPUT_OVER_FLAG: + if (!p_comp->input_over) + { + XF_CHK_API(xf_command(p_handle, 0, XF_EMPTY_THIS_BUFFER, NULL, 0)); + p_comp->input_over = 1; + p_comp->pending_resp++; + } + break; + + case XAF_INPUT_READY_FLAG: + if (!p_comp->input_over) + { + XAF_CHK_PTR(p_buf); + XF_CHK_API(xf_command(p_handle, 0, XF_EMPTY_THIS_BUFFER, p_buf, length)); + p_comp->pending_resp++; + } + break; + + case XAF_NEED_OUTPUT_FLAG: + if (p_comp->expect_out_cmd) + { + XAF_CHK_PTR(p_buf); + XF_CHK_API(xf_command(p_handle, (p_comp->inp_ports), XF_FILL_THIS_BUFFER, p_buf, length)); + p_comp->expect_out_cmd--; + + if (!p_comp->inpool && p_comp->outpool) p_comp->pending_resp++; + } + break; + } + + return XAF_NO_ERROR; +} + +XAF_ERR_CODE xaf_connect(void *src_ptr, void *dest_ptr, s32 num_buf) +{ + xaf_comp_t *p_src; + xaf_comp_t *p_dest; + + p_src = (xaf_comp_t *)src_ptr; + p_dest = (xaf_comp_t *)dest_ptr; + + XAF_CHK_PTR(p_src); + XAF_CHK_PTR(p_dest); + XAF_CHK_RANGE(num_buf, 2, 4); + + if (!p_src->init_done || p_src->out_routed == p_src->out_ports || p_dest->inp_routed == p_dest->inp_ports) + return XAF_ROUTING_ERROR; + + XF_CHK_API(xf_route(&p_src->handle, (p_src->inp_ports + p_src->out_routed), &p_dest->handle, (p_dest->inp_routed), num_buf, p_src->out_format.output_length, 8)); + + p_src->out_routed++; + p_dest->inp_routed++; + + return XAF_NO_ERROR; +} + +XAF_ERR_CODE xaf_disconnect(xaf_comp_t *p_comp) +{ + XAF_CHK_PTR(p_comp); + + /* ...tbd - support for multiple output ports */ + if (!p_comp->init_done || p_comp->out_routed != p_comp->out_ports) + return XAF_ROUTING_ERROR; + + XF_CHK_API(xf_unroute(&p_comp->handle, (p_comp->inp_ports))); + + return XAF_NO_ERROR; +} + + + + + + diff --git a/hifi/xaf/host-apf/proxy/xf-fio.c b/hifi/xaf/host-apf/proxy/xf-fio.c new file mode 100644 index 00000000..5c3c3dbf --- /dev/null +++ b/hifi/xaf/host-apf/proxy/xf-fio.c @@ -0,0 +1,193 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#define MODULE_TAG FIO + +/******************************************************************************* + * Includes + ******************************************************************************/ + +#include "xf.h" +#include <sys/ioctl.h> +#include <sys/mman.h> + +/******************************************************************************* + * Tracing configuration + ******************************************************************************/ + +TRACE_TAG(INIT, 1); +TRACE_TAG(CMD, 1); +TRACE_TAG(RSP, 1); + +/******************************************************************************* + * Local constants - tbd + ******************************************************************************/ + +/* ...proxy setup ioctl */ +#define XF_PROXY_SETUP_IOCTL _IO('P', 0x0) + +/* ...proxy close ioctl */ +#define XF_PROXY_CLOSE_IOCTL _IO('P', 0x1) + +#define HIFI_DSP_MISC_DRIVER "/dev/hifi_misc" +#ifndef GJB_COMMENT +#define HIFI_MISC_IOCTL_XAF_IPC_MSG_SEND _IOW('A', 0x7c, xf_proxy_message_driv_t) +#define HIFI_MISC_IOCTL_XAF_IPC_MSG_RECV _IOR('A', 0x7d, xf_proxy_message_driv_t) +#define HIFI_MISC_IOCTL_XAF_IPC_VMSG_PTR _IOR('A', 0x7e, xf_proxy_message_driv_t) +#endif +//u8 remote_ipc_pool[XF_CFG_REMOTE_IPC_POOL_SIZE]; +/******************************************************************************* + * Internal IPC API implementation + ******************************************************************************/ + +/* ...pass command to remote DSP */ +int xf_ipc_send(xf_proxy_ipc_data_t *ipc, xf_proxy_msg_t *msg, void *b) +{ + /* ...unused arg */ + (void) b; + + int fd = ipc->fd; + int ret; +#ifdef GJB_COMMENT + TRACE(CMD, _b("C[%08x]:(%x,%08x,%u)"), msg->id, msg->opcode, msg->address, msg->length); + + /* ...pass message to kernel driver */ + XF_CHK_ERR(write(fd, msg, sizeof(*msg)) == sizeof(*msg), -errno); +#else + ret = ioctl(fd, HIFI_MISC_IOCTL_XAF_IPC_MSG_SEND, msg);// GJB:-Verify th return value with driver implementation. +#endif + + /* ...communication mutex is still locked! */ + return 0; +} + +/* ...wait for response availability */ +int xf_ipc_wait(xf_proxy_ipc_data_t *ipc, u32 timeout) +{ + int fd = ipc->fd; + fd_set rfds; + struct timeval tv; + + /* ...specify waiting set */ + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + /* ...set timeout value if given */ + (timeout ? tv.tv_sec = timeout / 1000, tv.tv_usec = (timeout % 1000) * 1000 : 0); + + /* ...wait until there is a data in file */ +// XF_CHK_ERR(select(fd + 1, &rfds, NULL, NULL, (timeout ? &tv : NULL)) >= 0, -errno); + select(fd+1,&rfds,NULL,NULL,(timeout? &tv: NULL)); + + /* ...check if descriptor is set */ + return (FD_ISSET(fd, &rfds) ? 0 : -ETIMEDOUT); +} + +/* ...read response from proxy */ +int xf_ipc_recv(xf_proxy_ipc_data_t *ipc, xf_proxy_msg_t *msg, void **buffer) +{ + int fd = ipc->fd; + int r; + xf_proxy_msg_t temp; +#ifdef GJB_COMMENT + /* ...get message header from file */ + if ((r = read(fd, msg, sizeof(*msg))) == sizeof(*msg)) + { + TRACE(RSP, _b("R[%08x]:(%x,%u,%08x)"), msg->id, msg->opcode, msg->length, msg->address); + + /* ...translate shared address into local pointer */ + XF_CHK_ERR((*buffer = xf_ipc_a2b(ipc, msg->address)) != (void *)-1, -EBADFD); + + /* ...return positive result indicating the message has been received */ + return sizeof(*msg); + } +#else + if ((r = ioctl(fd, HIFI_MISC_IOCTL_XAF_IPC_MSG_RECV, &temp)) == sizeof(temp)) + { + msg->id = temp.id; + msg->opcode = temp.opcode; + msg->length = temp.length; + *buffer = xf_ipc_a2b(ipc, temp.address); + /* ...translate shared address into local pointer */ + XF_CHK_ERR((*buffer = xf_ipc_a2b(ipc, temp.address)) != (void *)-1, -EBADFD); + msg->address = temp.address; + return sizeof(*msg); + } +#endif + else + { + /* ...if no response is available, return 0 result */ + return XF_CHK_API(errno == EAGAIN ? 0 : -errno); + } +} + +/******************************************************************************* + * Internal API functions implementation + ******************************************************************************/ + +/* ...open proxy interface on proper DSP partition */ +int xf_ipc_open(xf_proxy_ipc_data_t *ipc, u32 core, void *p_shmem) +{ + //XF_CHK_ERR((p_shmem != NULL), -errno); + //size_t xf_cfg_remote_ipc_pool_size = *(size_t *)p_shmem;//user configured shmem pool size: minimum 256 KB + /* ...unused arg */ + (void) p_shmem; +#ifdef GJB_COMMENT + /* ...open file handle */ + XF_CHK_ERR((ipc->fd = open("/dev/xtensa-proxy", O_RDWR)) >= 0, -errno); + + /* ...pass shread memory core for this proxy instance */ + XF_CHK_ERR(ioctl(ipc->fd, XF_PROXY_SETUP_IOCTL, core) >= 0, -errno); +#else + XF_CHK_ERR((ipc->fd = open(HIFI_DSP_MISC_DRIVER, O_RDWR,0)) >= 0, -errno); +#endif + /* ...create pipe for asynchronous response delivery */ + XF_CHK_ERR(pipe(ipc->pipe) == 0, -errno); + + /* ...map entire shared memory region (not too good - tbd) */ +// ipc->shmem = remote_ipc_pool; +// ioctl(ipc->fd, HIFI_MISC_IOCTL_XAF_IPC_VMSG_PTR, ipc->shmem); +#if 1 + //allocate 256 KB constant size + XF_CHK_ERR((ipc->shmem = mmap(NULL, XF_CFG_REMOTE_IPC_POOL_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, ipc->fd, 0)) != MAP_FAILED, -errno); +#else + XF_CHK_ERR((ipc->shmem = mmap(NULL, xf_cfg_remote_ipc_pool_size, PROT_READ | PROT_WRITE, MAP_SHARED, ipc->fd, 0)) != MAP_FAILED, -errno); +#endif + TRACE(INIT, _b("proxy-%u interface opened"), core); + return 0; +} + +/* ...close proxy handle */ +void xf_ipc_close(xf_proxy_ipc_data_t *ipc, u32 core) +{ + /* ...unmap shared memory region */ +// (void)munmap(ipc->shmem, XF_CFG_REMOTE_IPC_POOL_SIZE); + + /* ...close asynchronous response delivery pipe */ + close(ipc->pipe[0]), close(ipc->pipe[1]); + + /* ...close proxy file handle */ + close(ipc->fd); + + TRACE(INIT, _b("proxy-%u interface closed"), core); +} + diff --git a/hifi/xaf/host-apf/proxy/xf-proxy.c b/hifi/xaf/host-apf/proxy/xf-proxy.c new file mode 100644 index 00000000..9487f4ea --- /dev/null +++ b/hifi/xaf/host-apf/proxy/xf-proxy.c @@ -0,0 +1,686 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#define MODULE_TAG PROXY + +/******************************************************************************* + * Includes + ******************************************************************************/ + +#include "xf.h" + +/******************************************************************************* + * Tracing configuration + ******************************************************************************/ + +TRACE_TAG(INIT, 1); +TRACE_TAG(CMD, 1); +TRACE_TAG(EXEC, 1); +TRACE_TAG(RSP, 1); +TRACE_TAG(REG, 1); +TRACE_TAG(MEM, 1); +TRACE_TAG(GRAPH, 1); +TRACE_TAG(BUFFER, 1); + +/******************************************************************************* + * Internal functions definitions + ******************************************************************************/ + +/* ...execute proxy command synchronously */ +static inline int xf_proxy_cmd_exec(xf_proxy_t *proxy, xf_user_msg_t *msg) +{ + xf_proxy_msg_t m; + + /* ...send command to remote proxy */ + m.id = msg->id, m.opcode = msg->opcode, m.length = msg->length; + + /* ...translate address */ + XF_CHK_ERR((m.address = xf_proxy_b2a(proxy, msg->buffer)) != XF_PROXY_BADADDR, -EINVAL); + + /* ...pass command to remote proxy */ + XF_CHK_API(xf_ipc_send(&proxy->ipc, &m, msg->buffer)); + + /* ...wait for response reception indication from proxy thread */ + XF_CHK_API(xf_proxy_response_get(proxy, &m)); + + /* ...copy parameters */ + msg->id = m.id, msg->opcode = m.opcode, msg->length = m.length; + + /* ...translate address back to virtual space */ + XF_CHK_ERR((msg->buffer = xf_proxy_a2b(proxy, m.address)) != (void *)-1, -EBADFD); + + TRACE(EXEC, _b("proxy[%p]: command done: [%08x:%p:%u]"), proxy, msg->opcode, msg->buffer, msg->length); + + return 0; +} + +#if 0 +/* ...pass command to remote DSP */ +static inline int xf_proxy_cmd(xf_proxy_t *proxy, xf_handle_t *handle, xf_user_msg_t *m) +{ + xf_proxy_msg_t msg; + + /* ...set session-id of the message */ + msg.id = __XF_MSG_ID(__XF_AP_CLIENT(proxy->core, handle->client), m->id); + msg.opcode = m->opcode; + msg.length = m->length; + + /* ...translate buffer pointer to shared address */ + XF_CHK_ERR((msg.address = xf_proxy_b2a(proxy, m->buffer)) != XF_PROXY_BADADDR, -EINVAL); + + /* ...submit command message to IPC layer */ + return XF_CHK_API(xf_ipc_send(&proxy->ipc, &msg, m->buffer)); +} +#endif /* 0 */ + +/* ...allocate local client-id number */ +static inline u32 xf_client_alloc(xf_proxy_t *proxy, xf_handle_t *handle) +{ + u32 client; + + if ((client = proxy->cmap[0].next) != 0) + { + /* ...pop client from free clients list */ + proxy->cmap[0].next = proxy->cmap[client].next; + + /* ...put client handle into association map */ + handle->client = client, proxy->cmap[client].handle = handle; + } + + return client; +} + +/* ...recycle local client-id number */ +static inline void xf_client_free(xf_proxy_t *proxy, xf_handle_t *handle) +{ + u32 client = handle->client; + + /* ...push client into head of the free clients list */ + proxy->cmap[client].next = proxy->cmap[0].next; + + /* ...adjust head of free clients */ + proxy->cmap[0].next = client; +} + +/* ...lookup client basing on its local id */ +static inline xf_handle_t * xf_client_lookup(xf_proxy_t *proxy, u32 client) +{ + /* ...client index must be in proper range */ + BUG(client >= XF_CFG_PROXY_MAX_CLIENTS, _x("Invalid client index: %u"), client); + + /* ...check if client index is small */ + if (proxy->cmap[client].next < XF_CFG_PROXY_MAX_CLIENTS) + return NULL; + else + return proxy->cmap[client].handle; +} + +/* ...create new client on remote core */ +static inline int xf_client_register(xf_proxy_t *proxy, xf_handle_t *handle, xf_id_t id, u32 core) +{ + void *b = xf_handle_aux(handle); + xf_user_msg_t msg; + + /* ...set session-id: source is local proxy, destination is remote proxy */ + msg.id = __XF_MSG_ID(__XF_AP_PROXY(proxy->core), __XF_DSP_PROXY(core)); + msg.opcode = XF_REGISTER; + msg.buffer = b; + msg.length = strlen(id) + 1; + + /* ...copy component identifier */ + strncpy(b, id, xf_buffer_length(handle->aux)); + + /* ...execute command synchronously */ + XF_CHK_API(xf_proxy_cmd_exec(proxy, &msg)); + + /* ...check operation is successfull */ + XF_CHK_ERR(msg.opcode == (u32) XF_REGISTER, -EFAULT); + + /* ...save received component global client-id */ + handle->id = XF_MSG_SRC(msg.id); + + TRACE(REG, _b("[%p]=[%s:%u:%u]"), handle, id, XF_PORT_CORE(handle->id), XF_PORT_CLIENT(handle->id)); + + return 0; +} + +/* ...unregister client from remote proxy */ +static inline int xf_client_unregister(xf_proxy_t *proxy, xf_handle_t *handle) +{ + xf_user_msg_t msg; + + /* ...make sure the client is consistent */ + BUG(proxy->cmap[handle->client].handle != handle, _x("Invalid handle: %p"), handle); + + /* ...set message parameters */ + msg.id = __XF_MSG_ID(__XF_AP_PROXY(proxy->core), handle->id); + msg.opcode = XF_UNREGISTER; + msg.buffer = NULL; + msg.length = 0; + + /* ...synchronously execute command on remote proxy */ + XF_CHK_API(xf_proxy_cmd_exec(proxy, &msg)); + + /* ...opcode must be XF_UNREGISTER - tbd */ + BUG(msg.opcode != XF_UNREGISTER, _x("Invalid opcode: %X"), msg.opcode); + + TRACE(REG, _b("%p[%u:%u] unregistered"), handle, XF_PORT_CORE(handle->id), XF_PORT_CLIENT(handle->id)); + + return 0; +} + +/* ...allocate shared buffer */ +static inline int xf_proxy_buffer_alloc(xf_proxy_t *proxy, u32 length, void **buffer) +{ + u32 core = proxy->core; + xf_user_msg_t msg; + + /* ...prepare command parameters */ + msg.id = __XF_MSG_ID(__XF_AP_PROXY(core), __XF_DSP_PROXY(core)); + msg.opcode = XF_ALLOC; + msg.length = length; + msg.buffer = NULL; + + /* ...synchronously execute command on remote proxy */ + XF_CHK_API(xf_proxy_cmd_exec(proxy, &msg)); + + /* ...check if response is valid */ + XF_CHK_ERR(msg.opcode == XF_ALLOC, -EBADFD); + + /* ...check if allocation is successful */ + XF_CHK_ERR(msg.buffer != NULL, -ENOMEM); + + /* ...save output parameter */ + *buffer = msg.buffer; + + TRACE(MEM, _b("proxy-%u: allocated [%p:%u]"), core, *buffer, length); + + return 0; +} + +/* ...free shared AP-DSP memory */ +static inline int xf_proxy_buffer_free(xf_proxy_t *proxy, void *buffer, u32 length) +{ + u32 core = proxy->core; + xf_user_msg_t msg; + + /* ...prepare command parameters */ + msg.id = __XF_MSG_ID(__XF_AP_PROXY(core), __XF_DSP_PROXY(core)); + msg.opcode = XF_FREE; + msg.length = length; + msg.buffer = buffer; + + /* ...synchronously execute command on remote proxy */ + XF_CHK_API(xf_proxy_cmd_exec(proxy, &msg)); + + /* ...check if response is valid */ + XF_CHK_ERR(msg.opcode == XF_FREE, -EBADFD); + + TRACE(MEM, _b("proxy-%u: free [%p:%u]"), core, buffer, length); + + return 0; +} + +/******************************************************************************* + * Proxy interface asynchronous receiving thread + ******************************************************************************/ + +static void * xf_proxy_thread(void *arg) +{ + xf_proxy_t *proxy = arg; + xf_handle_t *client; + int r; + + /* ...start polling thread */ + while (1) + { + xf_proxy_msg_t m; + xf_user_msg_t msg; + + /* ...wait for response from remote proxy (infinite timeout) */ + if ((r = xf_ipc_wait(&proxy->ipc, 0)) < 0) + break; + + /* ...retrieve all responses received */ + while ((r = xf_ipc_recv(&proxy->ipc, &m, &msg.buffer)) == sizeof(m)) + { + /* ...make sure we have proper core identifier of SHMEM interface */ + BUG(XF_MSG_DST_CORE(m.id) != proxy->core, _x("Invalid session-id: %X (core=%u)"), m.id, proxy->core); + + /* ...make sure translation is successful */ + BUG(msg.buffer == (void *)-1, _x("Invalid buffer address: %08x"), m.address); + + /* ...retrieve information fields */ + msg.id = XF_MSG_SRC(m.id), msg.opcode = m.opcode, msg.length = m.length; + + TRACE(RSP, _b("R[%08x]:(%08x,%u,%08x)"), m.id, m.opcode, m.length, m.address); + + /* ...lookup component basing on destination port specification */ + if (XF_AP_CLIENT(m.id) == 0) + { + /* ...put proxy response to local IPC queue */ + xf_proxy_response_put(proxy, &m); + } + else if ((client = xf_client_lookup(proxy, XF_AP_CLIENT(m.id))) != NULL) + { + /* ...client is found; invoke its response callback (must be non-blocking) */ + client->response(client, &msg); + } + else + { + /* ...client has been disconnected already; drop message */ + TRACE(RSP, _b("Client look-up failed - drop message")); + } + } + + /* ...if result code is negative; terminate thread operation */ + if (r < 0) + { + TRACE(ERROR, _x("abnormal proxy[%p] thread termination: %d"), proxy, r); + break; + } + } + + TRACE(INIT, _b("IPC proxy[%p] thread terminated: %d"), proxy, r); + + return (void *)(intptr_t)r; +} + +/******************************************************************************* + * HiFi proxy API + ******************************************************************************/ + +/* ...open HiFi proxy */ +int xf_proxy_init(xf_proxy_t *proxy, u32 core, void *p_shmem) +{ + u32 i; + int r; + + /* ...initialize proxy lock */ + __xf_lock_init(&proxy->lock); + + /* ...open proxy IPC interface */ + XF_CHK_API(xf_ipc_open(&proxy->ipc, core, p_shmem)); + + /* ...save proxy core - hmm, too much core identifiers - tbd */ + proxy->core = core; + + /* ...line-up all clients into single-linked list */ + for (i = 0; i < XF_CFG_PROXY_MAX_CLIENTS - 1; i++) + { + proxy->cmap[i].next = i + 1; + } + + /* ...tail of the list points back to head (list terminator) */ + proxy->cmap[i].next = 0; + + /* ...initialize thread attributes (joinable, with minimal stack) */ + if ((r = __xf_thread_create(&proxy->thread, xf_proxy_thread, proxy)) < 0) + { + TRACE(ERROR, _x("Failed to create polling thread: %d"), r); + xf_ipc_close(&proxy->ipc, core); + return r; + } + + TRACE(INIT, _b("proxy-%u[%p] opened"), core, proxy); + + return 0; +} + +/* ...close proxy handle */ +void xf_proxy_close(xf_proxy_t *proxy) +{ + u32 core = proxy->core; + + /* ...terminate proxy thread */ + __xf_thread_destroy(&proxy->thread); + + /* ...close proxy IPC interface */ + xf_ipc_close(&proxy->ipc, core); + + TRACE(INIT, _b("proxy-%u[%p] closed"), core, proxy); +} + +/******************************************************************************* + * HiFi component API + ******************************************************************************/ + +/* ...open component handle */ +int xf_open(xf_proxy_t *proxy, xf_handle_t *handle, xf_id_t id, u32 core, xf_response_cb response) +{ + int r; + + /* ...retrieve auxiliary control buffer from proxy - need I */ + XF_CHK_ERR(handle->aux = xf_buffer_get(proxy->aux), -EBUSY); + + /* ...initialize IPC data */ + XF_CHK_API(xf_ipc_data_init(&handle->ipc)); + + /* ...register client in interlocked fashion */ + xf_proxy_lock(proxy); + + /* ...allocate local client */ + if (xf_client_alloc(proxy, handle) == 0) + { + TRACE(ERROR, _x("client allocation failed")); + r = -EBUSY; + } + else if ((r = xf_client_register(proxy, handle, id, core)) < 0) + { + TRACE(ERROR, _x("client registering failed")); + xf_client_free(proxy, handle); + } + + xf_proxy_unlock(proxy); + + /* ...if failed, release buffer handle */ + if (r < 0) + { + /* ...operation failed; return buffer back to proxy pool */ + xf_buffer_put(handle->aux), handle->aux = NULL; + } + else + { + /* ...operation completed successfully; assign handle data */ + handle->response = response; + handle->proxy = proxy; + + TRACE(INIT, _b("component[%p]:(id=%s,core=%u) created"), handle, id, core); + } + + return XF_CHK_API(r); +} + +/* ...close component handle */ +void xf_close(xf_handle_t *handle) +{ + xf_proxy_t *proxy = handle->proxy; + + /* ...do I need to take component lock here? guess no - tbd */ + + /* ...buffers and stuff? - tbd */ + + /* ...acquire global proxy lock */ + xf_proxy_lock(proxy); + + /* ...unregister component from remote DSP proxy (ignore result code) */ + (void) xf_client_unregister(proxy, handle); + + /* ...recycle client-id afterwards */ + xf_client_free(proxy, handle); + + /* ...release global proxy lock */ + xf_proxy_unlock(proxy); + + /* ...destroy IPC data */ + xf_ipc_data_destroy(&handle->ipc); + + /* ...clear handle data */ + xf_buffer_put(handle->aux), handle->aux = NULL; + + /* ...wipe out proxy pointer */ + handle->proxy = NULL; + + TRACE(INIT, _b("component[%p] destroyed"), handle); +} + +/* ...port binding function */ +int xf_route(xf_handle_t *src, u32 src_port, xf_handle_t *dst, u32 dst_port, u32 num, u32 size, u32 align) +{ + xf_proxy_t *proxy = src->proxy; + xf_buffer_t *b; + xf_route_port_msg_t *m; + xf_user_msg_t msg; + + /* ...sanity checks - proxy pointers are same */ + XF_CHK_ERR(proxy == dst->proxy, -EINVAL); + + /* ...buffer data is sane */ + XF_CHK_ERR(num && size && xf_is_power_of_two(align), -EINVAL); + + /* ...get control buffer */ + XF_CHK_ERR(b = xf_buffer_get(proxy->aux), -EBUSY); + + /* ...get message buffer */ + m = xf_buffer_data(b); + + /* ...fill-in message parameters */ + //m->src = __XF_PORT_SPEC2(src->id, src_port); + m->dst = __XF_PORT_SPEC2(dst->id, dst_port); + m->alloc_number = num; + m->alloc_size = size; + m->alloc_align = align; + + /* ...set command parameters */ + msg.id = __XF_MSG_ID(__XF_AP_PROXY(proxy->core), __XF_PORT_SPEC2(src->id, src_port)); + msg.opcode = XF_ROUTE; + msg.length = sizeof(*m); + msg.buffer = m; + + /* ...synchronously execute command on remote DSP */ + XF_CHK_API(xf_proxy_cmd_exec(proxy, &msg)); + + /* ...return buffer to proxy */ + xf_buffer_put(b); + + /* ...check result is successfull */ + XF_CHK_ERR(msg.opcode == (u32) XF_ROUTE, -ENOMEM); + + /* ...port binding completed */ + TRACE(GRAPH, _b("[%p]:%u bound to [%p]:%u"), src, src_port, dst, dst_port); + + return 0; +} + +/* ...port unbinding function */ +int xf_unroute(xf_handle_t *src, u32 src_port) +{ + xf_proxy_t *proxy = src->proxy; + xf_buffer_t *b; + xf_unroute_port_msg_t *m; + xf_user_msg_t msg; + int r; + + /* ...get control buffer */ + XF_CHK_ERR(b = xf_buffer_get(proxy->aux), -EBUSY); + + /* ...get message buffer */ + m = xf_buffer_data(b); + + /* ...fill-in message parameters */ + //m->src = __XF_PORT_SPEC2(src->id, src_port); + + /* ...set command parameters */ + msg.id = __XF_MSG_ID(__XF_AP_PROXY(proxy->core), __XF_PORT_SPEC2(src->id, src_port)); + msg.opcode = XF_UNROUTE; + msg.length = sizeof(*m); + msg.buffer = m; + + /* ...synchronously execute command on remote DSP */ + if ((r = xf_proxy_cmd_exec(proxy, &msg)) != 0) + { + TRACE(ERROR, _x("Command failed: %d"), r); + goto out; + } + else if (msg.opcode != (u32) XF_UNROUTE) + { + TRACE(ERROR, _x("Port unbinding failed")); + r = -EBADFD; + goto out; + } + + /* ...port binding completed */ + TRACE(GRAPH, _b("[%p]:%u unbound"), src, src_port); + +out: + /* ...return buffer to proxy */ + xf_buffer_put(b); + + return r; +} + +/* ...send a command message to component */ +int xf_command(xf_handle_t *handle, u32 port, u32 opcode, void *buffer, u32 length) +{ + xf_proxy_t *proxy = handle->proxy; + xf_proxy_msg_t msg; + + /* ...fill-in message parameters */ + msg.id = __XF_MSG_ID(__XF_AP_CLIENT(proxy->core, handle->client), __XF_PORT_SPEC2(handle->id, port)); + msg.opcode = opcode; + msg.length = length; + XF_CHK_ERR((msg.address = xf_proxy_b2a(proxy, buffer)) != XF_PROXY_BADADDR, -EINVAL); + + TRACE(CMD, _b("[%p]:[%08x]:(%08x,%u,%p)"), handle, msg.id, opcode, length, buffer); + + /* ...pass command to IPC layer */ + return XF_CHK_API(xf_ipc_send(&proxy->ipc, &msg, buffer)); +} + +/******************************************************************************* + * Buffer pool API + ******************************************************************************/ + +/* ...allocate buffer pool */ +int xf_pool_alloc(xf_proxy_t *proxy, u32 number, u32 length, xf_pool_type_t type, xf_pool_t **pool, s32 id, + xaf_mem_malloc_fxn_t xaf_malloc, xaf_mem_free_fxn_t xaf_free) +{ + xf_pool_t *p; + xf_buffer_t *b; + void *data; + int r; + + /* ...unused arg */ + (void) type; + + /* ...basic sanity checks; number of buffers is positive */ + XF_CHK_ERR(number > 0, -EINVAL); + + /* ...get properly aligned buffer length */ + length = (length + XF_PROXY_ALIGNMENT - 1) & ~(XF_PROXY_ALIGNMENT - 1); + + /* ...allocate data structure */ + p = xaf_malloc(offset_of(xf_pool_t, buffer) + number * sizeof(xf_buffer_t), id); + XF_CHK_ERR(p, -ENOMEM); + + /* ...issue memory pool allocation request to remote DSP */ + xf_proxy_lock(proxy); + r = xf_proxy_buffer_alloc(proxy, number * length, &p->p); + xf_proxy_unlock(proxy); + + /* ...if operation is failed, do cleanup */ + if (r < 0) + { + TRACE(ERROR, _x("failed to allocate buffer: %d"), r); + xaf_free(p, id); + return r; + } + else + { + /* ...set pool parameters */ + p->number = number, p->length = length; + p->proxy = proxy; + } + + /* ...create individual buffers and link them into free list */ + for (p->free = b = &p->buffer[0], data = p->p; number > 0; number--, b++) + { + /* ...set address of the buffer (no length there) */ + b->address = data; + + /* ...file buffer into the free list */ + b->link.next = b + 1; + + /* ...advance data pointer in contiguous buffer */ + data = (unsigned char *) data + length; + } + + /* ...terminate list of buffers (not too good - tbd) */ + b[-1].link.next = NULL; + + TRACE(BUFFER, _b("[%p]: pool[%p] created: %u * %u"), proxy, p, p->number, p->length); + + /* ...return buffer pointer */ + *pool = p; + + return 0; +} + +/* ...buffer pool destruction */ +void xf_pool_free(xf_pool_t *pool, s32 id, xaf_mem_free_fxn_t xaf_free) +{ + xf_proxy_t *proxy = pool->proxy; + + /* ...check buffers are all freed - tbd */ + + /* ...use global proxy lock for pool operations protection */ + xf_proxy_lock(proxy); + + /* ...release allocated buffer on remote DSP */ + xf_proxy_buffer_free(proxy, pool->p, pool->length * pool->number); + + /* ...release global proxy lock */ + xf_proxy_unlock(proxy); + + /* ...deallocate pool structure itself */ + xaf_free(pool, id); + + TRACE(BUFFER, _b("[%p]::pool[%p] destroyed"), proxy, pool); +} + +/* ...get new buffer from a pool */ +xf_buffer_t * xf_buffer_get(xf_pool_t *pool) +{ + xf_buffer_t *b; + + /* ...use global proxy lock for pool operations protection */ + xf_proxy_lock(pool->proxy); + + /* ...take buffer from a head of the free list */ + if ((b = pool->free) != NULL) + { + /* ...advance free list head */ + pool->free = b->link.next, b->link.pool = pool; + + TRACE(BUFFER, _b("pool[%p]::get[%p]"), pool, b); + } + + xf_proxy_unlock(pool->proxy); + + return b; +} + +/* ...return buffer back to pool */ +void xf_buffer_put(xf_buffer_t *buffer) +{ + xf_pool_t *pool = buffer->link.pool; + + /* ...use global proxy lock for pool operations protection */ + xf_proxy_lock(pool->proxy); + + /* ...put buffer back to a pool */ + buffer->link.next = pool->free, pool->free = buffer; + + TRACE(BUFFER, _b("pool[%p]::put[%p]"), pool, buffer); + + xf_proxy_unlock(pool->proxy); +} diff --git a/hifi/xaf/host-apf/proxy/xf-trace.c b/hifi/xaf/host-apf/proxy/xf-trace.c new file mode 100644 index 00000000..fb902676 --- /dev/null +++ b/hifi/xaf/host-apf/proxy/xf-trace.c @@ -0,0 +1,90 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#include "xf.h" +#include <sys/time.h> + +#if XF_TRACE +/******************************************************************************* + * Local data definitions + ******************************************************************************/ + +/* ...tracing lock */ +static pthread_mutex_t xf_trace_mutex; + +/******************************************************************************* + * Tracing facility + ******************************************************************************/ + +/* ...timestamp function */ +static u32 xf_timenow(void) +{ + struct timeval tv; + + /* ...get current time value */ + gettimeofday(&tv, NULL); + + /* ...wrap over every 100 seconds */ + return (u32)((tv.tv_sec % 100) * 1000000 + tv.tv_usec); +} + +/* ...tracing initialization */ +void xf_trace_init(const char *banner) +{ + /* ...initialize tracing lock */ + pthread_mutex_init(&xf_trace_mutex, NULL); + + /* ...output banner */ + xf_trace(banner); +} + +/* ...tracing primitive */ +int xf_trace(const char *format, ...) +{ + va_list args; + static char buf[256]; + char *b = buf; + + /* ...get global tracing lock */ + pthread_mutex_lock(&xf_trace_mutex); + + /* ...output timestamp */ + b += sprintf(b, "[%08u] ", xf_timenow()); + + /* ...output format string */ + va_start(args, format); + b += vsprintf(b, format, args); + va_end(args); + + /* ...put terminator */ + *b = '\0'; + + /* ...output prepared string */ + __xf_puts(buf); + + /* ...release tracing lock */ + pthread_mutex_unlock(&xf_trace_mutex); + + return 0; +} + +#endif /* XF_TRACE */ diff --git a/hifi/xaf/host-apf/tools/dhifimesg b/hifi/xaf/host-apf/tools/dhifimesg Binary files differnew file mode 100755 index 00000000..88294880 --- /dev/null +++ b/hifi/xaf/host-apf/tools/dhifimesg diff --git a/hifi/xaf/host-apf/utest/include/xaf-mem.h b/hifi/xaf/host-apf/utest/include/xaf-mem.h new file mode 100644 index 00000000..68838035 --- /dev/null +++ b/hifi/xaf/host-apf/utest/include/xaf-mem.h @@ -0,0 +1,49 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#define MEM_NUM_MEM_ALLOC 32 + +typedef struct { + void* heap_ptr; + int size; +}mem_obj_dev_t; + +typedef struct { + void* heap_ptr; + int size; +}mem_obj_comp_t; + +typedef struct { + mem_obj_dev_t mem_dev[MEM_NUM_MEM_ALLOC]; + mem_obj_comp_t mem_comp[MEM_NUM_MEM_ALLOC]; + int num_malloc_dev; + int num_malloc_comp; + int persi_mem_dev; + int persi_mem_comp; +}mem_obj_t; + +void* mem_malloc(int size, int id); +void mem_free(void * heap_ptr, int id); +void* mem_init(); +void mem_exit(); +int mem_get_alloc_size(mem_obj_t* mem_handle, int id); + diff --git a/hifi/xaf/host-apf/utest/include/xaf-utils-test.h b/hifi/xaf/host-apf/utest/include/xaf-utils-test.h new file mode 100644 index 00000000..e6c2ce03 --- /dev/null +++ b/hifi/xaf/host-apf/utest/include/xaf-utils-test.h @@ -0,0 +1,37 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#include <stdio.h> + +#include "xf.h" +#include "xaf-api.h" +#include "xa_type_def.h" + +#include "xaf-mem.h" + +/* exported global variables */ +extern int audio_frmwk_buf_size; +extern int audio_comp_buf_size; + +int print_mem_mcps_info(mem_obj_t* mem_handle, int num_comp); +int print_banner(char *app_name); + diff --git a/hifi/xaf/host-apf/utest/xaf-dec-mix-test.c b/hifi/xaf/host-apf/utest/xaf-dec-mix-test.c new file mode 100644 index 00000000..28ac8767 --- /dev/null +++ b/hifi/xaf/host-apf/utest/xaf-dec-mix-test.c @@ -0,0 +1,421 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#define MODULE_TAG UTEST + +#include "xaf-utils-test.h" + +#include "audio/xa_vorbis_dec_api.h" +#include "audio/xa-mixer-api.h" +#include "audio/xa-audio-decoder-api.h" + +#include "xa_playback.h" + +#define PRINT_USAGE do { fprintf(stderr, "\nUsage: %s <input-file1> <input-file2>\n", argv[0]); \ + fprintf(stderr, " Only .ogg and .pcm files are supported. \n"); \ + fprintf(stderr, " Playback is configured @ 48kHz, 2 ch, 16 bits pcm. \n"); \ + fprintf(stderr, " <input-file2> is optional. \n"); \ + fprintf(stderr, " pcm output is written to dec-mix-out.pcm, by default. \n\n"); \ + } while(0) + +#define MAX_INP_STRMS 2 +#define NUM_COMP_IN_GRAPH 3 + +/* ...global variables */ +int g_pthread_exit_code=0x12345678; + +/* ...playback format */ +xaf_format_t pb_format; + +/* ...playback device parameters */ +void *pb_handle = NULL; + +void thread_exit_handler(int sig) +{ + /* ...unused arg */ + (void) sig; + + pthread_exit(0); +} + +static int vorbis_setup(void *p_decoder) +{ + int param[2]; + + /* 1: Raw decode, 0: Ogg decode */ + param[0] = XA_VORBISDEC_CONFIG_PARAM_RAW_VORBIS_FILE_MODE; + param[1] = 0; + + XF_CHK_API(xaf_comp_set_config(p_decoder, 1, ¶m[0])); + + return 0; +} + +static int pcm_setup(void *p_pcm) +{ + int param[6]; + + param[0] = XA_CODEC_CONFIG_PARAM_SAMPLE_RATE; + param[1] = pb_format.sample_rate; + param[2] = XA_CODEC_CONFIG_PARAM_CHANNELS; + param[3] = pb_format.channels; + param[4] = XA_CODEC_CONFIG_PARAM_PCM_WIDTH; + param[5] = pb_format.pcm_width; + + XF_CHK_API(xaf_comp_set_config(p_pcm, 3, ¶m[0])); + + return 0; +} + +static int mixer_setup(void *p_decoder, xaf_format_t *p_format) +{ + int param[6]; + + param[0] = XA_MIXER_CONFIG_PARAM_SAMPLE_RATE; + param[1] = p_format->sample_rate; + param[2] = XA_MIXER_CONFIG_PARAM_CHANNELS; + param[3] = p_format->channels; + param[4] = XA_MIXER_CONFIG_PARAM_PCM_WIDTH; + param[5] = p_format->pcm_width; + + XF_CHK_API(xaf_comp_set_config(p_decoder, 3, ¶m[0])); + + return 0; +} + +static int consume_output(void *p_buf, int buf_length, void *p_output) +{ + XAF_CHK_PTR(p_buf); + XAF_CHK_PTR(p_output); + +#if !defined BOARD + FILE *fp = p_output; + fwrite(p_buf, 1, buf_length, fp); + + if (xa_playback_buf(pb_handle, p_buf, buf_length)) { + TRACE(ERROR, _b("Playback Failed \n")); + return -1; + } +#else +#endif + return 0; +} + +static int read_input(void *p_buf, int buf_length, int *read_length, void *p_input) +{ + XAF_CHK_PTR(p_buf); + XAF_CHK_PTR(read_length); + XAF_CHK_PTR(p_input); + +#if !defined BOARD + FILE *fp = p_input; + *read_length = fread(p_buf, 1, buf_length, fp); +#else +#endif + return 0; +} + +static int comp_process_entry(void *arg) +{ + void *p_comp; + void *p_input, *p_output; + xaf_comp_status comp_status; + xaf_info_t comp_info; + int input_over, read_length; + void * (*arg_arr)[3]; + void *pg_pthread_exit_code = (void*)&g_pthread_exit_code; + + XAF_CHK_PTR(arg); + + arg_arr = arg; + p_comp = (*arg_arr)[0]; + p_input = (*arg_arr)[1]; + p_output = (*arg_arr)[2]; + input_over = 0; + + XF_CHK_API(xaf_comp_process(NULL, p_comp, NULL, 0, XAF_EXEC_FLAG)); + + while (1) + { + XF_CHK_API(xaf_comp_get_status(NULL, p_comp, &comp_status, &comp_info)); + + if (comp_status == XAF_EXEC_DONE) break; + + if (comp_status == XAF_NEED_INPUT && !input_over) + { + void *p_buf = (void *) comp_info.buf; + int size = comp_info.length; + + XF_CHK_API(read_input(p_buf, size, &read_length, p_input)); + + if (read_length) + XF_CHK_API(xaf_comp_process(NULL, p_comp, (void *)comp_info.buf, read_length, XAF_INPUT_READY_FLAG)); + else + { + XF_CHK_API(xaf_comp_process(NULL, p_comp, NULL, 0, XAF_INPUT_OVER_FLAG)); + input_over = 1; + } + } + + if (comp_status == XAF_OUTPUT_READY) + { + void *p_buf = (void *) comp_info.buf; + int size = comp_info.length; + + XF_CHK_API(consume_output(p_buf, size, p_output)); + XF_CHK_API(xaf_comp_process(NULL, p_comp, (void *)comp_info.buf, comp_info.length, XAF_NEED_OUTPUT_FLAG)); + } + } + pthread_exit(pg_pthread_exit_code); + + return 0; +} + +int main(int argc, const char **argv) +{ + void *p_adev = NULL; + void *p_decoder[MAX_INP_STRMS]; + void *p_mixer; + mem_obj_t* mem_handle; + int num_comp = NUM_COMP_IN_GRAPH; + + xaf_comp_status dec_status; + xaf_info_t comp_info; + + void *p_input[MAX_INP_STRMS], *p_output; + + xf_id_t dec_id[MAX_INP_STRMS]; + int (*dec_setup[MAX_INP_STRMS])(void *p_comp); + + pthread_t dec_thread[MAX_INP_STRMS]; + pthread_t mixer_thread; + void *dec_thread_args[MAX_INP_STRMS][3]; + void *mixer_thread_args[3]; + + const char *ext; + FILE *fp, *ofp; + void *dec_inbuf[MAX_INP_STRMS][2]; + int buf_length = XAF_INBUF_SIZE; + int read_length; + int input_over = 0; + int i, j; + int num_strms; + + unsigned int card = 0; + unsigned int device = 0; + unsigned int period_size = 1024; + unsigned int period_count = 4; + + int pthread_error; + void *pthread_exit_code[3]; + + struct sigaction actions; + memset(&actions, 0, sizeof(actions)); + sigemptyset(&actions.sa_mask); + actions.sa_flags = 0; + actions.sa_handler = thread_exit_handler; + sigaction(SIGUSR1,&actions,NULL); + + /* ...initialize playback format */ + pb_format.sample_rate = 48000; + pb_format.channels = 2; + pb_format.pcm_width = 16; + + audio_frmwk_buf_size = 0; //unused + audio_comp_buf_size = 0; //unused + + print_banner("\'Audio decoder(PCM/Ogg-Vorbis) + Mixer\'"); + + /* ...initialize tracing facility */ + TRACE_INIT("Xtensa Audio Framework - Sample Application"); + +#if !defined BOARD + /* ...check input arguments */ + if (argc < 2 || argc > (MAX_INP_STRMS+1)) + { + TRACE(ERROR, _b("Usage: ./xaf-test <infile1> <infile2>\n")); + PRINT_USAGE; + return 0; + } + + argc--; + for (i=0; i<argc; i++) + { + ext = strrchr(argv[i+1], '.'); + if (!ext) + { + PRINT_USAGE; + return 0; + } + ext++; + if (!strcmp(ext, "pcm")) { + dec_id[i] = "audio-decoder/pcm"; + dec_setup[i] = pcm_setup; + } + else if (!strcmp(ext, "ogg")) { + dec_id[i] = "audio-decoder/vorbis"; + dec_setup[i] = vorbis_setup; + } + else { + TRACE(ERROR, _x("Unknown Decoder Extension '%s'"), ext); + PRINT_USAGE; + exit(-1); + } + /* ...open file */ + if ((fp = fopen(argv[i+1], "rb")) == NULL) + { + TRACE(ERROR, _x("Failed to open '%s': %d"), argv[i+1], errno); + exit(-1); + } + p_input[i] = fp; + } + num_strms = i; + + if ((ofp = fopen("dec-mix-out.pcm", "wb")) == NULL) + { + TRACE(ERROR, _x("Failed to open '%s': %d"), "dec-mix-out.pcm", errno); + exit(-1); + } + p_output = ofp; +#endif + + mem_handle = mem_init(); //initialize memory handler + + XF_CHK_API(xaf_adev_open(&p_adev, audio_frmwk_buf_size, audio_comp_buf_size, mem_malloc, mem_free)); + + /* ...create mixer component */ + XF_CHK_API(xaf_comp_create(p_adev, &p_mixer, "mixer", 0, 1, NULL, XAF_MIXER)); + XF_CHK_API(mixer_setup(p_mixer, &pb_format)); + + for (i=0; i<num_strms; i++) + { + /* ...create decoder component */ + XF_CHK_API(xaf_comp_create(p_adev, &p_decoder[i], dec_id[i], 2, 0, &dec_inbuf[i][0], XAF_DECODER)); + XF_CHK_API((dec_setup[i])(p_decoder[i])); + + /* ...start decoder component */ + XF_CHK_API(xaf_comp_process(p_adev, p_decoder[i], NULL, 0, XAF_START_FLAG)); + + /* ...feed input to decoder component */ + for (j=0; j<2; j++) + { + XF_CHK_API(read_input(dec_inbuf[i][j], buf_length, &read_length, p_input[i])); + + if (read_length) + XF_CHK_API(xaf_comp_process(p_adev, p_decoder[i], dec_inbuf[i][j], read_length, XAF_INPUT_READY_FLAG)); + else + break; + } + + /* ...initialization loop */ + while (1) + { + XF_CHK_API(xaf_comp_get_status(p_adev, p_decoder[i], &dec_status, &comp_info)); + + if (dec_status == XAF_INIT_DONE || dec_status == XAF_EXEC_DONE) break; + + if (dec_status == XAF_NEED_INPUT && !input_over) + { + void *p_buf = (void *) comp_info.buf; + int size = comp_info.length; + + XF_CHK_API(read_input(p_buf, size, &read_length, p_input[i])); + + if (read_length) + XF_CHK_API(xaf_comp_process(p_adev, p_decoder[i], p_buf, read_length, XAF_INPUT_READY_FLAG)); + else + break; + } + } + + if (dec_status != XAF_INIT_DONE) + { + TRACE(ERROR, _x("Failed to init")); + exit(-1); + } + + XF_CHK_API(xaf_connect(p_decoder[i], p_mixer, 4)); + } + + XF_CHK_API(xaf_comp_process(p_adev, p_mixer, NULL, 0, XAF_START_FLAG)); + XF_CHK_API(xaf_comp_get_status(p_adev, p_mixer, &dec_status, &comp_info)); + + if (dec_status != XAF_INIT_DONE) + { + TRACE(ERROR, _x("Failed to init")); + exit(-1); + } + + /* ...open playback device */ + pb_handle = xa_playback_open(card, device, pb_format.channels, pb_format.sample_rate, + pb_format.pcm_width, period_size, period_count); + if (!pb_handle) { + TRACE(ERROR, _x("Playback open error\n")); + return -1; + } + + for (i=0; i<num_strms; i++) + { + dec_thread_args[i][0] = p_decoder[i]; + dec_thread_args[i][1] = p_input[i]; + dec_thread_args[i][2] = p_output; + pthread_create(&dec_thread[i], 0, (void *(*)(void*))&comp_process_entry, dec_thread_args[i]); + } + + mixer_thread_args[0] = p_mixer; + mixer_thread_args[1] = NULL; + mixer_thread_args[2] = p_output; + pthread_create(&mixer_thread, 0, (void *(*)(void*))comp_process_entry, &mixer_thread_args[0]); + + for (i=0; i<num_strms; i++) + { + pthread_error = pthread_join(dec_thread[i], (void **) &pthread_exit_code[i]); + if(pthread_error) + { + TRACE(ERROR, _b("decode thread %d join error:%x\n"), i, pthread_error); + } + } + pthread_error = pthread_join(mixer_thread, (void **) &pthread_exit_code[i]); + if(pthread_error) + { + TRACE(ERROR, _b("mixer thread join error:%x\n"), pthread_error); + } + + for (i=0; i<num_strms; i++) + { + XF_CHK_API(xaf_comp_delete(p_decoder[i])); + if (p_input[i]) fclose(p_input[i]); + } + XF_CHK_API(xaf_comp_delete(p_mixer)); + + /* ...exec done, clean-up */ + xa_playback_close(pb_handle); + + XF_CHK_API(xaf_adev_close(p_adev, 0 /*unused*/)); + if (p_output) fclose(p_output); + + mem_exit(); + XF_CHK_API(print_mem_mcps_info(mem_handle, num_comp)); + + return 0; +} + diff --git a/hifi/xaf/host-apf/utest/xaf-dec-test.c b/hifi/xaf/host-apf/utest/xaf-dec-test.c new file mode 100644 index 00000000..7e5d050a --- /dev/null +++ b/hifi/xaf/host-apf/utest/xaf-dec-test.c @@ -0,0 +1,344 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ + +#define MODULE_TAG UTEST + +#include "xaf-utils-test.h" + +#include "audio/xa_vorbis_dec_api.h" +#include "audio/xa-audio-decoder-api.h" + +#include "xa_playback.h" + +#define PRINT_USAGE do { fprintf(stderr, "\nUsage: %s <input-file>\n", argv[0]); \ + fprintf(stderr, " Only .ogg and .pcm files are supported. \n"); \ + fprintf(stderr, " Playback is configured @ 48kHz, 2 ch, 16 bits pcm. \n"); \ + fprintf(stderr, " pcm output is written to dec-out.pcm, by default. \n\n"); \ + } while(0) + + +#define NUM_COMP_IN_GRAPH 1 + +void *p_input, *p_output; +pthread_t dec_thread; + +FILE *fp, *ofp=NULL; +xaf_info_t comp_info; +void *pb_handle = NULL; +unsigned int card = 0; +unsigned int device = 0; +unsigned int period_size = 1024; +unsigned int period_count = 4; + +/* ...playback format */ +xaf_format_t pb_format; + +int g_pthread_exit_code=0x12345678; + +void thread_exit_handler(int sig) +{ + /* ...unused arg */ + (void) sig; + + pthread_exit(0); +} + +static int vorbis_setup(void *p_decoder) +{ + int param[2]; + + /* 1: Raw decode, 0: Ogg decode */ + param[0] = XA_VORBISDEC_CONFIG_PARAM_RAW_VORBIS_FILE_MODE; + param[1] = 0; + + XF_CHK_API(xaf_comp_set_config(p_decoder, 1, ¶m[0])); + + return 0; +} + +static int pcm_setup(void *p_pcm) +{ + int param[6]; + + param[0] = XA_CODEC_CONFIG_PARAM_SAMPLE_RATE; + param[1] = pb_format.sample_rate; + param[2] = XA_CODEC_CONFIG_PARAM_CHANNELS; + param[3] = pb_format.channels; + param[4] = XA_CODEC_CONFIG_PARAM_PCM_WIDTH; + param[5] = pb_format.pcm_width; + + XF_CHK_API(xaf_comp_set_config(p_pcm, 3, ¶m[0])); + + return 0; +} + +static int consume_output(void *p_buf, int buf_length, void *p_output) +{ + XAF_CHK_PTR(p_buf); + XAF_CHK_PTR(p_output); + +#if !defined BOARD + FILE *fp = p_output; + fwrite(p_buf, 1, buf_length, fp); + + if (xa_playback_buf(pb_handle, p_buf, buf_length)) { + TRACE(ERROR, _b("Playback Failed \n")); + return -1; + } +#else +#endif + return 0; +} + +static int read_input(void *p_buf, int buf_length, int *read_length, void *p_input) +{ + XAF_CHK_PTR(p_buf); + XAF_CHK_PTR(read_length); + XAF_CHK_PTR(p_input); + +#if !defined BOARD + FILE *fp = p_input; + *read_length = fread(p_buf, 1, buf_length, fp); +#else +#endif + return 0; +} + +static int comp_process_entry(void *arg) +{ + void *p_comp; + xaf_comp_status comp_status; + int input_over, read_length; + void *pg_pthread_exit_code = (void*)&g_pthread_exit_code; + + XAF_CHK_PTR(arg); + XAF_CHK_PTR(p_input); + XAF_CHK_PTR(p_output); + + p_comp = arg; + input_over = 0; + + XF_CHK_API(xaf_comp_process(NULL, p_comp, NULL, 0, XAF_EXEC_FLAG)); + + while (1) + { + + XF_CHK_API(xaf_comp_get_status(NULL, p_comp, &comp_status, &comp_info)); + + if (comp_status == XAF_EXEC_DONE) break; + + if (comp_status == XAF_NEED_INPUT && !input_over) + { + void *p_buf = (void *)comp_info.buf; + int size = comp_info.length; + + XF_CHK_API(read_input(p_buf, size, &read_length, p_input)); + + if (read_length) + XF_CHK_API(xaf_comp_process(NULL, p_comp, (void *)comp_info.buf, read_length, XAF_INPUT_READY_FLAG)); + else + { + XF_CHK_API(xaf_comp_process(NULL, p_comp, NULL, 0, XAF_INPUT_OVER_FLAG)); + input_over = 1; + } + } + + if (comp_status == XAF_OUTPUT_READY) + { + void *p_buf = (void *)comp_info.buf; + int size = comp_info.length; + + XF_CHK_API(consume_output(p_buf, size, p_output)); + XF_CHK_API(xaf_comp_process(NULL, p_comp, (void *)comp_info.buf, comp_info.length, XAF_NEED_OUTPUT_FLAG)); + } + } + pthread_exit(pg_pthread_exit_code); + + return 0; +} + + +int main(int argc, const char **argv) +{ + void *p_adev = NULL; + void *p_decoder; + mem_obj_t* mem_handle; + int num_comp = NUM_COMP_IN_GRAPH; + + xaf_comp_status dec_status; + void *dec_inbuf[2]; + int buf_length = XAF_INBUF_SIZE; + int read_length; + int i; + + xf_id_t dec_id; + int (*dec_setup)(void *p_comp); + const char *ext; + int pthread_error; + void *pthread_exit_code; + + struct sigaction actions; + memset(&actions, 0, sizeof(actions)); + sigemptyset(&actions.sa_mask); + actions.sa_flags = 0; + actions.sa_handler = thread_exit_handler; + sigaction(SIGUSR1,&actions,NULL); + + /* ...initialize playback format */ + pb_format.sample_rate = 48000; + pb_format.channels = 2; + pb_format.pcm_width = 16; + + audio_frmwk_buf_size = 0; //unused + audio_comp_buf_size = 0; //unused + + print_banner("\'Audio decoder(PCM/Ogg-Vorbis)\'"); + + /* ...initialize tracing facility */ + TRACE_INIT("Xtensa Audio Framework - Sample Application"); + +#if !defined BOARD + /* ...check input arguments */ + if (argc != 2) + { + TRACE(ERROR, _b("Usage: ./xaf-test <input-file-.ogg/.pcm>\n")); + PRINT_USAGE; + return 0; + } + + + ext = strrchr(argv[1], '.'); + if (!ext) + { + PRINT_USAGE; + return 0; + } + ext++; + if (!strcmp(ext, "pcm")) { + dec_id = "audio-decoder/pcm"; + dec_setup = pcm_setup; + } + else if (!strcmp(ext, "ogg")) { + dec_id = "audio-decoder/vorbis"; + dec_setup = vorbis_setup; + } + else { + TRACE(ERROR, _x("Unknown Decoder Extension '%s'"), ext); + PRINT_USAGE; + exit(-1); + } + + /* ...open file */ + if ((fp = fopen(argv[1], "rb")) == NULL) + { + TRACE(ERROR, _x("Failed to open '%s': %d"), argv[1], errno); + exit(-1); + } + if ((ofp = fopen("dec-out.pcm", "wb")) == NULL) + { + TRACE(ERROR, _x("Failed to open '%s': %d"), "dec-out.pcm", errno); + exit(-1); + } + p_input = fp; + p_output = ofp; +#endif + + mem_handle = mem_init(); //initialize memory handler + + XF_CHK_API(xaf_adev_open(&p_adev, audio_frmwk_buf_size, audio_comp_buf_size, mem_malloc, mem_free)); + + /* ...create decoder component */ + XF_CHK_API(xaf_comp_create(p_adev, &p_decoder, dec_id, 2, 1, &dec_inbuf[0], XAF_DECODER)); + XF_CHK_API(dec_setup(p_decoder)); + + /* ...start decoder component */ + XF_CHK_API(xaf_comp_process(p_adev, p_decoder, NULL, 0, XAF_START_FLAG)); + + /* ...feed input to decoder component */ + for (i=0; i<2; i++) + { + XF_CHK_API(read_input(dec_inbuf[i], buf_length, &read_length, p_input)); + + if (read_length) + XF_CHK_API(xaf_comp_process(p_adev, p_decoder, dec_inbuf[i], read_length, XAF_INPUT_READY_FLAG)); + else + break; + } + + /* ...initialization loop */ + while (1) + { + XF_CHK_API(xaf_comp_get_status(p_adev, p_decoder, &dec_status, &comp_info)); + + if (dec_status == XAF_INIT_DONE || dec_status == XAF_EXEC_DONE) + { + pb_handle = xa_playback_open(card, device, pb_format.channels, pb_format.sample_rate, + pb_format.pcm_width, period_size, period_count); + if (!pb_handle) { + TRACE(ERROR, _x("Playback open error\n")); + return -1; + } + + break; + } + + if (dec_status == XAF_NEED_INPUT) + { + void *p_buf = (void *) comp_info.buf; + int size = comp_info.length; + + XF_CHK_API(read_input(p_buf, size, &read_length, p_input)); + + if (read_length) + XF_CHK_API(xaf_comp_process(p_adev, p_decoder, p_buf, read_length, XAF_INPUT_READY_FLAG)); + else + break; + } + } + + if (dec_status != XAF_INIT_DONE) + { + TRACE(ERROR, _x("Failed to init")); + exit(-1); + } + + pthread_create(&dec_thread, 0, (void *(*)(void *))&comp_process_entry, p_decoder); + + pthread_error = pthread_join(dec_thread, (void **) &pthread_exit_code); + if(pthread_error) + { + TRACE(ERROR, _b("decode thread join error:%x\n"), pthread_error); + } + + /* ...exec done, clean-up */ + XF_CHK_API(xaf_comp_delete(p_decoder)); + xa_playback_close(pb_handle); + XF_CHK_API(xaf_adev_close(p_adev, 0 /*unused*/)); + if (fp) fclose(fp); + if (ofp) fclose(ofp); + + mem_exit(); + XF_CHK_API(print_mem_mcps_info(mem_handle, num_comp)); + + return 0; +} + diff --git a/hifi/xaf/host-apf/utest/xaf-mem-test.c b/hifi/xaf/host-apf/utest/xaf-mem-test.c new file mode 100644 index 00000000..1343c904 --- /dev/null +++ b/hifi/xaf/host-apf/utest/xaf-mem-test.c @@ -0,0 +1,150 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ +#include <stdio.h> +#include <stdlib.h> + +#include "xa_type_def.h" + +/* ...debugging facility */ +#include "xaf-utils-test.h" + +mem_obj_t g_mem_obj; + +void* mem_malloc(int size, int id) +{ + int index; + void* heap_ptr = NULL; + + if(id == XAF_MEM_ID_DEV) + { + index = g_mem_obj.num_malloc_dev; + if(index >= MEM_NUM_MEM_ALLOC-1) + { + heap_ptr = NULL; + } + else + { + heap_ptr = malloc(size); + g_mem_obj.num_malloc_dev++; + g_mem_obj.mem_dev[index].heap_ptr = heap_ptr; + g_mem_obj.mem_dev[index].size = size; + g_mem_obj.persi_mem_dev += size; + } + } + else if(id == XAF_MEM_ID_COMP) + { + index = g_mem_obj.num_malloc_comp; + if(index >= MEM_NUM_MEM_ALLOC-1) + { + heap_ptr = NULL; + } + else + { + heap_ptr = malloc(size); + g_mem_obj.num_malloc_comp++; + g_mem_obj.mem_comp[index].heap_ptr = heap_ptr; + g_mem_obj.mem_comp[index].size = size; + g_mem_obj.persi_mem_comp += size; + } + } + return heap_ptr; +} + +int get_heap_ptr_index(void* p_heap, int id) +{ + int idx; + + idx = -1; + if(id == XAF_MEM_ID_DEV) + { + for(idx = 0; idx < MEM_NUM_MEM_ALLOC; idx++) + { + if(g_mem_obj.mem_dev[idx].heap_ptr == p_heap) + break; + } + } + + else if(id == XAF_MEM_ID_COMP) + { + for(idx = 0; idx < MEM_NUM_MEM_ALLOC; idx++) + { + if(g_mem_obj.mem_comp[idx].heap_ptr == p_heap) + break; + } + } + return idx; +} + +void mem_free(void * heap_ptr, int id) +{ + int index; + int size; + + index = get_heap_ptr_index(heap_ptr, id); + + if (index != -1) + { + if(id == XAF_MEM_ID_DEV) + { + size=g_mem_obj.mem_dev[index].size; + g_mem_obj.mem_dev[index].size = 0; + g_mem_obj.num_malloc_dev--; + free(heap_ptr); + g_mem_obj.mem_dev[index].heap_ptr = NULL; + } + else if(id == XAF_MEM_ID_COMP) + { + size=g_mem_obj.mem_comp[index].size; + g_mem_obj.mem_comp[index].size = 0; + g_mem_obj.num_malloc_comp--; + free(heap_ptr); + g_mem_obj.mem_comp[index].heap_ptr = NULL; + } + } + return; +} + +int mem_get_alloc_size(mem_obj_t* pmem_handle, int id) +{ + int mem_size = 0; + if(id == XAF_MEM_ID_DEV) + mem_size = pmem_handle->persi_mem_dev; + else if(id == XAF_MEM_ID_COMP) + mem_size = pmem_handle->persi_mem_comp; + return mem_size; +} + +void* mem_init() +{ + void* ptr; + ptr = &g_mem_obj; + return ptr; +} + +void mem_exit() +{ + if((g_mem_obj.num_malloc_dev != 0)||(g_mem_obj.num_malloc_comp != 0)) + { + fprintf(stdout,"Memory leaks\n"); + } + return; +} diff --git a/hifi/xaf/host-apf/utest/xaf-utils-test.c b/hifi/xaf/host-apf/utest/xaf-utils-test.c new file mode 100644 index 00000000..79c6710d --- /dev/null +++ b/hifi/xaf/host-apf/utest/xaf-utils-test.c @@ -0,0 +1,69 @@ +/******************************************************************************* +* Copyright (C) 2018 Cadence Design Systems, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to use this Software with Cadence processor cores only and +* not with any other processors and platforms, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************************/ +#include <stdio.h> +#include <string.h> + +#include "xaf-utils-test.h" + +int audio_frmwk_buf_size; +int audio_comp_buf_size; + +int print_banner(char *app_name) +{ + /* + XAF_CHK_PTR(ver_info[0], "print_verinfo"); + XAF_CHK_PTR(ver_info[1], "print_verinfo"); + XAF_CHK_PTR(ver_info[2], "print_verinfo"); + */ + + fprintf(stdout, "******************************************************************************\n"); + fprintf(stdout, "Cadence Audio Framework (Hosted) : %s \n",app_name); + fprintf(stdout, "Copyright (c) 2018 Cadence Design Systems, Inc.\n"); + /*fprintf(stdout, "Lib Name : %s\n", ver_info[0]); + fprintf(stdout, "Lib Version : %s\n", ver_info[1]); + fprintf(stdout, "API Version : %s\n", ver_info[2]);*/ + fprintf(stdout, "******************************************************************************\n"); + + return 0; +} + +int print_mem_mcps_info(mem_obj_t* mem_handle, int num_comp) +{ + int tot_dev_mem_size, tot_comp_mem_size, tot_size; + + /* ...unused arg */ + (void) num_comp; + + /* ...printing memory info*/ + + tot_dev_mem_size = mem_get_alloc_size(mem_handle, XAF_MEM_ID_DEV); + tot_comp_mem_size = mem_get_alloc_size(mem_handle, XAF_MEM_ID_COMP); + tot_size = tot_dev_mem_size + tot_comp_mem_size; + + fprintf(stdout,"Shared Memory between AP and DSP for IPC: %8d \n", XF_CFG_REMOTE_IPC_POOL_SIZE); + fprintf(stdout,"Memory allocated on AP for Device : %8d \n", tot_dev_mem_size); + fprintf(stdout,"Memory allocated on AP for Components : %8d \n", tot_comp_mem_size); + fprintf(stdout,"Memory allocated on DSP for Components : %8d \n", XF_CFG_LOCAL_POOL_SIZE); + + return 0; +} + |