From 06251a9cde528f753a51f18bc0cb1539b66d8698 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 17 Jul 2020 19:34:41 +0100 Subject: [PATCH] ipc2: introduce IPC2 ABI. About ---- IPC2 is a MAJOR ABI update that is not fully backwards compatible with IPC1.x (using MAJOR 3 today). IPC2 has the following high level aims 1) Straight forward message life cycle management. Add/deprecate/modify messages with minimal pain across all messengers. 2) Provide a transition path for code that uses existing or legacy IPC ABI's so that it can incrementally add IPC2.x features and support. 3) Provide high density messaging similar to vanilla C structs. 4) Message discovery - clients can determine supported message types and fields at runtime. 5) Standard metadata for all messages with optional extra metadata. Message Header -------------- IPC2 messages will all use a standard header that contains generic message metadata with optional mesage metedata. This will be used by messengers to help process the message efficiently and securely. Messages are now catergorized into class, subclass and action in order to cleanly integrate into the correct driver, feature and use case infrastrcture within FW and SW. See header.h Messaging Enumeration --------------------- The FW extended manifest data will contain a list of supported messages classes, subclasses and actions for this individual FW release. This allows SW to scan the manifest and determine which driver, feature and use cases are supported. The SW can then make decisions at runtime to correctly support this individual FW release. See manifest.h Message Data Format ------------------- Each piece of data sent in a message must be tagged with an ID that the messengers all understand. This {id, data} tuple is the basis for all IPC2 communication as it's generic and has relatively simple life cycle requirements. i.e. tuples can be easily added, removed without breaking breaking binary ABIs or requiring all code to be rebuilt. IPC2 also provides a pathway for migrating legacy code to IPC2. i.e. IPC2 allows existing data messages to be sent using IPC2 with the small addition of a 1 word header that can be initially ignored by older messengers. See message.h Signed-off-by: Liam Girdwood --- src/include/ipc2/header.h | 367 ++++++++++++++++++++++++++++++++++++ src/include/ipc2/manifest.h | 100 ++++++++++ src/include/ipc2/message.h | 174 +++++++++++++++++ 3 files changed, 641 insertions(+) create mode 100644 src/include/ipc2/header.h create mode 100644 src/include/ipc2/manifest.h create mode 100644 src/include/ipc2/message.h diff --git a/src/include/ipc2/header.h b/src/include/ipc2/header.h new file mode 100644 index 000000000000..3314b3368228 --- /dev/null +++ b/src/include/ipc2/header.h @@ -0,0 +1,367 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +/** + * \file include/ipc2/header.h + * \brief IPC header + */ + +#ifndef __IPC_2_HEADER_H__ +#define __IPC_2_HEADER_H__ + +#include + +/** \addtogroup sof_uapi uAPI + * SOF uAPI specification. + * + * All standard mailbox IPC2 messages between host driver and DSP start + * with a common IPC header structure. This structure is + * + * IPC2.0 message header is 1 - 5 words made up as follows : + * + * The IPC 2 header works at a high level on the basic principle + * of a mandatory header metadata followed by optional message metadata. + * + * +------------------------+-----------+---------+---------------+ + * | struct sof_ipc2_hdr | Mandatory | 1 word | | + * +------------------------+-----------+---------+---------------+ + * | struct sof_ipc2_route | Optional | 2 words | hdr.route = 1 | + * +------------------------+-----------+---------+---------------+ + * | struct sof_ipc2_size | Optional | 1 word | hdr.size = 1 | + * +------------------------+-----------+---------+---------------+ + * | struct sof_ipc2_elem | Optional | 1 word | hdr.elems = 1 | + * +------------------------+-----------+---------+---------------+ + * | | + * | Message body follows here | + * | 1) Tuple elements | + * | 2) Private data | + * +--------------------------------------------------------------+ + * + * The optional message metadata is ordered, i.e. it always appears in the + * same order if used (and usage is determined by status bits in + * struct sof_ipc2_hdr). + * + * The header is designed to support the following use cases. + * + * 1) Nano messaging via 32bit message and reply. i.e. sending header and + * replying with header only is enough for some use cases like starting and + * stopping global events. + * + * 2) Micro messaging via 64bit message and reply - send and reply header with + * micro tuple. Expands uses cases from 1) to support stopping and starting + * targeted events. + * + * 3) Variable size message and reply - like 1) and 2) but messages and replies + * can be variable in size from 32bits upwards. Any use case can be supported + * here since there are no message restrictions. + * + * 4) Support of legacy ABIs. The header can be prefixed to legacy ABIs by + * using hdr.block = 1 and appending any legacy ABI structure. This allows + * a stable migration path with a small additional word prefixed to + * legacy ABI IPCs. + * + * 5) High priority messaging. The header now supports a hint for incoming + * message Q handlers so that they can prioritise real time high priority + * messages over standard batch messages. e.g stream start for low latency + * stream could be processed in the Q before sensor config message. + * + * 6) Datagram mode (no reply needed). The header can tell the message receiver + * that the message does not need to be acknowledged with a reply. Useful + * where the sender may be sending high volume, short lifetime information + * or where the sender does not care about reply (to save cycles on both + * sender and receiver). Door bell protocol would still be followed. + * + * 7) Message addressing. 32bit sender and receiver addresses can be added in + * header so that messages can be more easily routed to the correct + * destinations. Broadcast messages also supported. + * @{ + */ + +/** + * Structure Header - Mandatory. + * Header metadata for all IPC commands. Identifies IPC message. + * Class spelled with K for C++ users. + * + * @klass: Message feature class. e.g. audio, sensor, debug. + * @subklass: Message sub feature. e.g. PCM, kcontrol, Compressed PCM + * @action: Message action. e.g. Start (PCM), Get (kcontrol value) + * @ack: Reply - IPC success, other reply data may or may not follow. + */ +struct sof_ipc2_hdr { + uint32_t klass : 8; /**< class ID */ + uint32_t subklass : 8; /**< subclass ID */ + uint32_t action : 8; /**< action ID */ + uint32_t ack : 1; /**< message is a reply - success */ + uint32_t nack : 1; /**< message is a reply - fail */ + uint32_t priority : 1; /**< 0 normal, 1 high */ + uint32_t datagram : 1; /**< is datagram - no reply needed */ + uint32_t route : 1; /**< routing data follows */ + uint32_t size : 1; /**< size follows */ + uint32_t elems : 1; /**< data elems follows */ + uint32_t block : 1; /**< data block follows */ +} __attribute__((packed)); + +/* + * Structure Route - Optional + * Header routing data for this message. Allows 1:1 and 1:N messaging. + */ + +#define SOF_IPC2_ROUTE_BROADCAST 0xFFFFFFFF + +struct sof_ipc2_route { + uint32_t receiver; /**< receiver ID */ + uint32_t sender; /**< sender ID */ +} __attribute__((packed)); + +/* + * Structure Size - Optional. + * Header containing message size + */ +struct sof_ipc2_size { + uint32_t size; /**< size in words */ +} __attribute__((packed)); + +/* + * Structure Elems - Optional. + * Header containing number of tuple elements + */ +struct sof_ipc2_elems { + uint32_t num_elems; /**< number of data elems */ +} __attribute__((packed)); + + +/* + * Convenience macros to get struct offsets from header. + */ + +/* Internal macros to get header ponters. */ +#define _SOF_IPC2_HDR_ROUTE_ADD(hdr) \ + (hdr->route ? sizeof(struct sof_ipc2_route) : NULL) +#define _SOF_IPC2_HDR_SIZE_ADD(hdr) \ + (hdr->size ? sizeof(struct sof_ipc2_size) : NULL) +#define _SOF_IPC2_HDR_ELEM_ADD(hdr) \ + (hdr->elem ? sizeof(struct sof_ipc2_elem) : NULL) +#define _SOF_IPC2_HDR_PDATA_ADD(hdr) \ + (hdr->block ? sizeof(struct sof_ipc2_elem) : NULL) + +/* get header route pointer or NULL */ +#define SOF_IPC2_HDR_GET_ROUTE_PTR(hdr) \ + (hdr->route ? (void *)hdr + \ + _SOF_IPC2_HDR_ROUTE_ADD(hdr) : NULL) + +/* get header route pointer or NULL */ +#define SOF_IPC2_HDR_GET_SIZE_PTR(hdr) \ + (hdr->size ? (void *)hdr + \ + _SOF_IPC2_HDR_SIZE_ADD(hdr) + \ + _SOF_IPC2_HDR_ROUTE_ADD(hdr) : NULL) + +/* get header elem pointer or NULL */ +#define SOF_IPC2_HDR_GET_ELEM_PTR(hdr) \ + (hdr->elem ? (void *)hdr + \ + _SOF_IPC2_HDR_ELEM_ADD(hdr) + \ + _SOF_IPC2_HDR_SIZE_ADD(hdr) + \ + _SOF_IPC2_HDR_ROUTE_ADD(hdr) : NULL) + +/* get header elem pointer or NULL */ +#define SOF_IPC2_HDR_GET_PDATA_PTR(hdr) \ + (hdr->block ? (void *)hdr + \ + _SOF_IPC2_HDR_PDATA_OFFSET(hdr) \ + _SOF_IPC2_HDR_ELEM_ADD(hdr) + \ + _SOF_IPC2_HDR_SIZE_ADD(hdr) + \ + _SOF_IPC2_HDR_ROUTE_ADD(hdr) : NULL) + + +/* get headers size */ +#define SOF_IPC2_HDR_GET_HDR_SIZE(hdr) \ + _SOF_IPC2_HDR_PDATA_OFFSET(hdr) \ + _SOF_IPC2_HDR_ELEM_ADD(hdr) + \ + _SOF_IPC2_HDR_SIZE_ADD(hdr) + \ + _SOF_IPC2_HDR_ROUTE_ADD(hdr) + +/** \name IPC class + * @{ + * Top Level message class - Used to route message to correct subsystem + */ + +#define SOF_IPC_CLASS_SYSTEM 0x1 +#define SOF_IPC_CLASS_PM 0x2 +#define SOF_IPC_CLASS_DEBUG 0x3 +#define SOF_IPC_CLASS_TPLG 0x4 +#define SOF_IPC_CLASS_AUDIO 0x5 +#define SOF_IPC_CLASS_SENSOR 0x6 +#define SOF_IPC_CLASS_SHELL 0x7 + +/* + * Legacy IPC classes - reserve space at the block end. + */ +#define SOF_IPC_CLASS_PDATA_CAVS 0xf0 +#define SOF_IPC_CLASS_PDATA_SOF1 0xf1 + + +/** @} */ + +/** \name IPC Generic class - sub-class + * @{ + */ + +#define SOF_IPC_SYS_BOOT 0x1 +#define SOF_IPC_SYS_PANIC 0x2 + +/** @} */ + +/* + * Subclasses - Used to route message with the subsystem. + */ + +/** \name IPC PM sub-class + * @{ + */ + +#define SOF_IPC_PM_CTX 0x1 +#define SOF_IPC_PM_CLK 0x2 +#define SOF_IPC_PM_CORE 0x3 +#define SOF_IPC_PM_GATE 0x4 + +/** @} */ + +/** \name IPC DEBUG class - sub-class + * @{ + */ +#define SOF_IPC_DEBUG_TRACE 0x1 +#define SOF_IPC_DEBUG_GDB 0x2 +#define SOF_IPC_DEBUG_TEST 0x3 +#define SOF_IPC_DEBUG_PROBE 0x4 + +/** @} */ + +/** \name IPC TPLG class - sub-class + * @{ + */ +#define SOF_IPC_TPLG_COMP 0x1 +#define SOF_IPC_TPLG_PIPE 0x2 +#define SOF_IPC_TPLG_BUFFER 0x3 + +/** @} */ + +/** \name IPC Audio class - sub-class + * @{ + */ + +#define SOF_IPC_AUDIO_COMP 0x1 +#define SOF_IPC_AUDIO_STREAM 0x2 +#define SOF_IPC_AUDIO_DAI 0x3 + +/** @} */ + +/* IPC Actions - each subclass has a set of IPC actions. */ + +/** \name System Actions + * @{ + */ +/** SOF_IPC_REPLY actions */ +#define SOF_IPC_SYS_BOOT_FAIL 0x001 +#define SOF_IPC_SYS_BOOT_DONE 0x002 +#define SOF_IPC_SYS_ALERT_NONFATAL 0x003 +#define SOF_IPC_SYS_ALERT_FATAL 0x004 + +/** @} */ + +/** \name PM Actions + * @{ + */ +/** SOF_IPC_PM_CTX actions */ +#define SOF_IPC_PM_CTX_SAVE 0x001 +#define SOF_IPC_PM_CTX_RESTORE 0x002 +#define SOF_IPC_PM_CTX_SIZE 0x003 +/** SOF_IPC_PM_CLK actions */ +#define SOF_IPC_PM_CLK_SET 0x004 +#define SOF_IPC_PM_CLK_GET 0x005 +#define SOF_IPC_PM_CLK_REQ 0x006 +/** SOF_IPC_PM_CORE actions */ +#define SOF_IPC_PM_CORE_ENABLE 0x007 +/** SOF_IPC_PM_GATE actions */ +#define SOF_IPC_PM_GATE_CLK 0x008 + +/** @} */ + +/** \name DEBUG Actions + * @{ + */ +/** SOF_IPC_DEBUG_TRACE actions */ +#define SOF_IPC_DEBUG_TRACE_DMA_PARAMS 0x001 +#define SOF_IPC_DEBUG_TRACE_DMA_POSITION 0x002 +#define SOF_IPC_DEBUG_TRACE_DMA_PARAMS_EXT 0x003 +/** SOF_IPC_DEBUG_GDB actions */ +/** TODO: add SOF_IPC_DEBUG_GDB actions */ +/** SOF_IPC_DEBUG_TEST actions */ +#define SOF_IPC_DEBUG_TEST_IPC_FLOOD 0x001 +/** SOF_IPC_DEBUG_PROBE actions */ +#define SOF_IPC_DEBUG_PROBE_INIT 0x001 +#define SOF_IPC_DEBUG_PROBE_DEINIT 0x002 +#define SOF_IPC_DEBUG_PROBE_DMA_ADD 0x003 +#define SOF_IPC_DEBUG_PROBE_DMA_INFO 0x004 +#define SOF_IPC_DEBUG_PROBE_DMA_REMOVE 0x005 +#define SOF_IPC_DEBUG_PROBE_POINT_ADD 0x006 +#define SOF_IPC_DEBUG_PROBE_POINT_INFO 0x007 +#define SOF_IPC_DEBUG_PROBE_POINT_REMOVE 0x008 +/** @} */ + +/** \name TPLG class actions + * @{ + */ +/** SOF_IPC_TPLG_COMP actions */ +#define SOF_IPC_TPLG_COMP_NEW 0x001 +#define SOF_IPC_TPLG_COMP_FREE 0x002 +#define SOF_IPC_TPLG_COMP_CONNECT 0x003 +/** SOF_IPC_TPLG_PIPE actions */ +#define SOF_IPC_TPLG_PIPE_NEW 0x010 +#define SOF_IPC_TPLG_PIPE_FREE 0x011 +#define SOF_IPC_TPLG_PIPE_CONNECT 0x012 +#define SOF_IPC_TPLG_PIPE_COMPLETE 0x013 +/** SOF_IPC_TPLG_BUFFER actions */ +#define SOF_IPC_TPLG_BUFFER_NEW 0x020 +#define SOF_IPC_TPLG_BUFFER_FREE 0x021 + +/** @} */ + +/** \name Audio class actions + * @{ + */ +/** SOF_IPC_AUDIO_COMP actions */ +#define SOF_IPC_AUDIO_COMP_SET_VALUE 0x001 +#define SOF_IPC_AUDIO_COMP_GET_VALUE 0x002 +#define SOF_IPC_AUDIO_COMP_SET_DATA 0x003 +#define SOF_IPC_AUDIO_COMP_GET_DATA 0x004 +#define SOF_IPC_AUDIO_COMP_NOTIFICATION 0x005 +/** SOF_IPC_AUDIO_STREAM actions */ +#define SOF_IPC_AUDIO_STREAM_PCM_PARAMS 0x001 +#define SOF_IPC_AUDIO_STREAM_PCM_PARAMS_REPLY 0x002 +#define SOF_IPC_AUDIO_STREAM_PCM_FREE 0x003 +#define SOF_IPC_AUDIO_STREAM_TRIG_START 0x004 +#define SOF_IPC_AUDIO_STREAM_TRIG_STOP 0x005 +#define SOF_IPC_AUDIO_STREAM_TRIG_PAUSE 0x006 +#define SOF_IPC_AUDIO_STREAM_TRIG_RELEASE 0x007 +#define SOF_IPC_AUDIO_STREAM_TRIG_DRAIN 0x008 +#define SOF_IPC_AUDIO_STREAM_TRIG_XRUN 0x009 +#define SOF_IPC_AUDIO_STREAM_POSITION 0x00a +#define SOF_IPC_AUDIO_STREAM_VORBIS_PARAMS 0x010 +#define SOF_IPC_AUDIO_STREAM_VORBIS_FREE 0x011 +/** SOF_IPC_AUDIO_DAI actions */ +#define SOF_IPC_AUDIO_DAI_CONFIG 0x001 +#define SOF_IPC_AUDIO_DAI_LOOPBACK 0x002 + +/** @} */ + +/** \name IPC Message Definitions + * @{ + */ + + +/** @} */ + +/** @}*/ + +#endif /* __IPC_2_HEADER_H__ */ diff --git a/src/include/ipc2/manifest.h b/src/include/ipc2/manifest.h new file mode 100644 index 000000000000..4424b16bb61f --- /dev/null +++ b/src/include/ipc2/manifest.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#ifndef SRC_INCLUDE_IPC2_MANIFEST_H_ +#define SRC_INCLUDE_IPC2_MANIFEST_H_ + +#include +#include + +/* + * IPC2 uses the extended manifest to tell the kernel about the supported + * firmware features and IPC ABI. This way the kernel knows exactly how to + * communicate directly with firmware for each feature and use case for + * each version of firmware. + * + * The extended manifest contains the following IPC2 information that is + * used by the drivers + * + * 1) A list of features classes - this is used by the core driver to + * enumerate feature drivers like audio, sensing, shell, debug, etc. + * i.e. if feature class is listed in the manifest then the core driver + * should enumerate that feature driver. The feature driver can then + * parse the manifest data relevant to itself. + * + * 2) A list of sub classes per feature - this is used by the feature driver + * to determine the feature sub classes supported by the firmware. e.g for + * audio, the feature driver sub classes could be PCMs, controls, media + * decode, WoV, etc. + * + * 3) A list of actions per sub class - this is used by the feature driver to + * determine the ABI used for each sub class action. This includes + * mandatory and optional parameters for each sub class action so that + * feature driver can build the correct IPC per ABI version. + */ + +/* + * IPC2 Action + * + * Contains a list of optional and mandatory tuples needed by the driver + * to perform this action. Tuples are uint16_t. Structure is aligned on + * word. + */ +struct sof_ipc2_action { + uint32_t action_id; /**< action ID - maps to IPC message action */ + uint32_t action_size; /**< action size in bytes*/ + uint16_t num_mandatory; /**< number of mandatory tuple IDs */ + uint16_t num_optional; /**< number of optional tuple IDs */ + + /* tuple IDs follow here - mandatory then optional */ + uint16_t tuple[0]; /**< size is num_mandatory + num_optional */ +} __attribute__((packed)); + + +/* + * IPC2 Feature Sub Class - (spelled with a K for C++ users) + * + * Describes the capabilities of a use case within a feature driver. + */ +struct sof_ipc2_subclass { + uint32_t subclass_id; /**< subclass ID - use to map feature use case */ + uint32_t subclass_size; /**< subclass size in bytes */ + uint32_t num_actions; /**< number of actions in this subclass */ + + /* action data follows here */ + struct sof_ipc2_action actions[0]; /**< actions - size is num_actions */ +} __attribute__((packed)); + +/* + * IPC2 Feature Class - (spelled with a K for C++ users) + * + * Describes the capabilities of a feature driver. + */ +struct sof_ipc2_klass { + uint32_t klass_id; /**< class ID - used to match feature driver */ + uint32_t klass_size; /**< class size in bytes */ + uint32_t num_subklasses; /**< number of subclasses in this class */ + + /* sub class data follows here */ + struct sof_ipc2_subclass subklass[0]; /*<< subklasses - size is num_subclasses */ +} __attribute__((packed)); + + +/* + * IPC2 manifest header. + * + * Identifies this data as IPC2 extended manifest and first feature class + * follows the end of the structure. + */ +struct sof_ipc2_manifest_hdr { + struct ext_man_elem_header hdr; /**< extended manifest header for IPC2 */ + uint32_t num_klasses; /**< number of classes in manifest */ + + /* class data follows here */ + struct sof_ipc2_klass klass[0]; /**< klasses - size is num_klasses */ +} __attribute__((packed)); + +#endif diff --git a/src/include/ipc2/message.h b/src/include/ipc2/message.h new file mode 100644 index 000000000000..677e4c468723 --- /dev/null +++ b/src/include/ipc2/message.h @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#ifndef SRC_INCLUDE_IPC2_MESSAGE_H_ +#define SRC_INCLUDE_IPC2_MESSAGE_H_ + +#include + +/* + * High Level + * ========== + * + * IPC2 messaging works at a high level on the basic principle of a standard + * header followed by either a tuple array of data OR a private data structure. + * + * Tuple Mode + * ---------- + * + * +------------------------+ + * | IPC2 header | + * | route (optional) | + * | size (mandatory) | + * | elems (mandatory) | + * +------------------------+ + * | Tuple ID | Data | + * +------------------------+ + * | Tuple ID | Data | + * +------------------------+ + * | Tuple ID | Data | + * +------------------------+ + * | etc ...................| + * +------------------------+ + * + * (example 1 - IPC2 header with tuples) + * + * The tuple data is either fixed size or variable size and the tuples + * are unordered in the IPC message. + * + * Tuple mode is enabled by setting hdr.size = 1 and hdr.elems = 1 + * + * Tuple data can be represented by creating arrays using any combinations of + * struct ipc2_elem_std, ipc2_elem_micro and ipc2_elem_micro_array. This + * provides flexibility over data expression and data density. + * + * + * Private Data Mode + * ----------------- + * + * +------------------------+ + * | IPC2 header | + * | route (optional) | + * | size (optional) | + * | elems (optional) | + * +------------------------+ + * | Private data block | + * +------------------------+ + * + * (example 2 - IPC2 header with private data) + * + * The private data can be anything - The primary use case is C data structures + * from previous IPC ABIs. Private data only mode does not use the tuples below + * but uses existing or legacy IPC ABI structures. + * + * Private data block only mode is enabled by setting hdr.block = 1. + * + * + * Tuples + * ====== + * + * Tuples come in two types where type is determined by MSB of tuple ID. This + * is to provide flexibility for message density and data size. i.e. small + * tuple dense messages are supported alongside large messages with variable + * tuple density. + * + * 1) Standard tuple element - Minimum 2 words (1 data word) - max 256kB + * + * 2) Micro tuple element - Fixed size 1 word (1 data short). + * + * Where the tuple IDs are in a continuous range then the protocol can compress + * tuples and omit IDs for each tuple are ID[0] (the base tuple ID) meaning the + * tuple array is data only with each subsequent word/short being the next + * element in the array. + * + * Tuple IDs + * --------- + * + * The tuple ID is a 15bit number unique only to the class, subclass, AND action + * meaning each action can have up to 2^14 standard tuple data elements and 2^14 + * micro tuple elements or 2^15 data element IDs in total. + * + * This tuple ID range gives enough head room for ID deprication and new ID + * additions without having to add and code new actions. + */ + + +/* + * IPC2.0 Tuple ID. + * + * The tuple ID has a 15 bit ID value and a 1 bit type flag indication whether + * it uses struct ipc2_std_elem or struct ipc2_micro_elem for data below. + * + * The array flag indicates that the protocol is sending a continuous sequence + * of tuple IDs and has compressed the data. + */ + +struct ipc2_tuple { + uint16_t array : 1; /* tuple is an array of tuples NOT part of ID */ + uint16_t hd : 1; /* tuple ID - high density "micro elem" */ + uint16_t id : 14; /* tuple ID - specific to class/subclass/action */ +} __attribute__((packed)); + +/* + * IPC2.0 - generic tuple data element. + * + * Generic tuple type that can be used for either a single tuple + * (tuple.array = 0) or for an array of tuples (tuple.array = 1). + * + * Single tuple mode can represent from 4 bytes to 256kB of data. + * Array mode can represent 2^16 tuples of size 4 bytes. + * + * Tuple RAW IDs - 0x0000 ... 0x7FFF (as tuple.hd is set to 0). Array uses + * tuple ID as base array index. + */ +struct ipc2_elem_std { + struct ipc2_tuple tuple; /* tuple ID and type */ + union { + uint16_t size; /* data size in words - max 256kB */ + uint16_t count; /* number of data items in tuple array */ + }; + uint32_t data[]; /* tuple data */ +} __attribute__((packed)); + +/* + * IPC2.0 - Micro tuple element. + * + * Micro tuple type that can be used for 2 bytes of data. + * Tuple RAW IDs - 0x8000 ... 0xFFFF (as tuple.hd = 1) + */ +struct ipc2_elem_micro { + struct ipc2_tuple tuple; /* tuple ID and type */ + uint16_t data; /* tuple data */ +} __attribute__((packed)); + +/* + * IPC2.0 - Micro tuple element array. + * + * Micro tuple array type that can be used for array of 2 byte data. + * Tuple RAW IDs - 0x8000 ... 0xFFFF (as tuple.hd = 1 and tuple.array = 1) + */ +struct ipc2_elem_micro_array { + struct ipc2_tuple tuple; /* tuple ID and type */ + uint16_t count; /* tuple array count */ + uint16_t data[]; /* tuple data */ +} __attribute__((packed)); + +/* + * Tuple elem convenience macros + */ + +/* size of micro tuple elem */ +/* get size of standard tuple and data in bytes */ +#define SOF_IPC_ELEM_MICRO_SIZE(elem) \ + (elem->tuple.array ? \ + sizeof(ipc2_elem_micro) + elem->count * sizeof(uint16_t) :\ + sizeof(ipc2_elem_micro) + +/* get size of standard tuple and data in bytes */ +#define SOF_IPC_ELEM_STD_SIZE(elem) \ + (sizeof(ipc2_elem_std) + elem->size * sizeof(uint32)) + +#endif /* SRC_INCLUDE_IPC2_MESSAGE_H_ */