diff --git a/app/boards/imx8mp_evk_mimx8ml8_adsp.conf b/app/boards/imx8mp_evk_mimx8ml8_adsp.conf index c57b80ea..73e0db2e 100644 --- a/app/boards/imx8mp_evk_mimx8ml8_adsp.conf +++ b/app/boards/imx8mp_evk_mimx8ml8_adsp.conf @@ -4,3 +4,9 @@ CONFIG_IPM_IMX_MAX_DATA_SIZE_4=y CONFIG_OPENAMP_WITH_DCACHE=y CONFIG_IPM_IMX_FW_READY_REPLY=y CONFIG_POSAL_MMAP_NO_MMU=y +CONFIG_DAI=y +CONFIG_DMA=y +CONFIG_DAI_NXP_SAI=y +CONFIG_DMA_NXP_SDMA=y +CONFIG_SAI_HAS_MCLK_CONFIG_OPTION=y +CONFIG_CLOCK_CONTROL_FIXED_RATE_CLOCK=y \ No newline at end of file diff --git a/app/boards/imx8mp_evk_mimx8ml8_adsp.overlay b/app/boards/imx8mp_evk_mimx8ml8_adsp.overlay index e0b62f79..8b20ec98 100644 --- a/app/boards/imx8mp_evk_mimx8ml8_adsp.overlay +++ b/app/boards/imx8mp_evk_mimx8ml8_adsp.overlay @@ -17,8 +17,28 @@ compatible = "mmio-sram"; reg = <0x942f0000 0x110000>; }; + + mclk1: mclk { + status = "okay"; + }; }; &mailbox0 { status = "okay"; -}; \ No newline at end of file +}; + +&sdma3 { + status = "okay"; +}; + +&sai3 { + rx-fifo-watermark = <65>; + tx-fifo-watermark = <65>; + fifo-depth = <128>; + rx-sync-mode = <1>; + status = "okay"; +}; + +&micfil { + status = "okay"; +}; diff --git a/app/prj.conf b/app/prj.conf index cd387ccd..3422ea59 100644 --- a/app/prj.conf +++ b/app/prj.conf @@ -47,10 +47,12 @@ CONFIG_SHELL_BACKEND_RPMSG=y # AUDIOREACH ENGINE CONFIGURATION CONFIG_PROC_DOMAIN="ADSP" CONFIG_ARCH_ZEPHYR=y +CONFIG_SHARED_INTERRUPTS=y # AudioReach Features - Disabled for minimal build CONFIG_ALSA_DEVICE_SINK=n CONFIG_ALSA_DEVICE_SOURCE=n +CONFIG_NXP_DEVICE_SINK=y CONFIG_SH_MEM_PULL_MODE=n CONFIG_SH_MEM_PUSH_MODE=n CONFIG_LATENCY=n diff --git a/fwk/platform/modules/Kconfig b/fwk/platform/modules/Kconfig index 6c8f3724..d2d17baa 100644 --- a/fwk/platform/modules/Kconfig +++ b/fwk/platform/modules/Kconfig @@ -8,4 +8,8 @@ config ALSA_DEVICE_SOURCE tristate "Enable ALSA_DEVICE_SOURCE Library" default y +config NXP_DEVICE_SINK + tristate "Enable NXP_DEVICE_SINK Library" + default n + endmenu diff --git a/fwk/platform/modules/build/CMakeLists.txt b/fwk/platform/modules/build/CMakeLists.txt index a07c7a9c..76e6ca8e 100644 --- a/fwk/platform/modules/build/CMakeLists.txt +++ b/fwk/platform/modules/build/CMakeLists.txt @@ -17,3 +17,4 @@ include_directories( #Add the sub directories add_subdirectory(../generic/build generic) +add_subdirectory(../nxp/build nxp) diff --git a/fwk/platform/modules/nxp/build/CMakeLists.txt b/fwk/platform/modules/nxp/build/CMakeLists.txt new file mode 100644 index 00000000..daa3f3c1 --- /dev/null +++ b/fwk/platform/modules/nxp/build/CMakeLists.txt @@ -0,0 +1,13 @@ +#[[ + @file CMakeLists.txt + + @brief +]] +cmake_minimum_required(VERSION 3.10) + +#Include directories +include_directories( + ) + +#Add the sub directories +add_subdirectory(../endpoint/build endpoint) diff --git a/fwk/platform/modules/nxp/endpoint/api/hw_intf_cmn_api.h b/fwk/platform/modules/nxp/endpoint/api/hw_intf_cmn_api.h new file mode 100644 index 00000000..c2b5a087 --- /dev/null +++ b/fwk/platform/modules/nxp/endpoint/api/hw_intf_cmn_api.h @@ -0,0 +1,507 @@ +#ifndef HW_INTF_CMN_API +#define HW_INTF_CMN_API +/** + * \file hw_intf_cmn_api.h + * \brief + * + * \copyright + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "module_cmn_api.h" +#include "imcl_fwk_intent_api.h" + +/** @addtogroup ar_spf_mod_hwep_common_mods + These APIs are used by all hardware endpoint modules such as I2S and PCM + TDM. +*/ + +/*------------------------------------------------------------------------------ + Parameters +------------------------------------------------------------------------------*/ +/*============================================================================== + Constants +==============================================================================*/ + +/** @ingroup ar_spf_mod_hwep_common_macros + Frame size in milliseconds (inclusive). */ +#define FRAME_SIZE_FACTOR_1 1 + +/** @ingroup ar_spf_mod_hwep_common_macros + Minimum size of the frame in milliseconds. */ +#define FRAME_SIZE_MIN_MS 1 + +/** @ingroup ar_spf_mod_hwep_common_macros + Maximum size of the frame in milliseconds. */ +#define FRAME_SIZE_MAX_MS 40 + +/** @ingroup ar_spf_mod_hwep_common_mods + Valid types of Low-Power Audio Interfaces (LPAIFs). +*/ +typedef enum /** @cond */ lpaif_type_t /** @endcond */ +{ + LPAIF = 0, /**< */ + LPAIF_RXTX = 1, /**< */ + LPAIF_WSA = 2, /**< */ + LPAIF_VA = 3, /**< */ + LPAIF_AXI = 4, /**< */ + LPAIF_AUD = 5, /**< */ + LPAIF_SDR = 6, /**< */ + LPAIF_WSA2 = 7, /**< */ + MAX_NUM_LPAIF_TYPES, /**< */ + LPAIF_BLK_INVALID = 0x7FFFFFFF /**< */ +} lpaif_type_t ; + +/*============================================================================== + Type definitions +==============================================================================*/ + +/** @ingroup ar_spf_mod_hwep_common_mods + ID of the parameter used to configure the hardware endpoint media format. */ +#define PARAM_ID_HW_EP_MF_CFG 0x08001017 + +/*# @h2xmlp_parameter {"PARAM_ID_HW_EP_MF_CFG", PARAM_ID_HW_EP_MF_CFG} + @h2xmlp_description {ID for the parameter used to configure the hardware + endpoint media format.} + @h2xmlp_toolPolicy {Calibration} */ + +/** @ingroup ar_spf_mod_hwep_common_mods + Payload of the #PARAM_ID_HW_EP_MF_CFG parameter. +*/ +#include "spf_begin_pack.h" +struct param_id_hw_ep_mf_t +{ + uint32_t sample_rate; + /**< Defines the sampling rate of the interface. + + @values 8, 11.025, 12, 16, 22.05, 24,32, 44.1, 48, 88.2, 96, 176.4, + 192, 352.8, 384 kHz */ + + /*#< @h2xmle_description {Defines the sampling rate of the interface.} + @h2xmle_rangeList {"8 kHz"=8000; + "11.025 kHz"=11025; + "12 kHz"=12000; + "16 kHz"=16000; + "22.05 kHz"=22050; + "24 kHz"=24000; + "32 kHz"=32000; + "44.1 kHz"=44100; + "48 kHz"=48000; + "88.2 kHz"=88200; + "96 kHz"=96000; + "176.4 kHz"=176400; + "192 kHz"=192000; + "352.8 kHz"=352800; + "384 kHz"=384000} + @h2xmle_default {48000} */ + + uint16_t bit_width; + /**< Bit width in bits per sample. + + @valuesbul + - #BIT_WIDTH_16 + - #BIT_WIDTH_24 + - #BIT_WIDTH_32 @tablebulletend*/ + + /*#< @h2xmle_description {Bit width in bits per sample.} + @h2xmle_rangeList {"BIT_WIDTH_16"=16; + "BIT_WIDTH_24"=24; + "BIT_WIDTH_32"=32} + @h2xmle_default {16} */ + + uint16_t num_channels; + /**< Number of channels. + + @values 1 through 32 (Default = 1) */ + + /*#< @h2xmle_description {Number of channels.} + @h2xmle_range {1..32} + @h2xmle_default {1} */ + + uint32_t data_format; + /**< Format of the data. + + @valuesbul + - #DATA_FORMAT_FIXED_POINT (Default) + - #DATA_FORMAT_IEC61937_PACKETIZED + - #DATA_FORMAT_IEC60958_PACKETIZED + - #DATA_FORMAT_IEC60958_PACKETIZED_NON_LINEAR + - #DATA_FORMAT_DSD_OVER_PCM + - #DATA_FORMAT_GENERIC_COMPRESSED + - #DATA_FORMAT_RAW_COMPRESSED + - #DATA_FORMAT_COMPR_OVER_PCM_PACKETIZED @tablebulletend */ + + /*#< @h2xmle_description {Format of the data.} + @h2xmle_rangeList {"DATA_FORMAT_FIXED_POINT"=1; + "DATA_FORMAT_IEC61937_PACKETIZED"=2; + "DATA_FORMAT_IEC60958_PACKETIZED"=3; + "DATA_FORMAT_IEC60958_PACKETIZED_NON_LINEAR"= 8; + "DATA_FORMAT_DSD_OVER_PCM"=4; + "DATA_FORMAT_GENERIC_COMPRESSED"=5; + "DATA_FORMAT_RAW_COMPRESSED"=6; + "DATA_FORMAT_COMPR_OVER_PCM_PACKETIZED"= 7} + @h2xmle_default {1} */ +} +#include "spf_end_pack.h" +; +typedef struct param_id_hw_ep_mf_t param_id_hw_ep_mf_t; + + +/** @ingroup ar_spf_mod_hwep_common_mods + Identifier for the parameter that configures the operating frame size. + + @msgpayload + param_id_frame_size_factor_t +*/ +#define PARAM_ID_HW_EP_FRAME_SIZE_FACTOR 0x08001018 + +/*# @h2xmlp_parameter {"PARAM_ID_HW_EP_FRAME_SIZE_FACTOR", + PARAM_ID_HW_EP_FRAME_SIZE_FACTOR} + @h2xmlp_description {ID for the parameter that configures the operating + frame size.} + @h2xmlp_toolPolicy {Calibration} */ + +/** @ingroup ar_spf_mod_hwep_common_mods + Payload of the #PARAM_ID_HW_EP_FRAME_SIZE_FACTOR parameter. + */ +#include "spf_begin_pack.h" +struct param_id_frame_size_factor_t +{ + uint32_t frame_size_factor; + /**< Frame size factor used to derive the operating frame size. + + @values 1 through 40 samples per channel (Default = 1) */ + + /*#< @h2xmle_description {Frame size factor used to derive the operating + frame size (in number of samples per channel).} + @h2xmle_range {1..40} + @h2xmle_default {1} */ +} +#include "spf_end_pack.h" +; +typedef struct param_id_frame_size_factor_t param_id_frame_size_factor_t; + + +/** @ingroup ar_spf_mod_hwep_common_mods + Identifier for the parameter that configures the power mode (XO shutdown). + + @msgpayload + param_id_hw_ep_power_mode_cfg_t +*/ +#define PARAM_ID_HW_EP_POWER_MODE_CFG 0x08001176 + +/*# @h2xmlp_parameter {"PARAM_ID_HW_EP_POWER_MODE_CFG", + PARAM_ID_HW_EP_POWER_MODE_CFG} + @h2xmlp_description {Configures the power mode (XO shutdown).} + @h2xmlp_toolPolicy {Calibration} */ + +/** @ingroup ar_spf_mod_hwep_common_macros + Default mode where the endpoint is not in the low-power island (LPI). */ +#define POWER_MODE_0 0 + +/** @ingroup ar_spf_mod_hwep_common_macros + XO shutdown (deep sleep) is allowed, all LPM's allowed. */ +#define POWER_MODE_1 1 + +/** @ingroup ar_spf_mod_hwep_common_macros + XO shutdown not allowed, LPM+ modes disabled */ +#define POWER_MODE_2 2 + +/** @ingroup ar_spf_mod_hwep_common_macros + XO shutdown is allowed, LPM+ modes disabled */ +#define POWER_MODE_3 3 + +/** @ingroup ar_spf_mod_hwep_common_macros + Maximum number of power modes. */ +#define HW_EP_POWER_MODE_MAX AR_NON_GUID(POWER_MODE_3) + +/** @ingroup ar_spf_mod_hwep_common_mods + Payload of the #PARAM_ID_HW_EP_POWER_MODE_CFG parameter. + */ +#include "spf_begin_pack.h" +struct param_id_hw_ep_power_mode_cfg_t +{ + uint32_t power_mode; + /**< Indicates the sleep latency XO mode vote in a low-power scenario. + + @valuesbul + - #POWER_MODE_0 (Default) + - #POWER_MODE_1 + - #POWER_MODE_2 + - #POWER_MODE_3 @tablebulletend */ + + /*#< @h2xmle_description {Indicates the sleep latency XO mode vote in a + low-power scenario.} + @h2xmle_default {POWER_MODE_0} + @h2xmle_rangeList {"POWER_MODE_0"=POWER_MODE_0; + "POWER_MODE_1"=POWER_MODE_1; + "POWER_MODE_2"=POWER_MODE_2; + "POWER_MODE_3"=POWER_MODE_3} */ +} +#include "spf_end_pack.h" +; +typedef struct param_id_hw_ep_power_mode_cfg_t param_id_hw_ep_power_mode_cfg_t; + +/*********************************** HW EP Timestamp Propagation enable ******************************/ +/** @ingroup ar_spf_mod_hwep_common_mods + Identifier for the parameter that enable/disable the timestamp propagation. + + @msgpayload + param_id_hw_ep_timestamp_propagation_t +*/ +#define PARAM_ID_HW_EP_TIMESTAMP_PROPAGATION 0x08001A7E + +/*# @h2xmlp_parameter {"PARAM_ID_HW_EP_TIMESTAMP_PROPAGATION", + PARAM_ID_HW_EP_TIMESTAMP_PROPAGATION} + @h2xmlp_description {Identifier for the parameter that enable/disable + the timestamp propagation.} + @h2xmlp_toolPolicy {Calibration} */ + +/** @ingroup ar_spf_mod_hwep_common_macros + Mode where the timstamp propagation is disabled. */ +#define TIMESTAMP_PROPAGATION_DISABLE 1 + +/** @ingroup ar_spf_mod_hwep_common_macros + Default mode where the timstamp propagation is enabled. */ +#define TIMESTAMP_PROPAGATION_ENABLE 0 +/** @ingroup ar_spf_mod_hwep_common_mods + Payload of the #PARAM_ID_HW_EP_TIMESTAMP_PROPAGATION parameter. */ + +#include "spf_begin_pack.h" +struct param_id_hw_ep_timestamp_propagation_t +{ + uint32_t is_timestamp_disabled; + /**< Indicates that the timestamp propagation is disabled or not. + + @valuesbul + - #TIMESTAMP_PROPAGATION_DISABLE + - #TIMESTAMP_PROPAGATION_ENABLE (Default) @tablebulletend */ + + /*#< @h2xmle_description {Indicates the timestamp propagation is disabled or not.} + @h2xmle_default {TIMESTAMP_PROPAGATION_ENABLE} + @h2xmle_rangeList {"TIMESTAMP_PROPAGATION_DISABLE"=TIMESTAMP_PROPAGATION_DISABLE; + "TIMESTAMP_PROPAGATION_ENABLE"=TIMESTAMP_PROPAGATION_ENABLE} */ +} +#include "spf_end_pack.h" +; +typedef struct param_id_hw_ep_timestamp_propagation_t param_id_hw_ep_timestamp_propagation_t; + + +/*********************************** HW EP Interleaving ******************************/ + +/** @ingroup ar_spf_mod_hwep_common_mods + Identifier for the parameter that configures data interleaving for + the HW EP Source interface. + + @msgpayload + param_id_hw_ep_data_interleaving_t +*/ +#define PARAM_ID_HW_EP_SRC_OUT_DATA_INTERLEAVING 0x08001A7F + +/*# @h2xmlp_parameter {"PARAM_ID_HW_EP_SRC_OUT_DATA_INTERLEAVING", + PARAM_ID_HW_EP_SRC_OUT_DATA_INTERLEAVING} + @h2xmlp_description {ID for the parameter that configures the data + interleaving for the HW EP Module.} + @h2xmlp_toolPolicy {Calibration} */ + +/** @ingroup ar_spf_mod_hwep_common_macros + Mode to configure the data interleaving as interleaved. */ +#define DATA_INTERLEAVED 0 + +/** @ingroup ar_spf_mod_hwep_common_macros + Mode to configure the data interleaving as deinterleaved packed. */ +#define DATA_DEINTERLEAVED_PACKED 1 + +/** @ingroup ar_spf_mod_hwep_common_macros + Default mode to configure the data interleaving as deinterleaved unpacked. */ +#define DATA_DEINTERLEAVED_UNPACKED 2 + +/** @ingroup ar_spf_mod_hwep_common_macros + Mode to configure the data interleaving as invalid. */ +#define DATA_INVALID_INTERLEAVING 3 + +/** @ingroup ar_spf_mod_hwep_common_mods + Payload of the #PARAM_ID_HW_EP_SRC_OUT_DATA_INTERLEAVING parameter. */ + +#include "spf_begin_pack.h" +struct param_id_hw_ep_data_interleaving_t +{ + uint32_t data_interleaving; + /**< Indicates the data interleaving supported by the HW Endpoint Module. + + @valuesbul + - #DATA_INTERLEAVED + - #DATA_DEINTERLEAVED_PACKED + - #DATA_DEINTERLEAVED_UNPACKED (Default) + - #DATA_INVALID_INTERLEAVING @tablebulletend */ + + /*#< @h2xmle_description {Indicates the data interleaving supported by the + HW EP module.} + @h2xmle_default {DATA_DEINTERLEAVED_UNPACKED} + @h2xmle_rangeList {"DATA_INTERLEAVED"=DATA_INTERLEAVED; + "DATA_DEINTERLEAVED_PACKED"=DATA_DEINTERLEAVED_PACKED; + "DATA_DEINTERLEAVED_UNPACKED"=DATA_DEINTERLEAVED_UNPACKED; + "DATA_INVALID_INTERLEAVING"=DATA_INVALID_INTERLEAVING} */ +} +#include "spf_end_pack.h" +; +typedef struct param_id_hw_ep_data_interleaving_t param_id_hw_ep_data_interleaving_t; + +/*********************************** HW EP Source Custom Channel Map ******************************/ + +/** @ingroup ar_spf_mod_hwep_common_mods + Identifier for the parameter that configures custom channel maps for the + hardware endpoint source modules. + + @msgpayload + param_id_hw_ep_src_channel_map_t + */ +#define PARAM_ID_HW_EP_SRC_CHANNEL_MAP 0x0800108A + +/*# @h2xmlp_parameter {"PARAM_ID_HW_EP_SRC_CHANNEL_MAP", + PARAM_ID_HW_EP_SRC_CHANNEL_MAP} + @h2xmlp_description {ID for the parameter that configures custom channel + maps for the hardware EP source.} + @h2xmlp_toolPolicy {Calibration} */ + +/** @ingroup ar_spf_mod_hwep_common_mods + Payload of the #PARAM_ID_HW_EP_SRC_CHANNEL_MAP parameter. + */ +#include "spf_begin_pack.h" +#include "spf_begin_pragma.h" +struct param_id_hw_ep_src_channel_map_t +{ + uint16_t num_channels; + /**< Number of channels in the array. + + @values 0 through 16 (Default = 0) */ + + /*#< @h2xmle_description {Number of channels} + @h2xmle_default {0} + @h2xmle_range {0..16} + @h2xmle_policy {Basic} */ + +#if defined(__H2XML__) + uint16_t channel_mapping[0]; + /**< Array of channel mappings of size num_channels. + + @values PCM_CUSTOM_CHANNEL_MAP_1 (Default) through + PCM_CUSTOM_CHANNEL_MAP_16 (see #pcm_channel_map) + + Each element i of the array describes channel i in the buffer, where i + is less than num_channels. An unused channel is set to 0. + + Each channel that is used should be between the values of 48 and 63. + @newpagetable */ + + /*#< @h2xmle_description {Channel mapping array of size num_channels. Each + element i of the array describes channel i + in the buffer, where i is less than + num_channels. An unused channel is set to + 0. Each channel that is used should be + between the values of 48 and 63.} + @h2xmle_rangeList {"PCM_CUSTOM_CHANNEL_MAP_1"=PCM_CUSTOM_CHANNEL_MAP_1, + "PCM_CUSTOM_CHANNEL_MAP_2"=PCM_CUSTOM_CHANNEL_MAP_2, + "PCM_CUSTOM_CHANNEL_MAP_3"=PCM_CUSTOM_CHANNEL_MAP_3, + "PCM_CUSTOM_CHANNEL_MAP_4"=PCM_CUSTOM_CHANNEL_MAP_4, + "PCM_CUSTOM_CHANNEL_MAP_5"=PCM_CUSTOM_CHANNEL_MAP_5, + "PCM_CUSTOM_CHANNEL_MAP_6"=PCM_CUSTOM_CHANNEL_MAP_6, + "PCM_CUSTOM_CHANNEL_MAP_7"=PCM_CUSTOM_CHANNEL_MAP_7, + "PCM_CUSTOM_CHANNEL_MAP_8"=PCM_CUSTOM_CHANNEL_MAP_8, + "PCM_CUSTOM_CHANNEL_MAP_9"=PCM_CUSTOM_CHANNEL_MAP_9, + "PCM_CUSTOM_CHANNEL_MAP_10"=PCM_CUSTOM_CHANNEL_MAP_10, + "PCM_CUSTOM_CHANNEL_MAP_11"=PCM_CUSTOM_CHANNEL_MAP_11, + "PCM_CUSTOM_CHANNEL_MAP_12"=PCM_CUSTOM_CHANNEL_MAP_12, + "PCM_CUSTOM_CHANNEL_MAP_13"=PCM_CUSTOM_CHANNEL_MAP_13, + "PCM_CUSTOM_CHANNEL_MAP_14"=PCM_CUSTOM_CHANNEL_MAP_14, + "PCM_CUSTOM_CHANNEL_MAP_15"=PCM_CUSTOM_CHANNEL_MAP_15, + "PCM_CUSTOM_CHANNEL_MAP_16"=PCM_CUSTOM_CHANNEL_MAP_16} + @h2xmle_default {PCM_CUSTOM_CHANNEL_MAP_1} + @h2xmle_variableArraySize {"num_channels"} + @h2xmle_policy {Basic} */ +#endif +} +#include "spf_end_pragma.h" +#include "spf_end_pack.h" +; +typedef struct param_id_hw_ep_src_channel_map_t param_id_hw_ep_src_channel_map_t; + + +/** @ingroup ar_spf_mod_hwep_common_mods + Identifier for the parameter that configures DMA data alignment for the + Codec DMA interface. + + @msgpayload + param_id_hw_ep_dma_data_align_t +*/ +#define PARAM_ID_HW_EP_DMA_DATA_ALIGN 0x08001233 + +/*# @h2xmlp_parameter {"PARAM_ID_HW_EP_DMA_DATA_ALIGN", + PARAM_ID_HW_EP_DMA_DATA_ALIGN} + @h2xmlp_description {ID for the parameter that configures DMA data + alignment for the Codec DMA interface.} + @h2xmlp_toolPolicy {Calibration} */ + +/** @ingroup ar_spf_mod_hwep_common_macros + DMA data is aligned to the most significant bit (MSB). */ +#define DMA_DATA_ALIGN_MSB 0 + +/** @ingroup ar_spf_mod_hwep_common_macros + DMA data is aligned to the least significant bit (LSB). */ +#define DMA_DATA_ALIGN_LSB 1 + +/** @ingroup ar_spf_mod_hwep_common_mods + Payload of the #PARAM_ID_HW_EP_DMA_DATA_ALIGN parameter. + */ +#include "spf_begin_pack.h" +struct param_id_hw_ep_dma_data_align_t +{ + uint32_t dma_data_align; + /**< Indicates the data alignment in the DMA buffer. + + @valuesbul + - #DMA_DATA_ALIGN_MSB (Default) + - #DMA_DATA_ALIGN_LSB @tablebulletend */ + + /*#< @h2xmle_description {Indicates the data alignment in the DMA buffer.} + @h2xmle_rangeList {"DMA_DATA_ALIGN_MSB"=0; + "DMA_DATA_ALIGN_LSB"=1} + @h2xmle_default {0} */ +} +#include "spf_end_pack.h" +; +typedef struct param_id_hw_ep_dma_data_align_t param_id_hw_ep_dma_data_align_t; + +/** @ingroup ar_spf_mod_hwep_common_mods + * Identifier for the parameter that configures H.W delay + * for hardware interfaces. + + @msgpayload + param_id_hw_delay_t +*/ +#define PARAM_ID_HW_DELAY 0x080013D5 + +/*# @h2xmlp_parameter {"PARAM_ID_HW_DELAY", + PARAM_ID_HW_DELAY} + @h2xmlp_description {ID for the parameter that configures H.W delay + for hardware interfaces.} + @h2xmlp_toolPolicy {Calibration} */ + +/** @ingroup ar_spf_mod_hwep_common_mods + Payload of the #PARAM_ID_HW_DELAY parameter. + */ +#include "spf_begin_pack.h" +struct param_id_hw_delay_t +{ + uint32_t hw_delay_us; + /**< Indicates the H.W delay in micro seconds. */ + + /*#< @h2xmle_description {Indicates the H.W delay in micro seconds.} + @h2xmle_default {0} */ +} +#include "spf_end_pack.h" +; +typedef struct param_id_hw_delay_t param_id_hw_delay_t; + +#endif /* HW_INTF_CMN_API */ diff --git a/fwk/platform/modules/nxp/endpoint/api/nxp_device_api.h b/fwk/platform/modules/nxp/endpoint/api/nxp_device_api.h new file mode 100644 index 00000000..d1f9b08a --- /dev/null +++ b/fwk/platform/modules/nxp/endpoint/api/nxp_device_api.h @@ -0,0 +1,69 @@ +#ifndef NXP_DEVICE_API_H +#define NXP_DEVICE_API_H +/** + * \file nxp_device_api.h + * + * \brief nxp_device_api.h: This file contains the Module Id, Param IDs and + * configuration structures exposed by the NXP Device Sink and Source Modules. + * + * \copyright + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "hw_intf_cmn_api.h" + + /** @h2xml_title1 {NXP Device API} + @h2xml_title_agile_rev {NXP Device API} + @h2xml_title_date {June 10, 2026} */ + +/*============================================================================== + Constants +==============================================================================*/ + +/** @ingroup ar_spf_NXP_device_macros + Input port ID of NXP Device module */ +#define PORT_ID_NXP_DEVICE_INPUT 0x2 + +/** @ingroup ar_spf_NXP_device_macros + Output port ID of NXP Device module */ +#define PORT_ID_NXP_DEVICE_OUTPUT 0x1 + +#define NXP_DEVICE_STACK_SIZE 2048 + +/*------------------------------------------------------------------------------ + Module +------------------------------------------------------------------------------*/ + +#define MODULE_ID_NXP_DEVICE_SINK 0x0700109C + +/** @h2xmlm_module {"MODULE_ID_NXP_DEVICE_SINK", + MODULE_ID_NXP_DEVICE_SINK} + @h2xmlm_displayName {"NXP Device"} + @h2xmlm_modSearchKeys{hardware} + @h2xmlm_description {NXP_DEVICE Sink Module\n + - Supports following params: + - PARAM_ID_HW_EP_MF_CFG \n + - PARAM_ID_HW_EP_FRAME_SIZE_FACTOR \n + - Supported Input Media Format: \n + - Data Format : FIXED_POINT \n + - fmt_id : Don't care \n + - Sample Rates : 8, 11.025, 12, 16, 22.05, 24, 32, 44.1, 48, \n + - 88.2, 96, 176.4, 192, 352.8, 384 kHz \n + - Number of channels : 1 to 8 \n + - Channel type : Don't care \n + - Bit Width : 16 (bits per sample 16 and Q15), \n + - : 24 (bits per sample 24 and Q27) \n + - : 32 (bits per sample 32 and Q31) \n + - Q format : Q15, Q27, Q31 \n + - Interleaving : ? } + @h2xmlm_dataInputPorts {IN = PORT_ID_NXP_DEVICE_INPUT} + @h2xmlm_dataMaxInputPorts {1} + @h2xmlm_dataMaxOutputPorts {0} + @h2xmlm_supportedContTypes { APM_CONTAINER_TYPE_GC } + @h2xmlm_isOffloadable {false} + @h2xmlm_stackSize { NXP_DEVICE_STACK_SIZE } + @{ <-- Start of the Module --> + @} <-- End of the Module -->*/ + +#endif /* NXP_DEVICE_API_H */ \ No newline at end of file diff --git a/fwk/platform/modules/nxp/endpoint/build/CMakeLists.txt b/fwk/platform/modules/nxp/endpoint/build/CMakeLists.txt new file mode 100644 index 00000000..984d6b14 --- /dev/null +++ b/fwk/platform/modules/nxp/endpoint/build/CMakeLists.txt @@ -0,0 +1,34 @@ +#[[ + @file CMakeLists.txt + + @brief +]] + +cmake_minimum_required(VERSION 3.10) + +set(nxp_device_sources + ${LIB_ROOT}/capi/src/capi_nxp_device_utils.c + ${LIB_ROOT}/capi/src/capi_nxp_device.c +) + +set(nxp_device_includes + ${LIB_ROOT}/api + ${LIB_ROOT}/capi/inc + ${LIB_ROOT}/capi/src +) + +spf_module_sources( + KCONFIG CONFIG_NXP_DEVICE_SINK + NAME nxp_device_sink + MAJOR_VER 1 + MINOR_VER 0 + AMDB_ITYPE "capi" + AMDB_MTYPE "end_point" + AMDB_MID "0x0700109C" + AMDB_TAG "capi_nxp_device_sink" + AMDB_MOD_NAME "MODULE_ID_NXP_DEVICE_SINK" + SRCS ${nxp_device_sources} + INCLUDES ${nxp_device_includes} + H2XML_HEADERS "${LIB_ROOT}api/nxp_device_api.h" + CFLAGS "-Wno-address-of-packed-member" +) diff --git a/fwk/platform/modules/nxp/endpoint/capi/inc/capi_nxp_device.h b/fwk/platform/modules/nxp/endpoint/capi/inc/capi_nxp_device.h new file mode 100644 index 00000000..2c23463b --- /dev/null +++ b/fwk/platform/modules/nxp/endpoint/capi/inc/capi_nxp_device.h @@ -0,0 +1,39 @@ +/* ======================================================================== */ +/** + @file capi_nxp_device.h + @brief This file contains CAPI API's published by nxp device module. + + Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + SPDX-License-Identifier: BSD-3-Clause +==============================================================================*/ + +#ifndef CAPI_NXP_DEVICE_H +#define CAPI_NXP_DEVICE_H + +/*------------------------------------------------------------------------ + * Include files + * -----------------------------------------------------------------------*/ +#include "capi.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /*__cplusplus*/ + +/*------------------------------------------------------------------------ + * Function declarations + * ----------------------------------------------------------------------*/ + +capi_err_t capi_nxp_device_sink_init( + capi_t *_pif, + capi_proplist_t *init_set_properties); + +capi_err_t capi_nxp_device_sink_get_static_properties( + capi_proplist_t *init_set_properties, + capi_proplist_t *static_properties); + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif // CAPI_NXP_DEVICE_H \ No newline at end of file diff --git a/fwk/platform/modules/nxp/endpoint/capi/src/capi_nxp_device.c b/fwk/platform/modules/nxp/endpoint/capi/src/capi_nxp_device.c new file mode 100644 index 00000000..c0e5597b --- /dev/null +++ b/fwk/platform/modules/nxp/endpoint/capi/src/capi_nxp_device.c @@ -0,0 +1,565 @@ +/* ======================================================================== + @file capi_nxp_device.c + @brief This file contains CAPI implementation of nxp device Module + + Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + SPDX-License-Identifier: BSD-3-Clause +==============================================================================*/ + +/*===================================================================== + Includes + ======================================================================*/ +#include "capi_nxp_device_i.h" + +/*------------------------------------------------------------------------ + Function name: capi_nxp_device_sink_init + DESCRIPTION: Initialize the CAPIv2 nxp_device sink module and library. + This function can allocate memory. + -----------------------------------------------------------------------*/ +capi_err_t capi_nxp_device_sink_init( + capi_t *_pif, + capi_proplist_t *init_set_properties) +{ + //AR_MSG(DBG_ERROR_PRIO, + // "CAPI_NXP_DEVICE: Init enter"); + return capi_nxp_device_common_init(_pif, init_set_properties, 1); +} + +capi_err_t capi_nxp_device_sink_get_static_properties( + capi_proplist_t *init_set_properties, + capi_proplist_t *static_properties) +{ + return capi_nxp_device_process_get_properties((capi_nxp_device_t *)NULL, static_properties); +} + +/*--------------------------------------------------------------------- + Function name: capi_nxp_device_process + DESCRIPTION: Processes an input buffer and generates an output buffer. + -----------------------------------------------------------------------*/ +capi_err_t capi_nxp_device_process(capi_t *_pif, + capi_stream_data_t *input[], + capi_stream_data_t *output[]) +{ + capi_err_t result = CAPI_EOK; + capi_nxp_device_t *me_ptr = (capi_nxp_device_t *)_pif; + + if (me_ptr->direction == 0) + { + result |= capi_nxp_device_process_sink(_pif, input, output); + } + return result; +} + +/*------------------------------------------------------------------------ + Function name: capi_nxp_device_get_mf + DESCRIPTION: Function to get nxp device media fmt + * -----------------------------------------------------------------------*/ +static capi_err_t capi_nxp_device_get_mf(capi_nxp_device_t *me_ptr, capi_media_fmt_v2_t *media_fmt_ptr) +{ + + return CAPI_EOK; +} + +static capi_vtbl_t vtbl = {capi_nxp_device_process, capi_nxp_device_end, + capi_nxp_device_set_param, capi_nxp_device_get_param, + capi_nxp_device_set_properties, capi_nxp_device_get_properties}; + +capi_vtbl_t *capi_nxp_device_get_vtbl() +{ + return &vtbl; +} + +/*------------------------------------------------------------------------ + Function name: capi_nxp_device_get_param + DESCRIPTION: Gets either a parameter value or a parameter structure + containing multiple parameters. In the event of a failure, the appropriate + error code is returned. + * -----------------------------------------------------------------------*/ +capi_err_t capi_nxp_device_get_param(capi_t *_pif, + uint32_t param_id, + const capi_port_info_t *port_info_ptr, + capi_buf_t *params_ptr) +{ + capi_err_t capi_result = CAPI_EOK; + + if ((NULL == _pif) || (NULL == params_ptr) || (NULL == params_ptr->data_ptr)) + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: Get param received bad pointer, 0x%p, 0x%p", _pif, params_ptr); + return CAPI_EBADPARAM; + } + + capi_nxp_device_t *me_ptr = (capi_nxp_device_t *)_pif; + switch (param_id) + { + case FWK_EXTN_PARAM_ID_LATEST_TRIGGER_TIMESTAMP_PTR: + { + //capi_result = capi_cmn_populate_trigger_ts_payload(params_ptr, + // &me_ptr->drift_info.drift_calc_status.curr_intr_ts, + // capi_hw_intf_cmn_update_ts, + // (void *)(&me_ptr->hw_intf_ts_prop_cfg)); + params_ptr->data_ptr = NULL; + break; + } + case PARAM_ID_HW_EP_MF_CFG: + { + param_id_hw_ep_mf_t *i2s_cfg_ptr = (param_id_hw_ep_mf_t *)params_ptr->data_ptr; + i2s_cfg_ptr->bit_width = 16; + i2s_cfg_ptr->num_channels = 1; + i2s_cfg_ptr->sample_rate = 48000; + i2s_cfg_ptr->data_format = DATA_FORMAT_FIXED_POINT; + + break; + } + /*case PARAM_ID_I2S_INTF_CFG: + { + param_id_i2s_intf_cfg_t *i2s_cfg_ptr = (param_id_i2s_intf_cfg_t *)params_ptr->data_ptr; + i2s_cfg_ptr->intf_idx = 0; + i2s_cfg_ptr->sd_line_idx = I2S_SD0; + i2s_cfg_ptr->ws_src = 0; + + break; + }*/ + default: { + AR_MSG(DBG_ERROR_PRIO, "unsupported get param ID 0x%x", (int)param_id); + CAPI_SET_ERROR(capi_result, CAPI_EUNSUPPORTED); + break; + } + } + + return capi_result; +} + +/*------------------------------------------------------------------------ + Function name: capi_nxp_device_set_param + DESCRIPTION: Sets either a parameter value or a parameter structure containing + multiple parameters. In the event of a failure, the appropriate error code is + returned. + -----------------------------------------------------------------------*/ +capi_err_t capi_nxp_device_set_param(capi_t *_pif, + uint32_t param_id, + const capi_port_info_t *port_info_ptr, + capi_buf_t *params_ptr) +{ + capi_err_t capi_result = CAPI_EOK; + + if ((NULL == _pif) || (NULL == params_ptr) || (NULL == params_ptr->data_ptr)) + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_nxp_DEVICE: Get param received bad pointer, 0x%p, 0x%p", _pif, params_ptr); + return CAPI_EBADPARAM; + } + + switch (param_id) { + case PARAM_ID_HW_EP_TIMESTAMP_PROPAGATION: + { + /*if (I2S_SOURCE == me_ptr->i2s_driver.i2s_intf_state.direction) + { + if (param_size < sizeof(param_id_hw_ep_timestamp_propagation_t)) + { + AR_MSG(DBG_ERROR_PRIO, + "CAPI_I2S: SetParam 0x%lx, invalid param size %lx ", + param_id, + params_ptr->actual_data_len); + capi_result = CAPI_ENEEDMORE; + break; + } + param_id_hw_ep_timestamp_propagation_t *i2s_ts_prop_cfg_ptr = + (param_id_hw_ep_timestamp_propagation_t *)params_ptr->data_ptr; + + ar_result = + capi_hw_intf_cmn_ts_prop_cfg(&me_ptr->hw_intf_ts_prop_cfg, i2s_ts_prop_cfg_ptr->is_timestamp_disabled); + + if (AR_EOK != ar_result) + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_I2S: Timestamp propagation failed with 0x%lx", ar_result); + return CAPI_EFAILED; + } + AR_MSG(DBG_LOW_PRIO, + "CAPI_I2S: Timestamp propagation set param received with value [%d] (0:Enable, 1:Disable)", + i2s_ts_prop_cfg_ptr->is_timestamp_disabled); + } + else + { + capi_result |= CAPI_EUNSUPPORTED; + }*/ + break; + } + case PARAM_ID_HW_EP_SRC_OUT_DATA_INTERLEAVING: + { + /*if (I2S_SOURCE == me_ptr->i2s_driver.i2s_intf_state.direction) + { + if (param_size < sizeof(param_id_hw_ep_data_interleaving_t)) + { + AR_MSG(DBG_ERROR_PRIO, + "CAPI_I2S: SetParam 0x%lx, invalid param size %lx ", + param_id, + params_ptr->actual_data_len); + capi_result = CAPI_ENEEDMORE; + break; + } + + param_id_hw_ep_data_interleaving_t *i2s_src_data_int_ptr = + (param_id_hw_ep_data_interleaving_t *)params_ptr->data_ptr; + + if ((PCM_DEINTERLEAVED_UNPACKED != i2s_src_data_int_ptr->data_interleaving) && + (PCM_INTERLEAVED != i2s_src_data_int_ptr->data_interleaving)) + { + AR_MSG(DBG_ERROR_PRIO, + "CAPI_I2S: Interleaving value [%lu] not supported. ", + i2s_src_data_int_ptr->data_interleaving); + capi_result = CAPI_EBADPARAM; + break; + } + + pcm_to_capi_interleaved_with_native_param(&me_ptr->i2s_media_fmt.format.data_interleaving, + i2s_src_data_int_ptr->data_interleaving, + CAPI_INVALID_INTERLEAVING); + + if (me_ptr->i2s_driver.i2s_intf_state.ep_mf_received) + { + /*Raise media format events + capi_result |= capi_i2s_raise_media_fmt_event(me_ptr); + } + AR_MSG(DBG_LOW_PRIO, + "CAPI_I2S: Data Interleaving set param received, with int [%d]", + me_ptr->i2s_media_fmt.format.data_interleaving); + } + else + { + capi_result |= CAPI_EUNSUPPORTED; + }*/ + break; + } + case PARAM_ID_HW_EP_MF_CFG: + { + /*if (param_size < sizeof(param_id_hw_ep_mf_t)) + { + AR_MSG(DBG_ERROR_PRIO, + "CAPI_I2S: SetParam 0x%lx, invalid param size %lx ", + param_id, + params_ptr->actual_data_len); + capi_result = CAPI_ENEEDMORE; + break; + } + + param_id_hw_ep_mf_t *i2s_cfg_ptr = (param_id_hw_ep_mf_t *)params_ptr->data_ptr; + + ar_result = i2s_driver_set_hw_ep_mf_cfg(i2s_cfg_ptr, &(me_ptr->i2s_driver)); + if (AR_EOK != ar_result) + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_I2S: Driver set ep mf failed with 0x%lx", ar_result); + if(AR_EALREADY == ar_result) + { + return CAPI_EALREADY; + } + return CAPI_EFAILED; + } + + if (I2S_SOURCE == me_ptr->i2s_driver.i2s_intf_state.direction) + { + capi_cmn_data_fmt_map(&me_ptr->i2s_driver.i2s_intf_state.data_format, &me_ptr->i2s_media_fmt); + AR_MSG(DBG_HIGH_PRIO, "CAPI_I2S: Data format %d", me_ptr->i2s_media_fmt.header.format_header.data_format); + } + + /*Raise media format events + capi_result |= capi_i2s_raise_media_fmt_event(me_ptr); + + // threshold and algo event + capi_result |= capi_i2s_raise_thresh_delay_events(me_ptr); + if (CAPI_EOK != capi_result) + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_I2S:Failed to raise output media fmt and algo delay event", ar_result); + } + + // KPPS event + uint32_t kpps = + (3 * (me_ptr->i2s_driver.i2s_intf_state.sample_rate) * (me_ptr->i2s_driver.i2s_intf_state.num_channels)) / + 640; + capi_result = capi_cmn_update_kpps_event(&me_ptr->cb_info, kpps); + + // Bandwidth event + uint32_t code_bandwidth = 0; + uint32_t data_bandwidth = me_ptr->i2s_driver.i2s_intf_state.int_samples_per_period * + me_ptr->i2s_driver.i2s_intf_state.bit_width * + me_ptr->i2s_driver.i2s_intf_state.num_channels * 2; + + capi_result = capi_cmn_update_bandwidth_event(&me_ptr->cb_info, code_bandwidth, data_bandwidth); + if (CAPI_EOK != capi_result) + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_I2S: Failed to send bandwidth update event with %lu", capi_result); + }*/ + break; + } + case PARAM_ID_HW_EP_FRAME_SIZE_FACTOR: + { + /*if (param_size < sizeof(param_id_frame_size_factor_t)) + { + AR_MSG(DBG_ERROR_PRIO, + "CAPI_I2S: SetParam 0x%lx, invalid param size %lu ", + param_id, + params_ptr->actual_data_len); + capi_result = CAPI_ENEEDMORE; + break; + } + param_id_frame_size_factor_t *i2s_cfg_ptr = (param_id_frame_size_factor_t *)params_ptr->data_ptr; + + ar_result = i2s_driver_set_frame_size_cfg(i2s_cfg_ptr, &(me_ptr->i2s_driver)); + if (AR_EOK != ar_result) + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_I2S: Driver set param failed with 0x%lx", ar_result); + if(AR_EALREADY == ar_result) + { + return CAPI_EALREADY; + } + return CAPI_EFAILED; + } + + if (me_ptr->i2s_driver.i2s_intf_state.ep_mf_received) + { + capi_result = capi_i2s_raise_thresh_delay_events(me_ptr); + if (CAPI_EOK != capi_result) + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_I2S:Failed to raise output media fmt and algo delay event", ar_result); + } + }*/ + break; + } + case PARAM_ID_HW_EP_POWER_MODE_CFG: + { + // cfg should be received before START (STM trigger) + /*if (param_size < sizeof(param_id_hw_ep_power_mode_cfg_t)) + { + AR_MSG(DBG_ERROR_PRIO, + "CAPI_I2S: SetParam POWER_MODE_CFG, invalid param size %lu ", + params_ptr->actual_data_len); + capi_result = CAPI_ENEEDMORE; + break; + } + param_id_hw_ep_power_mode_cfg_t *power_cfg_ptr = (param_id_hw_ep_power_mode_cfg_t *)params_ptr->data_ptr; + + if (HW_EP_POWER_MODE_MAX < power_cfg_ptr->power_mode) + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_I2S: SetParam POWER_MODE_CFG, invalid value %lu ", power_cfg_ptr->power_mode); + capi_result = CAPI_EFAILED; + break; + } + + me_ptr->pm_info.power_mode = power_cfg_ptr->power_mode; + AR_MSG(DBG_HIGH_PRIO, "Received POWER_MODE_CFG: mode %lu", power_cfg_ptr->power_mode);*/ + break; + } + case PARAM_ID_HW_EP_SRC_CHANNEL_MAP: + { + /*if (param_size < sizeof(param_id_hw_ep_src_channel_map_t)) + { + AR_MSG(DBG_ERROR_PRIO, + "CAPI_I2S: SetParam HW_EP_SRC_CHANNEL_MAP, invalid param size %lu ", + params_ptr->actual_data_len); + capi_result = CAPI_ENEEDMORE; + break; + } + + if (I2S_SOURCE != me_ptr->i2s_driver.i2s_intf_state.direction) + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_I2S: SetParam HW_EP_SRC_CHANNEL_MAP only supported for source modules"); + capi_result = CAPI_EBADPARAM; + break; + } + + param_id_hw_ep_src_channel_map_t *channel_cfg_ptr = (param_id_hw_ep_src_channel_map_t *)params_ptr->data_ptr; + + /* Cache channel map to driver + capi_result |= i2s_driver_set_src_channel_map_cfg(channel_cfg_ptr, &me_ptr->i2s_driver); + + /* Send output mf if mf is received, if not it will be sent later + if (me_ptr->i2s_driver.i2s_intf_state.ep_mf_received) + { + /*Raise media format events + capi_result |= capi_i2s_raise_media_fmt_event(me_ptr); + } + + AR_MSG(DBG_HIGH_PRIO, "CAPI_I2S: Received Src Channel Map Cfg");*/ + break; + } + case INTF_EXTN_PARAM_ID_IMCL_PORT_OPERATION: + { + /*if (NULL == params_ptr->data_ptr) + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_I2S: Set param id 0x%lX, received null buffer", param_id); + + capi_result |= CAPI_EBADPARAM; + + break; + } + + /** Cache previous drift link state + bool_t was_ctrl_link_connected = me_ptr->ctrl_port_cfg.is_drift_link_connected ? TRUE : FALSE; + + /** Set the control port operation + if (CAPI_EOK != (capi_result = capi_hw_intf_cmn_imcl_port_operation(&me_ptr->ctrl_port_cfg, + &me_ptr->cb_info, + port_info_ptr, + params_ptr, + me_ptr->heap_mem.heap_id))) + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_I2S :Failed to set control port operation, result %d", capi_result); + } + else + { + // Check if STM module is enabled + if (TRUE == me_ptr->ctrl_port_cfg.is_stm_enabled) + { + // Check is there any change in drift link connection state + if (was_ctrl_link_connected != me_ptr->ctrl_port_cfg.is_drift_link_connected) + { + /** Reset drift tracking struct + tdu_reset_drift_info(&me_ptr->drift_info); // under mutex lock + + /* Chooses intended update period + tdu_cfg_drift_cal_params(&me_ptr->drift_info, + (me_ptr->ctrl_port_cfg.is_drift_link_connected) + ? TDU_DEFAULT_DRIFT_CALC_PERIOD_US + : TDU_DRIFT_CALC_PERIOD_US_LINK_NOT_CONNECTED, + me_ptr->i2s_driver.i2s_intf_state.frame_size_us); + } + } + }*/ + break; + } + case PARAM_ID_HW_DELAY: + { + /*if (NULL == params_ptr->data_ptr) + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_I2S: Set param id 0x%lX, received null buffer", param_id); + + capi_result |= CAPI_EBADPARAM; + + break; + } + + if (param_size < sizeof(param_id_hw_delay_t)) + { + AR_MSG(DBG_ERROR_PRIO, + "CAPI_I2S: SetParam 0x%lx, invalid param size %lu ", + param_id, + params_ptr->actual_data_len); + capi_result = CAPI_ENEEDMORE; + break; + } + + param_id_hw_delay_t *hw_delay_cfg_ptr = (param_id_hw_delay_t *)params_ptr->data_ptr; + + me_ptr->i2s_driver.i2s_intf_state.hw_delay_us = hw_delay_cfg_ptr->hw_delay_us; + + // In case HW delay is rcvd. after M.F raise algo delay again with HW delay included. + if (me_ptr->i2s_driver.i2s_intf_state.ep_mf_received) + { + capi_result = capi_i2s_raise_thresh_delay_events(me_ptr); + if (CAPI_EOK != capi_result) + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_I2S :Failed to raise output media fmt and algo delay event", capi_result); + } + } + + AR_MSG(DBG_HIGH_PRIO, + "CAPI_I2S: Received PARAM_ID_HW_DELAY with delay %d us", + hw_delay_cfg_ptr->hw_delay_us);*/ + break; + } + default: + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: Set, unsupported param ID 0x%x", (int)param_id); + CAPI_SET_ERROR(capi_result, CAPI_EUNSUPPORTED); + break; + } + + } /** End of switch (param ID) */ + + return capi_result; +} + +/*------------------------------------------------------------------------ + Function name: capi_nxp_device_end + DESCRIPTION: Returns the library to the uninitialized state and frees the + memory that was allocated by init(). This function also frees the virtual + function table. + -----------------------------------------------------------------------*/ +capi_err_t capi_nxp_device_end(capi_t *_pif) +{ + capi_err_t capi_result = CAPI_EOK; + + if (NULL == _pif) + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: capi_nxp_device_end received bad pointer, 0x%p", _pif); + return CAPI_EBADPARAM; + } + + capi_nxp_device_t *me_ptr = (capi_nxp_device_t *)_pif; + + capi_nxp_device_stop(me_ptr); + + capi_nxp_device_reset(me_ptr); + + return capi_result; +} + +/*------------------------------------------------------------------------ + Function name: capi_nxp_device_get_properties + DESCRIPTION: Function to get the properties for the nxp_device module + * -----------------------------------------------------------------------*/ +capi_err_t capi_nxp_device_get_properties(capi_t *_pif, + capi_proplist_t *proplist_ptr) +{ + return capi_nxp_device_process_get_properties((capi_nxp_device_t *)_pif, proplist_ptr); +} + +/*------------------------------------------------------------------------ + Function name: capi_nxp_device_set_properties + DESCRIPTION: Function to set the properties for the nxp_device module + * -----------------------------------------------------------------------*/ +capi_err_t capi_nxp_device_set_properties(capi_t *_pif, + capi_proplist_t *proplist_ptr) +{ + return capi_nxp_device_process_set_properties((capi_nxp_device_t *)_pif, proplist_ptr); +} + + +/*--------------------------------------------------------------------- + Function name: capi_nxp_device_update_dataflow_state + DESCRIPTION: . + -----------------------------------------------------------------------*/ +bool_t capi_nxp_device_update_dataflow_state(capi_stream_data_t *input, nxp_device_data_flow_state *data_flow_state, bool is_data_valid) +{ + bool_t is_not_steady_state = TRUE; + if (input && (TRUE == input->flags.marker_eos)) + { + *data_flow_state = DF_STOPPING; + } + else if (input && input->buf_ptr[0].data_ptr && is_data_valid) + { + *data_flow_state = DF_STARTED; + is_not_steady_state = FALSE; + } + else if (*data_flow_state == DF_STOPPING) + { + *data_flow_state = DF_STOPPED; + } + return is_not_steady_state; +} + +/*--------------------------------------------------------------------- + Function name: capi_nxp_device_check_data_sufficiency + DESCRIPTION: . + -----------------------------------------------------------------------*/ +bool_t capi_nxp_device_check_data_sufficiency(capi_stream_data_t *input, + capi_buf_t * scratch_buf, + uint32_t total_bytes, + bool_t packetized, + bool_t is_capi_in_media_fmt_set, + uint32_t expected_data_len, + uint16_t num_channels, + bool_t * need_to_underrun) +{ + bool_t is_data_valid = TRUE; + + return is_data_valid; +} diff --git a/fwk/platform/modules/nxp/endpoint/capi/src/capi_nxp_device_i.h b/fwk/platform/modules/nxp/endpoint/capi/src/capi_nxp_device_i.h new file mode 100644 index 00000000..6c590270 --- /dev/null +++ b/fwk/platform/modules/nxp/endpoint/capi/src/capi_nxp_device_i.h @@ -0,0 +1,233 @@ +/* ======================================================================== + @file capi_nxp_device_i.h + @brief This file contains CAPI includes of nxp Device Module + + Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + SPDX-License-Identifier: BSD-3-Clause +==============================================================================*/ + +#ifndef _CAPI_NXP_DEVICE_I_H +#define _CAPI_NXP_DEVICE_I_H + +/*===================================================================== + Includes + ======================================================================*/ +#include "capi_nxp_device.h" +#include "nxp_device_api.h" +#include "capi_cmn.h" +#include +#include +#include +#include +#include + +/*===================================================================== + Macros + ======================================================================*/ +#ifndef SIZE_OF_ARRAY +#define SIZE_OF_ARRAY(a) (sizeof(a) / sizeof((a)[0])) +#endif + +#ifndef min +#define min(A,B) ((A) < (B) ? (A) : (B)) +#endif + + /* Number of CAPI Framework extension needed */ +#define NXP_DEVICE_NUM_FRAMEWORK_EXTENSIONS 1 + +/* Number of milliseconds in a second*/ +#define NUM_MS_PER_SEC 1000 + +#define ALIGN_UP(val, align) (((val) + (align) - 1) & ~((align) - 1)) + +#define DT_DRV_COMPAT nxp_dai_sai + +typedef enum nxp_device_state +{ + NXP_DEVICE_INTERFACE_STOP = 0, + NXP_DEVICE_INTERFACE_START, + NXP_DEVICE_READY +} nxp_device_interface_state_t; + +typedef enum nxp_device_data_flow_state +{ + DF_STOPPED = 0, + DF_STARTED = 1, + DF_STOPPING = 2, +}nxp_device_data_flow_state; + +typedef struct i2s_port_state +{ + // interrupt statistics + int32_t *i2s_intr_cnt_ptr; + uint32_t fifo_ovf_cnt; + uint32_t ahb_err_cnt; + + // Signal Miss config - For debugging purpose only + bool_t is_periodic_signal_miss; + uint64_t intr_count_pre; // interrupt count to introduce a pre process signal miss (cntr delay) + uint64_t intr_count_post; // interrupt count to introduce a post process signal miss (module proc delay) + + //dma_device_handle dma_dev_hdl; + + // callback signal ptr for the interrupt + void *trigger_signal_ptr; + + /* status of current trigger shared between hwep module and client + * to differentiate between data and signal triggers. + * This flag will be set in interrupt callback context to indicate + * it is a signal trigger + */ + bool_t signal_trigger_status; + + //uint32_t i2s_ctl; /* Content of I2S control status register */ + + // H.W delay in us. + //uint32_t hw_delay_us; + /* This field is used to indicate if the frame duration normalization is allowed or not. + * If the frame duration is outside the range, the frame duration will be normalized to + * the closest supported range. + + bool_t allow_frame_duration_normalization; + uint32_t min_normalized_frame_dur_us; + uint32_t max_normalized_frame_dur_us; + uint32_t normalized_num_dma_buffers;*/ +} i2s_port_state_t; + +typedef struct i2s_drv_state +{ + i2s_port_state_t i2s_intf_state; + /* Pointer to individual interface state object*/ + +} i2s_drv_state_t; + +typedef struct capi_nxp_device { + /* v-table pointer */ + capi_t vtbl; + + /* Heap id, used to allocate memory */ + capi_heap_id_t heap_mem; + + /* Call back info for event raising */ + capi_event_callback_info_t cb_info; + + //struct capi_dai_data dai_data; + + void *user_cb_data; + + i2s_drv_state_t i2s_driver; + + /* Instance ID of this module */ + uint32_t iid; + + uint32_t direction; + + uint32_t log_id; + /* Unique log ID provided by framework */ + + uint32_t log_id_reserved_mask; + /* bits reserved for this module to use from the LSB*/ + + /* pointer to scratch data buffer used in process function */ + int8_t *out_data_buffer; + + /* Size of the scratch data buffer */ + uint32_t out_data_buffer_size; + + void *dma_src_addr; /**< Buffer base address */ + + void *dma_dest_addr; //Address of DMA buffer in system heap + + uint32_t dma_buf_size; /**< Runtime buffer size in bytes (period multiple) */ + + uint32_t dma_chan_index; + + struct dma_config *z_config; + + int dai_dir; //Different from the CAPI direction + +} capi_nxp_device_t; + +struct sai_params { + uint32_t reserved0; + + /* MCLK */ + uint16_t reserved1; + uint16_t mclk_id; + uint32_t mclk_direction; + + uint32_t mclk_rate; /* MCLK frequency in Hz */ + uint32_t fsync_rate; + uint32_t bclk_rate; + + /* TDM */ + uint32_t tdm_slots; + uint32_t rx_slots; + uint32_t tx_slots; + uint16_t tdm_slot_width; + uint16_t reserved2; /* alignment */ +}; + +/*------------------------------------------------------------------------ + * VTBL function declarations + * -----------------------------------------------------------------------*/ + +capi_vtbl_t *capi_nxp_device_get_vtbl(); + +capi_err_t capi_nxp_device_process(capi_t *_pif, + capi_stream_data_t *input[], + capi_stream_data_t *output[]); + +capi_err_t capi_nxp_device_end(capi_t *_pif); + +capi_err_t capi_nxp_device_get_param(capi_t *_pif, + uint32_t param_id, + const capi_port_info_t *port_info_ptr, + capi_buf_t *params_ptr); + +capi_err_t capi_nxp_device_set_param(capi_t *_pif, + uint32_t param_id, + const capi_port_info_t *port_info_ptr, + capi_buf_t *params_ptr); + +capi_err_t capi_nxp_device_get_properties(capi_t *_pif, + capi_proplist_t *proplist_ptr); + +capi_err_t capi_nxp_device_set_properties(capi_t *_pif, + capi_proplist_t *proplist_ptr); + +bool_t capi_nxp_device_update_dataflow_state(capi_stream_data_t *input, + nxp_device_data_flow_state *current_state, + bool is_data_sufficient); + +bool_t capi_nxp_device_check_data_sufficiency(capi_stream_data_t *input, + capi_buf_t *scratch_buf, + uint32_t total_bytes, + bool_t packetized, + bool_t is_capi_in_media_fmt_set, + uint32_t expected_data_len, + uint16_t num_channels, + bool_t *need_to_underrun); + +capi_err_t capi_nxp_device_dai_init(capi_nxp_device_t *me_ptr, uint32_t dir); + +capi_err_t capi_nxp_device_init_param(capi_nxp_device_t *me_ptr); + +capi_err_t capi_nxp_device_init_dma_buffer(capi_nxp_device_t *me_ptr, uint32_t *pb, uint32_t *pc); + +capi_err_t capi_nxp_device_set_dma_config(capi_nxp_device_t *me_ptr, uint32_t period_bytes, uint32_t period_count); + +void capi_nxp_device_reset(capi_nxp_device_t *me_ptr); + +void capi_nxp_device_stop(capi_nxp_device_t *me_ptr); + +void capi_nxp_device_dma_callback(const struct device *dev, void *user_data, + uint32_t channel, int status); + +capi_err_t capi_nxp_device_process_get_properties(capi_nxp_device_t *me_ptr, capi_proplist_t *proplist_ptr); + +capi_err_t capi_nxp_device_process_set_properties(capi_nxp_device_t *me_ptr, capi_proplist_t *proplist_ptr); + +capi_err_t capi_nxp_device_process_sink(capi_t *_pif, capi_stream_data_t *input[], capi_stream_data_t *output[]); + +#endif /* _CAPI_NXP_DEVICE_I_H */ \ No newline at end of file diff --git a/fwk/platform/modules/nxp/endpoint/capi/src/capi_nxp_device_utils.c b/fwk/platform/modules/nxp/endpoint/capi/src/capi_nxp_device_utils.c new file mode 100644 index 00000000..3c89b650 --- /dev/null +++ b/fwk/platform/modules/nxp/endpoint/capi/src/capi_nxp_device_utils.c @@ -0,0 +1,848 @@ +/* ======================================================================== + @file capi_nxp_device_utils.c + @brief This file contains library implementation of nxp device Module + + Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + SPDX-License-Identifier: BSD-3-Clause +==============================================================================*/ + +/*===================================================================== + Includes + ======================================================================*/ +#include "capi_nxp_device_i.h" +#include +#include + +#define PLATFORM_DCACHE_ALIGN 32 + +/* 16-bit interleaved stereo sine: 48 frames x (L,R) = 96 int16 = 192 bytes. + * Mono source sample duplicated into L and R slots for the 2-slot SAI frame. */ +#define BUF_SIZE 96 +static int16_t sine_buf[BUF_SIZE] = { + 0x0000, 0x0000, 0x10b5, 0x10b5, 0x2120, 0x2120, 0x30fb, 0x30fb, + 0x4000, 0x4000, 0x4deb, 0x4deb, 0x5a82, 0x5a82, 0x658c, 0x658c, + 0x6ed9, 0x6ed9, 0x7641, 0x7641, 0x7ba3, 0x7ba3, 0x7ee7, 0x7ee7, + 0x7fff, 0x7fff, 0x7ee7, 0x7ee7, 0x7ba3, 0x7ba3, 0x7641, 0x7641, + 0x6ed9, 0x6ed9, 0x658c, 0x658c, 0x5a82, 0x5a82, 0x4deb, 0x4deb, + 0x4000, 0x4000, 0x30fb, 0x30fb, 0x2120, 0x2120, 0x10b5, 0x10b5, + 0x0000, 0x0000, 0xef4a, 0xef4a, 0xdedf, 0xdedf, 0xcf04, 0xcf04, + 0xc000, 0xc000, 0xb214, 0xb214, 0xa57d, 0xa57d, 0x9a73, 0x9a73, + 0x9126, 0x9126, 0x89be, 0x89be, 0x845c, 0x845c, 0x8118, 0x8118, + 0x8000, 0x8000, 0x8118, 0x8118, 0x845c, 0x845c, 0x89be, 0x89be, + 0x9126, 0x9126, 0x9a73, 0x9a73, 0xa57d, 0xa57d, 0xb214, 0xb214, + 0xc000, 0xc000, 0xcf04, 0xcf04, 0xdedf, 0xdedf, 0xef4a, 0xef4a, +}; + +extern char _end[], _heap_sentry[]; +#define heapmem ((uint8_t *)ALIGN_UP((uintptr_t)_end, PLATFORM_DCACHE_ALIGN)) + +//Heap for dma_buffer +static struct k_heap kernel_heap; + +//const struct device *dai_devs[] = { DT_FOREACH_STATUS_OKAY(DT_NODELABEL(nxp_dai_sai), DEVICE_DT_GET(DT_NODELABEL(nxp_dai_sai))) }; +const struct device *dma_device = DEVICE_DT_GET(DT_NODELABEL(sdma3)); +const struct device *dai_dev = DEVICE_DT_GET(DT_NODELABEL(sai3)); + +/*------------------------------------------------------------------------ + Function name: capi_nxp_device_common_init + DESCRIPTION: Initialize the CAPIv2 nxp_device module and library. + This function can allocate memory. + -----------------------------------------------------------------------*/ +capi_err_t capi_nxp_device_common_init(capi_t *_pif, capi_proplist_t *init_set_properties, uint32_t dir) +{ + capi_err_t capi_result = CAPI_EOK; + //AR_MSG(DBG_ERROR_PRIO, + // "CAPI_NXP_DEVICE: Init enter"); + + if (NULL == _pif || NULL == init_set_properties) + { + AR_MSG(DBG_ERROR_PRIO, + "CAPI_NXP_DEVICE: Init received bad pointer, 0x%lx", + (uint32_t)_pif); + return CAPI_EBADPARAM; + } + + capi_nxp_device_t *me_ptr = (capi_nxp_device_t *)_pif; + memset((void *)me_ptr, 0, sizeof(capi_nxp_device_t)); + + // Allocate vtbl + me_ptr->vtbl.vtbl_ptr = capi_nxp_device_get_vtbl(); + + // Cache direction + me_ptr->direction = 0; //sink + //me_ptr->i2s_media_fmt.format.data_interleaving = CAPI_DEINTERLEAVED_UNPACKED; + + capi_result = capi_nxp_device_process_set_properties(me_ptr, init_set_properties); + capi_result ^= (capi_result & CAPI_EUNSUPPORTED); // ignore unsupported + if (CAPI_EOK != capi_result) + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: init set properties failed"); + return capi_result; + } + + //me_ptr->drift_info.heap_id = (POSAL_HEAP_ID)me_ptr->heap_mem.heap_id; + + capi_result = capi_nxp_device_dai_init(me_ptr, DAI_DIR_TX); + if (capi_result < 0) { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: Failed to initialize dai"); + return CAPI_EFAILED; + } + + capi_result = capi_nxp_device_init_param(me_ptr); + if (capi_result < 0) { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: Failed to initialize device parameters"); + return CAPI_EFAILED; + } + + AR_MSG(DBG_ERROR_PRIO, "rc: %d", capi_result); + return capi_result; +} + +/*------------------------------------------------------------------------ + Function name: capi_nxp_device_dai_init + DESCRIPTION: Initialize the CAPIv2 nxp_device dai. + -----------------------------------------------------------------------*/ +capi_err_t capi_nxp_device_dai_init(capi_nxp_device_t *me_ptr, uint32_t dir) +{ + capi_err_t capi_result = CAPI_EOK; + int ret = 0; + struct dai_config cfg; + struct sai_params *sai_cfg_params; + const void* cfg_params; + + if (NULL == me_ptr) + { + AR_MSG(DBG_ERROR_PRIO, + "CAPI_NXP_DEVICE: Init received null property"); + return CAPI_EBADPARAM; + } + + ret = dai_config_get(dai_dev, &cfg, DAI_DIR_TX); + if (ret != 0) { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: Failed to get dai configuration rc: %d", ret); + capi_result = CAPI_EFAILED; + goto end; + } + + if (dai_probe(dai_dev)) { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: Failed to probe dai"); + capi_result = CAPI_EFAILED; + goto end; + } + + sai_cfg_params = posal_memory_malloc(sizeof(struct sai_params), (POSAL_HEAP_ID)me_ptr->heap_mem.heap_id); + if (NULL == sai_cfg_params) { + AR_MSG(DBG_ERROR_PRIO, + "CAPI_NXP_DEVICE: Failed to allocate sai configuration pointer"); + capi_result = CAPI_ENOMEMORY; + goto end; + } + + me_ptr->dai_dir = dir; + + //Set the configuration + cfg.dai_index = 3; + //cfg.format = 1; + cfg.format = DAI_PROTO_I2S; + cfg.options = 1; + cfg.rate = 48000; + cfg.type = DAI_IMX_SAI; + cfg.channels = 2; + cfg.word_size = 16; + // Fill cfg_params + sai_cfg_params->mclk_id = 0; + sai_cfg_params->mclk_direction = 0; + sai_cfg_params->mclk_rate = 12288000; + sai_cfg_params->fsync_rate = 48000; + sai_cfg_params->bclk_rate = 1536000; //(48000 x 16 x 2) + sai_cfg_params->tdm_slots = 2; + sai_cfg_params->rx_slots = 0x3; + sai_cfg_params->tx_slots = 0x3; + sai_cfg_params->tdm_slot_width = 16; + cfg_params = sai_cfg_params; + ret = dai_config_set(dai_dev, &cfg, cfg_params); + if (ret) { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: dai_config_set failed %d", ret); + return CAPI_EFAILED; + } + +end: + if (sai_cfg_params) + posal_memory_free(sai_cfg_params); + + return capi_result; +} + +/*------------------------------------------------------------------------ + Function name: capi_nxp_device_init_param + DESCRIPTION: Sets either a parameter value or a parameter structure containing + multiple parameters. In the event of a failure, the appropriate error code is + returned. + -----------------------------------------------------------------------*/ +capi_err_t capi_nxp_device_init_param(capi_nxp_device_t *me_ptr) +{ + capi_err_t capi_result = CAPI_EOK; + uint32_t period_bytes = 0; + uint32_t period_count = 0; + + capi_result = capi_nxp_device_init_dma_buffer(me_ptr, &period_bytes, &period_count); + if (capi_result < 0) { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: Failed to initialize dma buffer"); + return CAPI_EFAILED; + } + + capi_result = capi_nxp_device_set_dma_config(me_ptr, period_bytes, period_count); + if (capi_result < 0) { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: Failed to set dma config"); + return CAPI_EFAILED; + } + + return capi_result; +} + +capi_err_t capi_nxp_device_init_dma_buffer(capi_nxp_device_t *me_ptr, uint32_t *pb, uint32_t *pc) +{ + capi_err_t capi_result = CAPI_EOK; + //struct capi_dai_data dai_data = me_ptr->dai_data; + struct dai_config cfg; + int ret = 0; + uint32_t channels = 2; /* 2 slots on the wire (WM8960 stereo frame) */ + uint32_t sample_bytes, frame_size, period_bytes, period_count; + uint32_t align = 0, addr_align, buf_size; + size_t heap_size = 0; + + ret = dai_config_get(dai_dev, &cfg, DAI_DIR_TX); + if (ret) { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: Failed to get dai configuration"); + return CAPI_EFAILED; + } + + //Get the DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT + ret = dma_get_attribute(dma_device, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, &addr_align); //128 + if (ret < 0) { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: Failed to get dma address align"); + return CAPI_EFAILED; + } + + //Get the DMA_ATTR_BUFFER_SIZE_ALIGNMENT + ret = dma_get_attribute(dma_device, DMA_ATTR_BUFFER_SIZE_ALIGNMENT, &align); // 4 + if (ret < 0) { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: Failed to get dma align"); + return CAPI_EFAILED; + } + + //Calculate frame size, period size, and period count from the values in cfg + sample_bytes = 2; /* 16-bit sample */ + frame_size = sample_bytes * channels; + period_bytes = 192; /* 48 samples x 2 bytes x 2 slots (1ms @ 48kHz) */ + period_count = 2; + buf_size = ALIGN_UP(period_count * period_bytes, align); + *pb = period_bytes; + *pc = period_count; + me_ptr->dma_buf_size = buf_size; + + AR_MSG(DBG_ERROR_PRIO, "dma_buf_size %u", buf_size); + //If dma buffer exists, change the dma_buffer size to the period size + if (me_ptr->dma_dest_addr) { + //Check if the dma_buffer is the same size as the period size, otherwise resize it + + //Use sys_heap_realloc? + AR_MSG(DBG_ERROR_PRIO, "empty block called"); + } else { + /* heap_size must cover: sys_heap metadata + alignment padding + buf_size + * sys_heap overhead ~ 2 * CHUNK_UNIT (64 bytes on 32-bit) + * alignment padding = addr_align - 1 (up to 127 bytes for 128-byte align) + * Use buf_size * 2 as a safe upper bound. + */ + heap_size = (size_t)(buf_size * 2); + AR_MSG(DBG_ERROR_PRIO, + "sys_heap_init: base=%p size=%u buf_size=%u addr_align=%u", + heapmem, heap_size, buf_size, addr_align); + sys_heap_init(&kernel_heap.heap, heapmem, heap_size); + + me_ptr->dma_src_addr = sys_heap_aligned_alloc(&kernel_heap.heap, addr_align, buf_size); + AR_MSG(DBG_ERROR_PRIO, + "sys_heap_aligned_alloc: ptr=%p align=%u size=%u %s", + me_ptr->dma_src_addr, addr_align, buf_size, + me_ptr->dma_src_addr ? "OK" : "FAILED - NULL returned"); + if (NULL == me_ptr->dma_src_addr) { + AR_MSG(DBG_ERROR_PRIO, + "CAPI_NXP_DEVICE: Failed to allocate DMA destination buffer"); + return CAPI_ENOMEMORY; + } + } + AR_MSG(DBG_ERROR_PRIO, "init_dma_buffer exit"); + return capi_result; +} + +capi_err_t capi_nxp_device_set_dma_config(capi_nxp_device_t *me_ptr, uint32_t period_bytes, uint32_t period_count) +{ + capi_err_t capi_result = CAPI_EOK; + struct dma_config *dma_cfg = NULL; + struct dma_block_config *dma_block_cfg = NULL; + struct dma_block_config *prev = NULL; + int ret, channel; + uint32_t fifo, burst_elems, max_block_count, buf_size; + + const struct dai_properties *props = dai_get_properties(dai_dev, DAI_DIR_TX, 0); + uint32_t hs = props->dma_hs_id; + burst_elems = props->fifo_depth; + fifo = props->fifo_address; + channel = hs & GENMASK(7, 0); + + AR_MSG(DBG_ERROR_PRIO, "channel %d", channel); + + ret = dma_get_attribute(dma_device, DMA_ATTR_MAX_BLOCK_COUNT, &max_block_count); //2 + if (ret < 0 || !max_block_count) { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: Failed to get block count"); + capi_result = CAPI_EFAILED; + goto end; + } + + if (max_block_count < period_count) { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: unsupported period count %d, max_block_count %d", period_count, max_block_count); + buf_size = period_count * period_bytes; + do { + if (IS_ALIGNED(buf_size, max_block_count)) { + period_count = max_block_count; + period_bytes = buf_size / period_count; + break; + } else { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: alignment error for buf_size = %d, block count = %d", + buf_size, max_block_count); + } + } while (--max_block_count > 0); + } + + dma_cfg = posal_memory_malloc(sizeof(struct dma_config), (POSAL_HEAP_ID)me_ptr->heap_mem.heap_id); + if (NULL == dma_cfg) { + AR_MSG(DBG_ERROR_PRIO, + "CAPI_NXP_DEVICE: Failed to allocate dma configuration pointer"); + capi_result = CAPI_ENOMEMORY; + goto end; + } + + + dma_cfg->channel_direction = MEMORY_TO_PERIPHERAL; + dma_cfg->source_data_size = 4; + dma_cfg->dest_data_size = dma_cfg->source_data_size; + dma_cfg->source_burst_length = 4; + dma_cfg->dest_burst_length = dma_cfg->source_burst_length; + dma_cfg->cyclic = 1; + dma_cfg->user_data = me_ptr; + dma_cfg->dma_callback = &capi_nxp_device_dma_callback; //Set to dma callback function + dma_cfg->block_count = max_block_count; + dma_cfg->dma_slot = (hs & GENMASK(15, 8)) >> 8; + + dma_block_cfg = posal_memory_malloc(sizeof(struct dma_block_config) * dma_cfg->block_count, (POSAL_HEAP_ID)me_ptr->heap_mem.heap_id); + if (NULL == dma_block_cfg) { + AR_MSG(DBG_ERROR_PRIO, + "CAPI_NXP_DEVICE: Failed to allocate DMA blocks"); + capi_result = CAPI_ENOMEMORY; + goto end; + } + + dma_cfg->head_block = dma_block_cfg; + for (int i = 0; i < dma_cfg->block_count; i++) { + dma_block_cfg->dest_scatter_en = 0; + dma_block_cfg->block_size = period_bytes; + dma_block_cfg->source_address = (uint32_t)me_ptr->dma_src_addr + i * period_bytes; + dma_block_cfg->dest_address = fifo; + dma_block_cfg->source_addr_adj = DMA_ADDR_ADJ_DECREMENT; + dma_block_cfg->dest_addr_adj = DMA_ADDR_ADJ_INCREMENT; + AR_MSG(DBG_ERROR_PRIO, + "DMA BD[%d]: block_cfg=%p src=0x%08x dst=0x%08x size=%u src_adj=%d dst_adj=%d", + i, dma_block_cfg, + dma_block_cfg->source_address, + dma_block_cfg->dest_address, + dma_block_cfg->block_size, + dma_block_cfg->source_addr_adj, + dma_block_cfg->dest_addr_adj); + prev = dma_block_cfg; + prev->next_block = ++dma_block_cfg; + } + if (prev) + prev->next_block = dma_cfg->head_block; + + me_ptr->z_config = dma_cfg; + + channel = dma_request_channel(dma_device, &channel); + if (channel < 0) { + AR_MSG(DBG_ERROR_PRIO, + "CAPI_NXP_DEVICE: DMA request channel failed"); + capi_result = CAPI_EFAILED; + goto end; + } + me_ptr->dma_chan_index = channel; + + ret = dma_config(dma_device, me_ptr->dma_chan_index, dma_cfg); + if (ret < 0) { + AR_MSG(DBG_ERROR_PRIO, + "CAPI_NXP_DEVICE: dma_config failed"); + capi_result = CAPI_EFAILED; + goto end; + } + + end: + if (capi_result != 0) { + if (dma_block_cfg) + posal_memory_free(dma_block_cfg); + if (dma_cfg) + posal_memory_free(dma_cfg); + + if (me_ptr->dma_src_addr) + sys_heap_free(&kernel_heap.heap, me_ptr->dma_src_addr); + } + AR_MSG(DBG_ERROR_PRIO, "set_dma_config exit"); + + return capi_result; +} + +void capi_nxp_device_reset(capi_nxp_device_t *me_ptr) +{ + if (me_ptr->z_config->head_block) + posal_memory_free(me_ptr->z_config->head_block); + + if (me_ptr->z_config) + posal_memory_free(me_ptr->z_config); + + if (me_ptr->dma_src_addr) + sys_heap_free(&kernel_heap.heap, me_ptr->dma_src_addr); +} + +void capi_nxp_device_stop(capi_nxp_device_t *me_ptr) +{ + //Stop the DMA and the DAI + dma_stop(dma_device, me_ptr->dma_chan_index); + dai_trigger(dai_dev, DAI_DIR_TX, DAI_TRIGGER_STOP); +} + +/*--------------------------------------------------------------------- + Function name: capi_nxp_device_dma_callback + DESCRIPTION: Will be called by the DMA driver when it needs more data + -----------------------------------------------------------------------*/ + +void capi_nxp_device_dma_callback(const struct device *dev, void *user_data, + uint32_t channel, int status) { + capi_nxp_device_t *me_ptr; + static uint32_t cb_count = 0; + cb_count++; + + //AR_MSG(DBG_ERROR_PRIO, "NXP CB [#%u]: ch=%u status=%d", cb_count, channel, status); + + if (user_data) + me_ptr = (capi_nxp_device_t *) user_data; + else { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: User data is NULL"); + return; + } + + /* --- SDMA register state --- */ + /*{ + SDMAARM_Type *sdma = (SDMAARM_Type *)0x30E00000; + AR_MSG(DBG_ERROR_PRIO, + "NXP CB [#%u] SDMA: CHNENBL[5]=0x%08x EVTOVR=0x%08x " + "HOSTOVR=0x%08x STOP_STAT=0x%08x INTR=0x%08x CHNPRI[1]=%u", + cb_count, + sdma->CHNENBL[5], + sdma->EVTOVR, + sdma->HOSTOVR, + sdma->STOP_STAT, + sdma->INTR, + sdma->SDMA_CHNPRI[1]); + }*/ + + /* --- SAI FIFO watermark vs burst size --- */ + { + I2S_Type *sai = (I2S_Type *)0x30c30000; + uint32_t tcsr = sai->TCSR; + uint32_t tcr1 = sai->TCR1; /* TX FIFO watermark in TCR1[2:0] */ + AR_MSG(DBG_ERROR_PRIO, + "NXP CB [#%u] SAI: TCSR=0x%08x TCR1=0x%08x " + "FRF=%d FEF=%d TE=%d FRDE=%d", + cb_count, tcsr, tcr1, + !!(tcsr & I2S_TCSR_FRF_MASK), + !!(tcsr & I2S_TCSR_FEF_MASK), + !!(tcsr & I2S_TCSR_TE_MASK), + !!(tcsr & I2S_TCSR_FRDE_MASK)); + } + + /* --- BD source addresses (cache coherency check) --- */ + /*{ + struct dma_block_config *bd0 = me_ptr->z_config->head_block; + struct dma_block_config *bd1 = bd0 ? bd0->next_block : NULL; + AR_MSG(DBG_ERROR_PRIO, + "NXP CB [#%u] BD: bd[0].src=0x%08x bd[0].dst=0x%08x " + "bd[1].src=0x%08x bd[1].dst=0x%08x", + cb_count, + bd0 ? bd0->source_address : 0, + bd0 ? bd0->dest_address : 0, + bd1 ? bd1->source_address : 0, + bd1 ? bd1->dest_address : 0); + }*/ + + /* Trigger the waiting thread to tell the container we need more data */ + if (me_ptr->i2s_driver.i2s_intf_state.trigger_signal_ptr) { + AR_MSG(DBG_ERROR_PRIO, "NXP CB [#%u]: sending signal ptr=%p", + cb_count, me_ptr->i2s_driver.i2s_intf_state.trigger_signal_ptr); + posal_signal_send((posal_signal_t)me_ptr->i2s_driver.i2s_intf_state.trigger_signal_ptr); + } else { + AR_MSG(DBG_ERROR_PRIO, "NXP CB [#%u]: trigger_signal_ptr is NULL", cb_count); + } +} + +/*--------------------------------------------------------------------- + Function name: capi_nxp_device_process_sink + DESCRIPTION: Processes an input buffer and generates an output buffer. + -----------------------------------------------------------------------*/ +capi_err_t capi_nxp_device_process_sink(capi_t *_pif, capi_stream_data_t *input[], capi_stream_data_t *output[]) +{ + capi_err_t capi_result = CAPI_EOK; + capi_nxp_device_t *me_ptr = (capi_nxp_device_t *)_pif; + struct dma_status stat; + int ret = 0; + uint16_t port = 0; + uint16_t i = 0; + uint32_t free_bytes = 0; + uint32_t buf_data_len = 0; + + static uint32_t sink_count = 0; + sink_count++; + + //AR_MSG(DBG_ERROR_PRIO, "process_sink [#%u]", sink_count); + + //Get data sizes and read/write buffer positions from the DMA + ret = dma_get_status(dma_device, me_ptr->dma_chan_index, &stat); + if (ret != 0) + { + AR_MSG(DBG_ERROR_PRIO, "dma_get_status failed rc: %d", ret); + capi_result = CAPI_EFAILED; + return capi_result; + } + + /* Periodic SAI register dump every 10 calls to catch stall */ + if ((sink_count % 10) == 1) { + I2S_Type *sai_base = (I2S_Type *)0x30c30000; + uint32_t tcsr = sai_base->TCSR; + uint32_t tcr3 = sai_base->TCR3; + AR_MSG(DBG_ERROR_PRIO, + "SINK [#%u] SAI: TCSR=0x%08x TCR3=0x%08x " + "TE=%d FEF=%d FWF=%d FRF=%d FRDE=%d", + sink_count, tcsr, tcr3, + !!(tcsr & I2S_TCSR_TE_MASK), + !!(tcsr & I2S_TCSR_FEF_MASK), + !!(tcsr & I2S_TCSR_FWF_MASK), + !!(tcsr & I2S_TCSR_FRF_MASK), + !!(tcsr & I2S_TCSR_FRDE_MASK)); + } + + free_bytes = stat.free; //The amount of free bytes in the output DMA buffer + buf_data_len = input[port]->buf_ptr[i].actual_data_len; + + //AR_MSG(DBG_ERROR_PRIO, "free_bytes: %u, buf_data_len: %u, stat.wr_pos:%u", free_bytes, buf_data_len, stat.write_position); + + /* Reload gating: only copy + flush + reload when at least one full period + * (192 bytes) of space is free in the DMA ring. */ + if (free_bytes >= 192) { + /* Write sine data to the correct ring buffer slot using write_position. + * stat.write_position is the offset within dma_src_addr where the + * CPU should write next — this ensures each BD gets fresh data. + */ + uint8_t *write_addr = (uint8_t *)me_ptr->dma_src_addr + stat.write_position; + memcpy(write_addr, sine_buf, 192); + /* Flush the CPU-written data so SDMA reads fresh bytes from DRAM (dcache is enabled) */ + sys_cache_data_flush_range(write_addr, 192); + /*AR_MSG(DBG_ERROR_PRIO, + "process_sink: wrote 192 bytes to %p (base=%p wr_pos=%u)", + write_addr, me_ptr->dma_src_addr, stat.write_position);*/ + + dma_reload(dma_device, me_ptr->dma_chan_index, 0, 0, 192); + } else { + AR_MSG(DBG_ERROR_PRIO, "process_sink: skip reload, free_bytes %u < 192", free_bytes); + } + + AR_MSG(DBG_ERROR_PRIO, "process_sink exit"); + + return capi_result; +} + + +capi_err_t capi_nxp_device_process_get_properties(capi_nxp_device_t *me_ptr, capi_proplist_t *proplist_ptr) +{ + capi_err_t capi_result = CAPI_EOK; + uint32_t fwk_extn_ids[1] = { 0 }; + fwk_extn_ids[0] = FWK_EXTN_STM; + + capi_basic_prop_t mod_prop; + mod_prop.init_memory_req = sizeof(capi_nxp_device_t); + mod_prop.stack_size = NXP_DEVICE_STACK_SIZE; + mod_prop.num_fwk_extns = NXP_DEVICE_NUM_FRAMEWORK_EXTENSIONS; + mod_prop.fwk_extn_ids_arr = fwk_extn_ids; + mod_prop.is_inplace = 0; // NA + mod_prop.req_data_buffering = 0; // NA + mod_prop.max_metadata_size = 0; // NA + + capi_result = capi_cmn_get_basic_properties(proplist_ptr, &mod_prop); + if (CAPI_EOK != capi_result) + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: Get common basic properties failed with result %lu", capi_result); + return capi_result; + } + + capi_prop_t *prop_ptr = proplist_ptr->prop_ptr; + for (uint32_t i = 0; i < proplist_ptr->props_num; i++) + { + capi_buf_t *payload_ptr = &prop_ptr[i].payload; + switch (prop_ptr[i].id) + { + case CAPI_INIT_MEMORY_REQUIREMENT: + case CAPI_STACK_SIZE: + case CAPI_NUM_NEEDED_FRAMEWORK_EXTENSIONS: + case CAPI_NEEDED_FRAMEWORK_EXTENSIONS: + case CAPI_OUTPUT_MEDIA_FORMAT_SIZE: + case CAPI_IS_INPLACE: + case CAPI_REQUIRES_DATA_BUFFERING: + case CAPI_OUTPUT_MEDIA_FORMAT_V2: + { + break; + } + case CAPI_PORT_DATA_THRESHOLD: + { + if (NULL == me_ptr) + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: null ptr while querying threshold"); + return CAPI_EBADPARAM; + } + + // based on int samples per period calculation (frame size in bytes) + /* mono graph input: 48 samples x 2 bytes/sample x 1 channel = 96 bytes (1ms period) */ + uint32_t threshold_in_bytes = 48 * 2 * 1; + + capi_result = capi_cmn_handle_get_port_threshold(&prop_ptr[i], threshold_in_bytes); + break; + } + case CAPI_INTERFACE_EXTENSIONS: + { + //capi_result = capi_hw_intf_cmn_update_intf_extn_status(payload_ptr); + break; + } + default: + { + AR_MSG(DBG_HIGH_PRIO, "CAPI_NXP_DEVICE: Skipped Get Property for 0x%x. Not supported.", prop_ptr[i].id); + capi_result |= CAPI_EUNSUPPORTED; + break; + } + } + } + return capi_result; +} + +/*------------------------------------------------------------------------ + Function name: capi_nxp_device_process_set_properties + DESCRIPTION: Function to set the properties for the nxp_device module + * -----------------------------------------------------------------------*/ +capi_err_t capi_nxp_device_process_set_properties(capi_nxp_device_t *me_ptr, capi_proplist_t *proplist_ptr) +{ + capi_err_t capi_result = CAPI_EOK; + int ret = 0; + //struct dma_status stat; + //uint32_t free_bytes; + uint32_t i = 0; + //AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: Set properties enter"); + + if (NULL == me_ptr) + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: Set property received null property."); + return CAPI_EBADPARAM; + } + + capi_result = capi_cmn_set_basic_properties(proplist_ptr, &me_ptr->heap_mem, &me_ptr->cb_info, FALSE); + + if (CAPI_EOK != capi_result) + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: Set basic properties failed with result %lu", capi_result); + return capi_result; + } + + + capi_prop_t *prop_ptr = proplist_ptr->prop_ptr; + + for (i = 0; i < proplist_ptr->props_num; i++) + { + capi_buf_t *payload_ptr = &prop_ptr[i].payload; + switch (prop_ptr[i].id) + { + case CAPI_HEAP_ID: + case CAPI_EVENT_CALLBACK_INFO: + case CAPI_ALGORITHMIC_RESET: + { + break; + } + case CAPI_INPUT_MEDIA_FORMAT_V2: + { + capi_result = CAPI_EOK; + + break; + } + case CAPI_PORT_NUM_INFO: + { + if (payload_ptr->actual_data_len >= sizeof(capi_port_num_info_t)) + { + capi_port_num_info_t *data_ptr = (capi_port_num_info_t *)payload_ptr->data_ptr; + if (!(data_ptr->num_input_ports == 1 && data_ptr->num_output_ports == 0) && + !(data_ptr->num_input_ports == 0 && data_ptr->num_output_ports == 1)) + { + AR_MSG(DBG_ERROR_PRIO, + "CAPI_NXP_DEVICE: Invalid number of input = %d, number of output ports = %d.", + data_ptr->num_input_ports, + data_ptr->num_output_ports); + CAPI_SET_ERROR(capi_result, CAPI_EBADPARAM); + } + } + else + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: Bad param size %lu", payload_ptr->actual_data_len); + CAPI_SET_ERROR(capi_result, CAPI_ENEEDMORE); + } + break; + } + case CAPI_CUSTOM_PROPERTY: + { + capi_custom_property_t *cust_prop_ptr = (capi_custom_property_t *)payload_ptr->data_ptr; + void * cust_payload_ptr = (void *)(cust_prop_ptr + 1); + + switch (cust_prop_ptr->secondary_prop_id) + { + case FWK_EXTN_PROPERTY_ID_STM_TRIGGER: + { + if (payload_ptr->actual_data_len < sizeof(capi_custom_property_t) + sizeof(capi_prop_stm_trigger_t)) + { + AR_MSG(DBG_ERROR_PRIO, + "CAPI_NXP_DEVICE: Insufficient payload size for stm trigger %d", + payload_ptr->actual_data_len); + return CAPI_EBADPARAM; + } + + //AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: Setting STM trigger"); + + // Get end point info + capi_prop_stm_trigger_t *trig_ptr = (capi_prop_stm_trigger_t *)cust_payload_ptr; + me_ptr->i2s_driver.i2s_intf_state.trigger_signal_ptr = trig_ptr->signal_ptr; + me_ptr->i2s_driver.i2s_intf_state.i2s_intr_cnt_ptr = trig_ptr->raised_intr_counter_ptr; + + break; + } + case FWK_EXTN_PROPERTY_ID_STM_CTRL: + { + //AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: Setting STM CTRL enter"); + if (payload_ptr->actual_data_len < sizeof(capi_prop_stm_ctrl_t) + sizeof(capi_custom_property_t)) + { + /* Insufficient payload size */ + AR_MSG(DBG_ERROR_PRIO, "invalid payload size"); + capi_result |= CAPI_ENEEDMORE; + break; + } + + capi_prop_stm_ctrl_t *ctr_ptr = (capi_prop_stm_ctrl_t *)cust_payload_ptr; + + if (ctr_ptr->enable){ + + //AR_MSG(DBG_ERROR_PRIO, "Start DMA"); + ret = dma_start(dma_device, me_ptr->dma_chan_index); + if (ret < 0) { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: DMA start failed rc: %d", ret); + return CAPI_EFAILED; + } + + //Start the DAI + dai_trigger(dai_dev, DAI_DIR_TX, DAI_TRIGGER_START); + + /* SAI TCSR status after trigger + * SAI3 base = 0x30c30000 on i.MX8MP + * TCSR offset = 0x00, TCR3 offset = 0x0C + */ + /*{ + I2S_Type *sai_base = (I2S_Type *)0x30c30000; + uint32_t tcsr = sai_base->TCSR; + uint32_t tcr3 = sai_base->TCR3; + AR_MSG(DBG_ERROR_PRIO, + "SAI post-start: TCSR=0x%08x TCR3=0x%08x " + "TE=%d FEF=%d FWF=%d FRF=%d FRDE=%d", + tcsr, tcr3, + !!(tcsr & I2S_TCSR_TE_MASK), + !!(tcsr & I2S_TCSR_FEF_MASK), + !!(tcsr & I2S_TCSR_FWF_MASK), + !!(tcsr & I2S_TCSR_FRF_MASK), + !!(tcsr & I2S_TCSR_FRDE_MASK)); + }*/ + + AR_MSG(DBG_ERROR_PRIO, "DMA & DAI start done"); + } + else{ + AR_MSG(DBG_ERROR_PRIO, "disable: True"); + } + break; + } + default: + { + AR_MSG(DBG_HIGH_PRIO, "CAPI_NXP_DEVICE: Unknown Custom Property[%d]", cust_prop_ptr->secondary_prop_id); + capi_result |= CAPI_EUNSUPPORTED; + break; + } + } // inner switch - CUSTOM Properties + break; + } + case CAPI_MODULE_INSTANCE_ID: + { + if (payload_ptr->actual_data_len >= sizeof(capi_module_instance_id_t)) + { + capi_module_instance_id_t *data_ptr = (capi_module_instance_id_t *)payload_ptr->data_ptr; + me_ptr->iid = data_ptr->module_instance_id; + AR_MSG(DBG_LOW_PRIO, + "CAPI_NXP_DEVICE: This module-id 0x%08lX, instance-id 0x%08lX", + data_ptr->module_id, + me_ptr->iid); + } + else + { + AR_MSG(DBG_ERROR_PRIO, + "CAPI_NXP_DEVICE: Set, Param id 0x%lx Bad param size %lu", + (uint32_t)prop_ptr[i].id, + payload_ptr->actual_data_len); + CAPI_SET_ERROR(capi_result, CAPI_ENEEDMORE); + } + break; + } + case CAPI_LOGGING_INFO: + { + if (payload_ptr->actual_data_len >= sizeof(capi_logging_info_t)) + { + capi_logging_info_t *data_ptr = (capi_logging_info_t *)payload_ptr->data_ptr; + me_ptr->log_id = data_ptr->log_id; + me_ptr->log_id_reserved_mask = data_ptr->log_id_mask; + AR_MSG(DBG_LOW_PRIO, + "CAPI_NXP_DEVICE: log-id 0x%08lX, mask 0x%08lX", + me_ptr->log_id, + me_ptr->log_id_reserved_mask); + } + else + { + AR_MSG(DBG_ERROR_PRIO, + "CAPI_NXP_DEVICE: Set, Param id 0x%lx Bad param size %lu", + (uint32_t)prop_ptr[i].id, + payload_ptr->actual_data_len); + CAPI_SET_ERROR(capi_result, CAPI_ENEEDMORE); + } + break; + } + default: + { + AR_MSG(DBG_ERROR_PRIO, "CAPI_NXP_DEVICE: Skipping set prop, unsupported param[%d]", prop_ptr[i].id); + capi_result |= CAPI_EUNSUPPORTED; + continue; + } + } /* Outer switch - Generic CAPI Properties */ + } /* Loop all properties */ + + return capi_result; +} \ No newline at end of file