From 6571c7283e0d4ea63b39772eabcca0c1a7094a66 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Sun, 25 Apr 2021 22:18:22 +0100 Subject: [PATCH 01/13] ipc: abstraction: abstract pipeline_new() to support other IPC ABIs Add support to the IPC pipeline logic to support creation of pipelines using generic IPC ABI. Signed-off-by: Liam Girdwood --- src/include/ipc4/pipeline.h | 379 +++++++++++++++++++++++++++++++++ src/include/sof/ipc/topology.h | 19 +- src/ipc/helper-ipc3.c | 4 +- tools/testbench/topology.c | 2 +- 4 files changed, 400 insertions(+), 4 deletions(-) create mode 100644 src/include/ipc4/pipeline.h diff --git a/src/include/ipc4/pipeline.h b/src/include/ipc4/pipeline.h new file mode 100644 index 000000000000..8ee8d2ce214e --- /dev/null +++ b/src/include/ipc4/pipeline.h @@ -0,0 +1,379 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + */ + +/** + * \file include/ipc4/pipeline.h + * \brief IPC4 pipeline definitions + */ + +#ifndef __SOF_IPC4_PIPELINE_H__ +#define __SOF_IPC4_PIPELINE_H__ + +#include + +#define IXC_STATUS_BITS 24 + +//! Pipeline priority +enum ipc4_pipeline_priority { + //! Priority 0 (run first) + SOF_IPC4_PIPELINE_PRIORITY_0 = 0, + //! Priority 1 + SOF_IPC4_PIPELINE_PRIORITY_1, + //! Priority 2 + SOF_IPC4_PIPELINE_PRIORITY_2, + //! Priority 3 + SOF_IPC4_PIPELINE_PRIORITY_3, + //! Priority 4 + SOF_IPC4_PIPELINE_PRIORITY_4, + //! Priority 5 + SOF_IPC4_PIPELINE_PRIORITY_5, + //! Priority 6 + SOF_IPC4_PIPELINE_PRIORITY_6, + //! Priority 7 + SOF_IPC4_PIPELINE_PRIORITY_7, + //! Max (and lowest) priority + SOF_IPC4_MAX_PIPELINE_PRIORITY = SOF_IPC4_PIPELINE_PRIORITY_7 +}; + +//! Pipeline State +enum ipc4_pipeline_state { + //! Invalid value + SOF_IPC4_PIPELINE_STATE_INVALID = 0, + //! Created but initialization incomplete + SOF_IPC4_PIPELINE_STATE_UNINITIALIZED = 1, + //! Resets pipeline + SOF_IPC4_PIPELINE_STATE_RESET = 2, + //! Pauses pipeline + SOF_IPC4_PIPELINE_STATE_PAUSED = 3, + //! Starts pipeline + SOF_IPC4_PIPELINE_STATE_RUNNING = 4, + //! Marks pipeline as expecting End Of Stream + SOF_IPC4_PIPELINE_STATE_EOS = 5, + //! Stopped on error + SOF_IPC4_PIPELINE_STATE_ERROR_STOP, + //! Saved to the host memory + SOF_IPC4_PIPELINE_STATE_SAVED +}; + +/*! + lp - indicates whether the pipeline should be kept on running in low power + mode. On BXT the driver should set this flag to 1 for WoV pipeline. + + \remark hide_methods +*/ +struct ipc4_pipeline_create { + + union { + uint32_t dat; + + struct { + //! # pages for pipeline + uint32_t ppl_mem_size : 11; + //! priority - uses enum ipc4_pipeline_priority + uint32_t ppl_priority : 5; + //! pipeline id + uint32_t instance_id : 8; + //! Global::CREATE_PIPELINE + uint32_t type : 5; + //! Msg::MSG_REQUEST + uint32_t rsp : 1; + //! Msg::FW_GEN_MSG + uint32_t msg_tgt : 1; + uint32_t _reserved_0 : 1; + } r; + } header; + + union{ + uint32_t dat; + + struct { + //! 1 - is low power + uint32_t lp : 1; + uint32_t rsvd1 : 3; + uint32_t attributes : 16; + uint32_t rsvd2 : 10; + uint32_t _reserved_2 : 2; + } r; + } data; +} __attribute__((packed, aligned(4))); + +/*! + SW Driver sends this IPC message to delete a pipeline from ADSP memory. + + All module instances and tasks that are associated with the pipeline are + deleted too. + + There must be no existing binding from any pipeline's module instance + to another pipeline to complete the command successfully. + + \remark hide_methods +*/ +struct ipc4_pipeline_delete { + union { + uint32_t dat; + + struct { + uint32_t rsvd0 : 16; + //! Ppl instance id + uint32_t instance_id : 8; + //! Global::DELETE_PIPELINE + uint32_t type : 5; + //! Msg::MSG_REQUEST + uint32_t rsp : 1; + //! Msg::FW_GEN_MSG + uint32_t msg_tgt : 1; + uint32_t _reserved_0 : 1; + } r; + } header; + + union{ + uint32_t dat; + + struct { + uint32_t rsvd1 : 30; + uint32_t _reserved_2 : 2; + } r; + } data; +} __attribute__((packed, aligned(4))); + +/*! + Host SW sends this message to set a pipeline to the specified state. + + If there are multiple pipelines, from FW input to FW output, connected + in a data processing stream, the driver should start them in reverse order, + beginning with pipeline connected to the output gateway, in order to avoid + overruns (FW protects the output gateway against underruns in this scenario). + + If driver starts multiple pipelines using a single Set Pipeline State + command, it should take care of the pipeline ID order in the command payload + to follow the above rule. + + sync_stop_start indicates whether all specified pipelines' gateways should + be started with a minimal delay possible. If this flag is set to 0 while + multiple pipelines are specified, the target pipelines' state is adjusted + pipeline by pipeline meaning that internal propagation to all child modules + may take more time between reaching state of attached gateways. Output and + input gateways are grouped separately, and started/stopped separately. + + NOTE: Task Creation/Registration is part of the first state transition. + There is no other dedicated call for this. + + \remark hide_methods +*/ +struct ipc4_pipeline_set_state_data { + //! Number of items in ppl_id[] + uint32_t pipelines_count; + //! Pipeline ids + uint32_t ppl_id[0]; +} __attribute__((packed, aligned(4))); + +struct ipc4_pipeline_set_state { + union { + uint32_t dat; + + struct { + //! new state, one of enum ipc4_pipeline_state + uint32_t ppl_state : 16; + //! pipeline instance id (ignored if multi_ppl =1) + uint32_t ppl_id : 8; + //! Global::SET_PIPELINE_STATE + uint32_t type : 5; + //! Msg::MSG_REQUEST + uint32_t rsp : 1; + + //! Msg::FW_GEN_MSG + uint32_t msg_tgt : 1; + uint32_t _reserved_0: 1; + } r; + } header; + + union{ + uint32_t dat; + + struct { + //! = 1 if there are more pipeline ids in payload + uint32_t multi_ppl : 1; + //! = 1 if FW should sync state change across multiple ppls + uint32_t sync_stop_start : 1; + uint32_t rsvd1 : 28; + uint32_t _reserved_2: 2; + } r; + } data; + + /* multiple pipeline states */ + struct ipc4_pipeline_set_state_data s_data; +} __attribute__((packed, aligned(4))); + +//! Reply to Set Pipeline State +/*! + In case of error, there is failed pipeline id reported back. + + \remark hide_methods +*/ +struct ipc4_pipeline_set_state_reply { + union { + uint32_t dat; + + struct { + //! status + uint32_t status : IXC_STATUS_BITS; + //! Global::SET_PIPELINE_STATE + uint32_t type : 5; + //! Msg::MSG_REPLY + uint32_t rsp : 1; + //! Msg::FW_GEN_MSG + uint32_t msg_tgt : 1; + uint32_t _reserved_0: 1; + } r; + } header; + + union{ + uint32_t dat; + + struct { + //! id of failed pipeline on error + uint32_t ppl_id : 30; + uint32_t _reserved_2: 2; + } r; + } data; +} __attribute__((packed, aligned(4))); + +//! This IPC message is sent to the FW in order to retrieve a pipeline state. +/*! \remark hide_methods */ +struct ipc4_pipeline_get_state { + union { + uint32_t dat; + + struct { + //! pipeline id + uint32_t ppl_id : 8; + uint32_t rsvd : 16; + //! Global::GET_PIPELINE_STATE + uint32_t type : 5; + //! Msg::MSG_REQUEST + uint32_t rsp : 1; + //! Msg::FW_GEN_MSG + uint32_t msg_tgt : 1; + uint32_t _reserved_0: 1; + } r; + } header; + + union{ + uint32_t dat; + + struct { + uint32_t rsvd1 : 30; + uint32_t _reserved_2: 2; + } r; + } data; +} __attribute__((packed, aligned(4))); + +//! Sent by the FW in response to GetPipelineState. +/*! \remark hide_methods */ +struct ipc4_pipeline_get_state_reply { + union { + uint32_t dat; + + struct { + //! status + uint32_t status :IXC_STATUS_BITS; + //! Global::GET_PIPELINE_STATE + uint32_t type : 5; + //! Msg::MSG_REPLY + uint32_t rsp : 1; + //! Msg::FW_GEN_MSG + uint32_t msg_tgt : 1; + uint32_t _reserved_0: 1; + } r; + } header; + + union{ + uint32_t dat; + + struct { + //! one of PipelineState + uint32_t state : 5; + uint32_t rsvd1 : 25; + uint32_t _reserved_2: 2; + } r; + } data; +} __attribute__((packed, aligned(4))); + +/*! + The size is expressed in number of pages. It is a total number of memory pages + allocated for pipeline memory buffer and all separately allocated child + module instances. + + \remark hide_methods +*/ +struct ipc4_pipeline_get_context_size { + union { + uint32_t dat; + + struct { + uint32_t rsvd0 : 16; + //! pipeline id + uint32_t instance_id : 8; + //! Global::GET_PIPELINE_CONTEXT_SIZE + uint32_t type : 5; + //! Msg::MSG_REQUEST + uint32_t rsp : 1; + //! Msg::FW_GEN_MSG + uint32_t msg_tgt : 1; + uint32_t _reserved_0 : 1; + } r; + } header; + + union{ + uint32_t dat; + + struct { + uint32_t rsvd1 : 30; + uint32_t _reserved_2 : 2; + } r; + } data; +} __attribute__((packed, aligned(4))); + +//! Reply to Get Pipeline Context Size. +/*! \remark hide_methods */ +struct ipc4_pipeline_get_context_size_reply { + union { + uint32_t dat; + + struct { + //! status + uint32_t status :IXC_STATUS_BITS; + //! Global::GET_PIPELINE_CONTEXT_SIZE + uint32_t type : 5; + //! Msg::MSG_REPLY + uint32_t rsp : 1; + //! Msg::FW_GEN_MSG + uint32_t msg_tgt : 1; + uint32_t _reserved_0: 1; + } r; + } header; + + union{ + uint32_t dat; + + struct { + //! size of pipeline context (in number of pages) + uint32_t ctx_size : 16; + uint32_t rsvd1 : 14; + uint32_t _reserved_2: 2; + } r; + } data; +} __attribute__((packed, aligned(4))); + +#endif + diff --git a/src/include/sof/ipc/topology.h b/src/include/sof/ipc/topology.h index 2daec37b9f89..1a1909e3d39f 100644 --- a/src/include/sof/ipc/topology.h +++ b/src/include/sof/ipc/topology.h @@ -24,6 +24,23 @@ #include #include +/* generic IPC pipeline regardless of ABI MAJOR type that is always 4 byte aligned */ +typedef uint32_t ipc_pipe_new; + +/* + * Topology IPC logic uses standard types for abstract IPC features. This means all ABI MAJOR + * abstraction is done in the IPC layer only and not in the surrounding infrastructure. + */ +#if CONFIG_IPC_MAJOR_3 +#include +#define ipc_get_pipe_new(x) ((struct sof_ipc_pipe_new *)x) +#elif CONFIG_IPC_MAJOR_4 +#include +#define ipc_get_pipe_new(x) ((struct ipc4_pipeline_create *)x) +#else +#error "No or invalid IPC MAJOR version selected." +#endif + struct dai_config; struct ipc_msg; @@ -106,7 +123,7 @@ int ipc_buffer_free(struct ipc *ipc, uint32_t buffer_id); * @param pipeline New IPC pipeline descriptor. * @return 0 on success or negative error. */ -int ipc_pipeline_new(struct ipc *ipc, struct sof_ipc_pipe_new *pipeline); +int ipc_pipeline_new(struct ipc *ipc, ipc_pipe_new *pipeline); /** * \brief Free an IPC pipeline. diff --git a/src/ipc/helper-ipc3.c b/src/ipc/helper-ipc3.c index 6ade9ac47f51..51a329e4ce7b 100644 --- a/src/ipc/helper-ipc3.c +++ b/src/ipc/helper-ipc3.c @@ -276,9 +276,9 @@ struct comp_dev *comp_new(struct sof_ipc_comp *comp) return cdev; } -int ipc_pipeline_new(struct ipc *ipc, - struct sof_ipc_pipe_new *pipe_desc) +int ipc_pipeline_new(struct ipc *ipc, ipc_pipe_new *_pipe_desc) { + struct sof_ipc_pipe_new *pipe_desc = ipc_get_pipe_new(_pipe_desc); struct ipc_comp_dev *ipc_pipe; struct pipeline *pipe; struct ipc_comp_dev *icd; diff --git a/tools/testbench/topology.c b/tools/testbench/topology.c index bfdbf7cea2b1..48d82202a7c4 100644 --- a/tools/testbench/topology.c +++ b/tools/testbench/topology.c @@ -484,7 +484,7 @@ int load_pipeline(void *dev, int comp_id, int pipeline_id, pipeline.sched_id = sched_id; /* Create pipeline */ - if (ipc_pipeline_new(sof->ipc, &pipeline) < 0) { + if (ipc_pipeline_new(sof->ipc, (ipc_pipe_new *)&pipeline) < 0) { fprintf(stderr, "error: pipeline new\n"); return -EINVAL; } From 579fcbb79d42093057e34a0f4fdc2362418e0e57 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Sun, 25 Apr 2021 22:25:52 +0100 Subject: [PATCH 02/13] pipeline: add support for pipeline to allocate memory Add support to allocate memory at the pipeline level so that the all its processing components can use the same resource. Signed-off-by: Liam Girdwood --- src/audio/pipeline/pipeline-graph.c | 6 ++++++ src/include/sof/audio/pipeline.h | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/audio/pipeline/pipeline-graph.c b/src/audio/pipeline/pipeline-graph.c index 7cb83c4a2571..276c2f5cf01e 100644 --- a/src/audio/pipeline/pipeline-graph.c +++ b/src/audio/pipeline/pipeline-graph.c @@ -102,6 +102,12 @@ void pipeline_posn_init(struct sof *sof) spinlock_init(&sof->pipeline_posn->lock); } +int pipeline_alloc_memory(struct pipeline *p, uint32_t bytes) +{ + // TODO + return 0; +} + /* create new pipeline - returns pipeline id or negative error */ struct pipeline *pipeline_new(struct comp_dev *cd, uint32_t pipeline_id, uint32_t priority, uint32_t comp_id) diff --git a/src/include/sof/audio/pipeline.h b/src/include/sof/audio/pipeline.h index 37e094301ff7..64f06f37bd2a 100644 --- a/src/include/sof/audio/pipeline.h +++ b/src/include/sof/audio/pipeline.h @@ -52,6 +52,8 @@ struct pipeline { uint32_t frames_per_sched;/**< output frames of pipeline, 0 is variable */ uint32_t xrun_limit_usecs; /**< report xruns greater than limit */ uint32_t time_domain; /**< scheduling time domain */ + uint32_t memory_size; + void *memory; /* runtime status */ int32_t xrun_bytes; /* last xrun length */ @@ -189,6 +191,14 @@ static inline uint32_t pipeline_id(struct pipeline *p) return p->pipeline_id; } +/** + * Allocates memory buffers for entire pipeline. + * @param p pipeline. + * @param bytes allocation request in bytes. + * @return 0 on success. + */ +int pipeline_alloc_memory(struct pipeline *p, uint32_t bytes); + /* * Pipeline configuration APIs * From 04a82ee0af5cda2d44aa3f1b9a9b77be5b1cad57 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Sun, 25 Apr 2021 22:26:33 +0100 Subject: [PATCH 03/13] ipc4: wip Signed-off-by: Liam Girdwood --- src/include/ipc4/module.h | 190 ++++++++++++++++++++ src/include/ipc4/notification.h | 51 ++++++ src/include/ipc4/pipeline.h | 1 + src/include/sof/audio/buffer.h | 35 ++++ src/include/sof/audio/component.h | 9 + src/ipc/CMakeLists.txt | 5 + src/ipc/handler-ipc4.c | 285 ++++++++++++++++++++++++++++++ src/ipc/helper-ipc3.c | 4 + src/ipc/helper-ipc4.c | 183 +++++++++++++++++++ 9 files changed, 763 insertions(+) create mode 100644 src/include/ipc4/module.h create mode 100644 src/include/ipc4/notification.h create mode 100644 src/ipc/handler-ipc4.c create mode 100644 src/ipc/helper-ipc4.c diff --git a/src/include/ipc4/module.h b/src/include/ipc4/module.h new file mode 100644 index 000000000000..22bcacf47a22 --- /dev/null +++ b/src/include/ipc4/module.h @@ -0,0 +1,190 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + */ + +/** + * \file include/ipc4/module.h + * \brief IPC4 module definitions + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __IPC4_MODULE_H__ +#define __IPC4_MODULE_H__ + +#include + +#define SOF_IPC4_DST_QUEUE_ID_BITFIELD_SIZE 3 +#define SOF_IPC4_SRC_QUEUE_ID_BITFIELD_SIZE 3 + +enum sof_ipc4_module_type { + SOF_IPC4_MOD_INIT_INSTANCE = 0, + SOF_IPC4_MOD_CONFIG_GET = 1, + SOF_IPC4_MOD_CONFIG_SET = 2, + SOF_IPC4_MOD_LARGE_CONFIG_GET = 3, + SOF_IPC4_MOD_LARGE_CONFIG_SET = 4, + SOF_IPC4_MOD_BIND = 5, + SOF_IPC4_MOD_UNBIND = 6, + SOF_IPC4_MOD_SET_DX = 7, + SOF_IPC4_MOD_SET_D0IX = 8, + SOF_IPC4_MOD_ENTER_MODULE_RESTORE = 9, + SOF_IPC4_MOD_EXIT_MODULE_RESTORE = 10, + SOF_IPC4_MOD_DELETE_INSTANCE = 11, +}; + +/* + * //! Host Driver sends this message to create a new module instance. + */ +struct ipc4_module_init_ext_init { + //! if it is set to 1, proc_domain should be ignored and processing + // domain is RTOS scheduling + uint32_t rtos_domain : 1; + //! Indicates that GNA is used by a module and additional information + //(gna_config) is passed after ExtendedData. + uint32_t gna_used : 1; + uint32_t rsvd_0 : 30; + uint32_t rsvd_1[2]; +} __attribute__((packed, aligned(4))); + +struct ipc4_module_init_ext_data { + struct ipc4_module_init_ext_init extended_init; + + //! Data (actual size set to param_block_size) + uint32_t param_data[0]; +} __attribute__((packed, aligned(4))); + +struct ipc4_module_init_gna_config { + //! Number of GNA cycles required to process one input frame. + //This information is used by DP scheduler to correctly schedule a DP module. + uint32_t gna_cpc; + uint32_t rsvd; +} __attribute__((packed, aligned(4))); + +struct ipc4_module_init_data { + //! Data (actual size set to param_block_size) + uint32_t param_data[0]; +} __attribute__((packed, aligned(4))); + +/*! + Created instance is a child element of pipeline identified by the ppl_id + specified by the driver. + + The module_id should be set to an index of the module entry in the FW Image + Manifest. + + The instance_id assigned by the driver should be in the + 0..ModuleEntry.max_instance_count range defined in the FW Image Manifest. + + Initial configuration of the module instance is provided by the driver in + the param_data array. Size of the array is specified in param_block_size + field of the message header. + + Refer to Module Configuration section of FW I/F Specification for details on + module specific initial configuration parameters. + + \remark hide_methods +*/ +struct ipc4_module_init_instance { + + union { + uint32_t dat; + + struct { + //! module id + uint32_t module_id : 16; + //! instance id + uint32_t instance_id : 8; + //! ModuleMsg::INIT_INSTANCE + uint32_t type : 5; + //! Msg::MSG_REQUEST + uint32_t rsp : 1; + //! Msg::MODULE_MSG + uint32_t msg_tgt : 1; + uint32_t _reserved_0 : 1; + } r; + } header; + + union { + uint32_t dat; + + struct { + //! Size of Data::param_data[] (in dwords) + uint32_t param_block_size : 16; + //! ID of module instance's parent pipeline + uint32_t ppl_instance_id : 8; + //! ID of core that instance will run on + uint32_t core_id : 4; + //! Processing domain, 0-LL, 1-DP + uint32_t proc_domain : 1; + // reserved in cAVS + uint32_t extended_init : 1; + uint32_t _hw_reserved_2 : 2; + } r; + } data; + + struct ipc4_module_init_ext_init ext_init; + struct ipc4_module_init_ext_data ext_data; + struct ipc4_module_init_gna_config gna_config; + struct ipc4_module_init_data init_data; +} __attribute__((packed, aligned(4))); + +/*! + SW Driver sends Bind IPC message to connect two module instances together + creating data processing path between them. + + Unbind IPC message is sent to destroy a connection between two module instances + (belonging to different pipelines) previously created with Bind call. + + NOTE: when both module instances are parts of the same pipeline Unbind IPC would + be ignored by FW since FW does not support changing internal topology of pipeline + during run-time. The only way to change pipeline topology is to delete the whole + pipeline and create it in modified form. + + \remark hide_methods + */ +struct ipc4_module_bind_unbind { + union { + uint32_t dat; + + struct { + //! module id + uint32_t module_id : 16; + //! instance id + uint32_t instance_id : 8; + //! ModuleMsg::BIND / UNBIND. + uint32_t type : 5; + //! Msg::MSG_REQUEST + uint32_t rsp : 1; + //! Msg::MODULE_MSG + uint32_t msg_tgt : 1; + uint32_t _reserved_0 : 1; + } r; + } header; + + union { + uint32_t dat; + + struct { + //! destination module id + uint32_t dst_module_id : 16; + //! destination instance id + uint32_t dst_instance_id : 8; + //! destination queue (pin) id + uint32_t dst_queue : SOF_IPC4_DST_QUEUE_ID_BITFIELD_SIZE; + //! source queue (pin) id + uint32_t src_queue : SOF_IPC4_SRC_QUEUE_ID_BITFIELD_SIZE; + uint32_t _reserved_2 : 2; + } r; + } data; +} __attribute__((packed, aligned(4))); + +#endif + diff --git a/src/include/ipc4/notification.h b/src/include/ipc4/notification.h new file mode 100644 index 000000000000..56c0b5d1e07a --- /dev/null +++ b/src/include/ipc4/notification.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + */ + +/** + * \file include/ipc4/notification.h + * \brief IPC4 notification definitions + */ + +#ifndef __IPC4_NOTIFICATION_H__ +#define __IPC4_NOTIFICATION_H__ + +#include +#include + +/* ipc4 notification msg */ + +enum sof_ipc4_notification_type { + SOF_IPC4_NOTIFY_PHRASE_DETECTED = 4, + SOF_IPC4_NOTIFY_RESOURCE_EVENT = 5, + SOF_IPC4_NOTIFY_LOG_BUFFER_STATUS = 6, + SOF_IPC4_NOTIFY_TIMESTAMP_CAPTURED = 7, + SOF_IPC4_NOTIFY_FW_READY = 8, + SOF_IPC4_FW_AUD_CLASS_RESULT = 9, + SOF_IPC4_EXCEPTION_CAUGHT = 10, + SOF_IPC4_MODULE_NOTIFICATION = 12, + SOF_IPC4_UAOL_RSVD_ = 13, + SOF_IPC4_PROBE_DATA_AVAILABLE = 14, + SOF_IPC4_WATCHDOG_TIMEOUT = 15, + SOF_IPC4_MANAGEMENT_SERVICE = 16, +}; + +#define SOF_IPC4_GLB_NOTIFY_DIR_MASK BIT(29) +#define SOF_IPC4_REPLY_STATUS_MASK 0xFFFFFF +#define SOF_IPC4_GLB_NOTIFY_TYPE_SHIFT 16 +#define SOF_IPC4_GLB_NOTIFY_MSG_TYPE_SHIFT 24 + + +#define SOF_IPC4_FW_READY \ + (((SOF_IPC4_NOTIFY_FW_READY) << (SOF_IPC4_GLB_NOTIFY_TYPE_SHIFT)) |\ + ((SOF_IPC4_GLB_NOTIFICATION) << (SOF_IPC4_GLB_NOTIFY_MSG_TYPE_SHIFT))) +#endif diff --git a/src/include/ipc4/pipeline.h b/src/include/ipc4/pipeline.h index 8ee8d2ce214e..28c506dae58f 100644 --- a/src/include/ipc4/pipeline.h +++ b/src/include/ipc4/pipeline.h @@ -14,6 +14,7 @@ /** * \file include/ipc4/pipeline.h * \brief IPC4 pipeline definitions + * NOTE: This ABI uses bit fields and is non portable. */ #ifndef __SOF_IPC4_PIPELINE_H__ diff --git a/src/include/sof/audio/buffer.h b/src/include/sof/audio/buffer.h index a3b0be9b93e3..9a305973644a 100644 --- a/src/include/sof/audio/buffer.h +++ b/src/include/sof/audio/buffer.h @@ -83,6 +83,41 @@ extern struct tr_ctx buffer_tr; #define BUFF_PARAMS_RATE BIT(2) #define BUFF_PARAMS_CHANNELS BIT(3) +/*! \brief defines the bitfield structure of flags associated to an InputStreamBuffer + */ +struct buffer_stream_flags { + const bool end_of_stream : 1; /*!< indicates that End Of Stream condition has occured on the input stream */ +}; + +struct buffer_input_stream { + uint8_t* const data; /*!< data stream buffer */ + /*! + * \brief size indicator about the data in the stream buffer + * + * - When read, it indicates the size of available data in the data stream buffer + * - When written, it reports the size of data which has actually be considered during the buffer processing + * (can be less than the given available data size) + */ + size_t size; + struct buffer_stream_flags flags; /*!< readonly status flags about the input stream */ +}; + +/*! \brief Descriptor of the data stream buffer to inject into an output module pin + * \see ProcessingModuleInterface::Process() + */ +struct buffer_output_stream { + uint8_t* const data; /*!< data stream buffer */ + /*! + * \brief size indicator about the data in the stream buffer + * + * - When read, it indicates the size of available room in the stream buffer + * - When written, it reports the size of data which has actually be produced into the buffer during the buffer processing + * (can be less than the given available room size) + */ + size_t size; +}; + + /* audio component buffer - connects 2 audio components together in pipeline */ struct comp_buffer { spinlock_t *lock; /* locking mechanism */ diff --git a/src/include/sof/audio/component.h b/src/include/sof/audio/component.h index 223521923527..77874a0dbcdf 100644 --- a/src/include/sof/audio/component.h +++ b/src/include/sof/audio/component.h @@ -221,6 +221,15 @@ enum comp_copy_type { COMP_COPY_ONE_SHOT, /**< One-shot */ }; +/*! \brief enumeration values of processing mode */ +enum comp_processing_mode { + COMP_PROCESS_NORMAL = 0, /*!< Indicates that module is expected to apply its custom processing on signal. */ + COMP_PROCESS_BYPASS /*!< Indicates that module is expected to not apply its custom processing on signal. + * The module is expected to forward as far as possible the input signals unmodified + * with respect of the signal continuity at the mode transition. + */ +}; + struct comp_driver; /** diff --git a/src/ipc/CMakeLists.txt b/src/ipc/CMakeLists.txt index a512ebb11e46..359f84836908 100644 --- a/src/ipc/CMakeLists.txt +++ b/src/ipc/CMakeLists.txt @@ -5,6 +5,11 @@ if (CONFIG_IPC_MAJOR_3) handler-ipc3.c helper-ipc3.c ) +elseif (CONFIG_IPC_MAJOR_4) + add_local_sources(sof + handler-ipc4.c + helper-ipc4.c + ) endif() add_local_sources(sof diff --git a/src/ipc/handler-ipc4.c b/src/ipc/handler-ipc4.c new file mode 100644 index 000000000000..dbf3cd60c11f --- /dev/null +++ b/src/ipc/handler-ipc4.c @@ -0,0 +1,285 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Rander Wang +/* + * IPC (InterProcessor Communication) provides a method of two way + * communication between the host processor and the DSP. The IPC used here + * utilises a shared mailbox and door bell between the host and DSP. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * Global IPC Operations. + */ +static int ipc4_create_pipeline(union ipc4_message_header *ipc4) +{ + tr_err(&ipc_tr, "ipc4 create pipeline %x:", (uint32_t)ipc4->r.type); + + return 0; +} + +static int ipc4_delete_pipeline(union ipc4_message_header *ipc4) +{ + tr_err(&ipc_tr, "ipc4 delete pipeline %x:", (uint32_t)ipc4->r.type); + + return 0; +} + +static int ipc4_set_pipeline_state(union ipc4_message_header *ipc4) +{ + tr_err(&ipc_tr, "ipc4 set pipeline state %x:", (uint32_t)ipc4->r.type); + + return 0; +} + +static int ipc4_process_glb_message(union ipc4_message_header *ipc4) +{ + uint32_t type; + int ret = 0; + + type = ipc4->r.type; + + switch (type) { + case SOF_IPC4_GLB_BOOT_CONFIG: + case SOF_IPC4_GLB_ROM_CONTROL: + case SOF_IPC4_GLB_IPCGATEWAY_CMD: + case SOF_IPC4_GLB_START_RTOS_EDF_TASK: + case SOF_IPC4_GLB_STOP_RTOS_EDF_TASK: + case SOF_IPC4_GLB_PERF_MEASUREMENTS_CMD: + case SOF_IPC4_GLB_CHAIN_DMA: + case SOF_IPC4_GLB_LOAD_MULTIPLE_MODULES: + case SOF_IPC4_GLB_UNLOAD_MULTIPLE_MODULES: + tr_err(&ipc_tr, "not implemented ipc message type %d", type); + break; + + /* pipeline settings */ + case SOF_IPC4_GLB_CREATE_PIPELINE: + ret = ipc4_create_pipeline(ipc4); + break; + case SOF_IPC4_GLB_DELETE_PIPELINE: + ret = ipc4_delete_pipeline(ipc4); + break; + case SOF_IPC4_GLB_SET_PIPELINE_STATE: + ret = ipc4_set_pipeline_state(ipc4); + break; + + case SOF_IPC4_GLB_GET_PIPELINE_STATE: + case SOF_IPC4_GLB_GET_PIPELINE_CONTEXT_SIZE: + case SOF_IPC4_GLB_SAVE_PIPELINE: + case SOF_IPC4_GLB_RESTORE_PIPELINE: + tr_err(&ipc_tr, "not implemented ipc message type %d", type); + break; + + /* Loads library (using Code Load or HD/A Host Output DMA) */ + case SOF_IPC4_GLB_LOAD_LIBRARY: + case SOF_IPC4_GLB_INTERNAL_MESSAGE: + tr_err(&ipc_tr, "not implemented ipc message type %d", type); + break; + + /* Notification (FW to SW driver) */ + case SOF_IPC4_GLB_NOTIFICATION: + tr_err(&ipc_tr, "not implemented ipc message type %d", type); + break; + + default: + tr_err(&ipc_tr, "unsupported ipc message type %d", type); + ret = -EINVAL; + break; + } + + return ret; +} + +/* + * Module IPC operations. + */ + +static int ipc4_init_module(union ipc4_message_header *ipc4) +{ + return 0; +} + +static int ipc4_bind_module(union ipc4_message_header *ipc4) +{ + return 0; +} + +static int ipc4_unbind_module(union ipc4_message_header *ipc4) +{ + return 0; +} + +static int ipc4_set_large_config_module(union ipc4_message_header *ipc4) +{ + return 0; +} + +static int ipc4_process_module_message(union ipc4_message_header *ipc4) +{ + uint32_t type; + int ret = 0; + + type = ipc4->r.type; + + switch (type) { + case SOF_IPC4_MOD_INIT_INSTANCE: + ret = ipc4_init_module(ipc4); + break; + case SOF_IPC4_MOD_CONFIG_GET: + break; + case SOF_IPC4_MOD_CONFIG_SET: + break; + case SOF_IPC4_MOD_LARGE_CONFIG_GET: + break; + case SOF_IPC4_MOD_LARGE_CONFIG_SET: + ret = ipc4_set_large_config_module(ipc4); + break; + case SOF_IPC4_MOD_BIND: + ret = ipc4_bind_module(ipc4); + break; + case SOF_IPC4_MOD_UNBIND: + ret = ipc4_unbind_module(ipc4); + break; + case SOF_IPC4_MOD_SET_DX: + break; + case SOF_IPC4_MOD_SET_D0IX: + break; + case SOF_IPC4_MOD_ENTER_MODULE_RESTORE: + break; + case SOF_IPC4_MOD_EXIT_MODULE_RESTORE: + break; + case SOF_IPC4_MOD_DELETE_INSTANCE: + break; + default: + break; + } + + return ret; +} + +ipc_cmd_hdr *mailbox_validate(void) +{ + ipc_cmd_hdr *hdr = ipc_get()->comp_data; + + /* TODO validate message */ + return hdr; +} + +/* + * Most ABI 4 messages use compact format - keep logic simpler + * and handle all in IPC command. + */ +static uint32_t msg_in[2]; /* local copy of current message from host header */ +static uint32_t msg_out[2]; /* local copy of current message to host header */ + +ipc_cmd_hdr *ipc_compact_read_msg(void) +{ + ipc_cmd_hdr *hdr = (ipc_cmd_hdr*)msg_in; + int words; + + words = ipc_platform_compact_read_msg(hdr, 2); + if (!words) + return mailbox_validate(); + + return ipc_to_hdr(msg_in); +} + +void ipc_cmd(ipc_cmd_hdr *_hdr) +{ + union ipc4_message_header *in = ipc_get_hdr(_hdr); + union ipc4_message_header *out = ipc_get_hdr(msg_out); + enum ipc4_message_target target; + int err = -EINVAL; + + if (!in) + return; + + target = in->r.msg_tgt; + + switch (target) { + case SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG: + err = ipc4_process_glb_message(in); + break; + case SOF_IPC4_MESSAGE_TARGET_MODULE_MSG: + err = ipc4_process_module_message(in); + break; + default: + /* should not reach here as we only have 2 message tyes */ + tr_err(&ipc_tr, "ipc4: invalid target %d", target); + err = -EINVAL; + } + + if (err) { + tr_err(&ipc_tr, "ipc4: %d failed ....", target); + } + + /* FW sends a ipc message to host if request bit is set*/ + if (in->r.rsp == SOF_IPC4_MESSAGE_DIR_MSG_REQUEST) { + //struct ipc *ipc = ipc_get(); + + /* copy contents of message received */ + *out = *in; + out->r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REPLY; + + // TODO: validate and create reply header + err = ipc_platform_compact_write_msg(ipc_to_hdr(out), 2); + if (err != 2) { + tr_err(&ipc_tr, "ipc4: reply %d failed ....", target); + } + } +} diff --git a/src/ipc/helper-ipc3.c b/src/ipc/helper-ipc3.c index 51a329e4ce7b..e44d4ff7f460 100644 --- a/src/ipc/helper-ipc3.c +++ b/src/ipc/helper-ipc3.c @@ -438,6 +438,9 @@ int ipc_pipeline_complete(struct ipc *ipc, uint32_t comp_id) return ret; } +/* + * Configure DAI - TODO: this can be simplified to run only on core 0. + */ int ipc_comp_dai_config(struct ipc *ipc, struct sof_ipc_dai_config *config) { bool comp_on_core[CONFIG_CORE_COUNT] = { false }; @@ -456,6 +459,7 @@ int ipc_comp_dai_config(struct ipc *ipc, struct sof_ipc_dai_config *config) continue; } + /* comp on this core ? TODO: we dont care if it's not a DAI */ if (!cpu_is_me(icd->core)) { comp_on_core[icd->core] = true; ret = 0; diff --git a/src/ipc/helper-ipc4.c b/src/ipc/helper-ipc4.c new file mode 100644 index 000000000000..1f3703701de4 --- /dev/null +++ b/src/ipc/helper-ipc4.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood +// Keyon Jie + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +extern struct tr_ctx comp_tr; + +void ipc_build_stream_posn(struct sof_ipc_stream_posn *posn, uint32_t type, + uint32_t id) +{ +} + +void ipc_build_comp_event(struct sof_ipc_comp_event *event, uint32_t type, + uint32_t id) +{ +} + +void ipc_build_trace_posn(struct sof_ipc_dma_trace_posn *posn) +{ +} + +/* used with IPC4 - placeholder atm */ +int comp_verify_params(struct comp_dev *dev, uint32_t flag, + struct sof_ipc_stream_params *params) +{ + return 0; +} + +/* used with IPC4 new module - placeholder atm */ +struct comp_dev *comp_new(struct sof_ipc_comp *comp) +{ + return NULL; +} + +int ipc_pipeline_new(struct ipc *ipc, ipc_pipe_new *_pipe_desc) +{ + struct ipc4_pipeline_create *pipe_desc = ipc_get_pipe_new(_pipe_desc); + struct ipc_comp_dev *ipc_pipe; + struct pipeline *pipe; + + /* check whether pipeline id is already taken or in use */ + ipc_pipe = ipc_get_comp_by_ppl_id(ipc, COMP_TYPE_PIPELINE, + pipe_desc->header.r.instance_id); + if (ipc_pipe) { + tr_err(&ipc_tr, "ipc_pipeline_new(): pipeline id is already taken, pipe_desc->instance_id = %u", + (uint32_t)pipe_desc->header.r.instance_id); + return -EINVAL; + } + + /* create the pipeline */ + pipe = pipeline_new(ipc_pipe->cd, pipe_desc->header.r.instance_id, + pipe_desc->header.r.ppl_priority, 0); + if (!pipe) { + tr_err(&ipc_tr, "ipc_pipeline_new(): pipeline_new() failed"); + return -ENOMEM; + } + + /* allocate the IPC pipeline container */ + ipc_pipe = rzalloc(SOF_MEM_ZONE_RUNTIME_SHARED, 0, SOF_MEM_CAPS_RAM, + sizeof(struct ipc_comp_dev)); + if (!ipc_pipe) { + pipeline_free(pipe); + return -ENOMEM; + } + + ipc_pipe->pipeline = pipe; + ipc_pipe->type = COMP_TYPE_PIPELINE; + //ipc_pipe->core = pipe_desc->core; + ipc_pipe->id = pipe_desc->header.r.instance_id; + + /* add new pipeline to the list */ + list_item_append(&ipc_pipe->list, &ipc->comp_list); + + return 0; +} + +int ipc_pipeline_free(struct ipc *ipc, uint32_t comp_id) +{ + struct ipc_comp_dev *ipc_pipe; + int ret; + + /* check whether pipeline exists */ + ipc_pipe = ipc_get_comp_by_id(ipc, comp_id); + if (!ipc_pipe) + return -ENODEV; + + /* check core */ + if (!cpu_is_me(ipc_pipe->core)) + return ipc_process_on_core(ipc_pipe->core); + + /* free buffer and remove from list */ + ret = pipeline_free(ipc_pipe->pipeline); + if (ret < 0) { + tr_err(&ipc_tr, "ipc_pipeline_free(): pipeline_free() failed"); + return ret; + } + ipc_pipe->pipeline = NULL; + list_item_del(&ipc_pipe->list); + rfree(ipc_pipe); + + return 0; +} + +/* not used with IPC4 - placeholder atm */ +int ipc_pipeline_complete(struct ipc *ipc, uint32_t comp_id) +{ + return 0; +} + +/* not used with IPC4 - placeholder atm */ +int ipc_comp_dai_config(struct ipc *ipc, struct sof_ipc_dai_config *config) +{ + return 0; +} + +/* not used with IPC4 - placeholder atm */ +int ipc_buffer_new(struct ipc *ipc, struct sof_ipc_buffer *desc) +{ + return 0; +} + +/* not used with IPC4 - placeholder atm */ +int ipc_buffer_free(struct ipc *ipc, uint32_t buffer_id) +{ + return 0; +} + +/* used with IPC4 - placeholder atm */ +int ipc_comp_connect(struct ipc *ipc, + struct sof_ipc_pipe_comp_connect *connect) +{ + + return 0; +} + +/* used with IPC4 - placeholder atm */ +int ipc_comp_new(struct ipc *ipc, struct sof_ipc_comp *comp) +{ + return 0; +} + +/* used with IPC4 - placeholder atm */ +int ipc_comp_free(struct ipc *ipc, uint32_t comp_id) +{ + return 0; +} + +/* not used with IPC4 - placeholder atm */ +struct comp_buffer *buffer_new(struct sof_ipc_buffer *desc) +{ + return NULL; +} From 381f00537c14a824f9e1c116a8aeaa59343fe25b Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Mon, 26 Apr 2021 21:26:25 +0100 Subject: [PATCH 04/13] ipc: abstraction: Add yet more IPC structures WIP. Signed-off-by: Liam Girdwood --- src/include/ipc4/copier.h | 436 +++++++++++++++++++++++++++++++++ src/include/ipc4/gateway.h | 191 +++++++++++++++ src/include/sof/ipc/topology.h | 27 +- src/ipc/handler-ipc3.c | 8 +- src/ipc/helper-ipc3.c | 12 +- src/ipc/helper-ipc4.c | 2 +- 6 files changed, 660 insertions(+), 16 deletions(-) create mode 100644 src/include/ipc4/copier.h create mode 100644 src/include/ipc4/gateway.h diff --git a/src/include/ipc4/copier.h b/src/include/ipc4/copier.h new file mode 100644 index 000000000000..e477622cc696 --- /dev/null +++ b/src/include/ipc4/copier.h @@ -0,0 +1,436 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + */ + +/** + * \file include/ipc4/header.h + * \brief IPC4 global definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __SOF_IPC4_COPIER_H__ +#define __SOF_IPC4_COPIER_H__ + +#include + +/** + * This is basic module config that may serve as a base for more specialized, module + * specific config received along with Init Module Instance from host. + * + * Remarks:
+ * The data required to build basic module configuration should be retrieved by the + * software driver from the Module Configuration array, part of the FW Image Manifest. + * Appropriate Module Configuration record is selected based on look up parameters + * (specific look up parameter values are driver implementation specific and should + * be provided as an input to the FW Image Builder). + */ +//typedef intel_adsp::LegacyModuleInitialSettings BaseModuleCfg; + +//! Linear Link Position Reading Data +struct LlpReading +{ + //! lower part of 64-bit LLP + uint32_t llp_l; + //! upper part of 64-bit LLP + uint32_t llp_u; + //! lower part of 64-bit Wallclock + uint32_t wclk_l; + //! upper part of 64-bit Wallclock + uint32_t wclk_u; +}; + +struct LlpReadingExtended +{ + struct LlpReading llp_reading; + //! total processed data (low part) + uint32_t tpd_low; + //! total processed data (high part) + uint32_t tpd_high; +}; + +struct BaseModuleCfgExt +{ + /*! + * \brief Specifies number of items in input_pins array. Maximum size is 8. + */ + uint16_t nb_input_pins; + /*! + * \brief Specifies number of items in output_pins array. Maximum size is 8. + */ + uint16_t nb_output_pins; + /*! + * \brief Not used, set to 0. + */ + uint8_t reserved[8]; + /*! + * \brief Length of optional module specific parameters that follow BaseModuleCfgExt. + */ + uint32_t priv_param_length; + /*! + * \brief Specifies format of input pins. + * \remarks Pin format arrays may be non-continuous i.e. may contain pin #0 format followed by pin #2 format + * in case pin #1 will not be in use. FW assigned format of the pin based on pin_index, + * not on a position of the item in the array. Applies to both input and output pins. + */ + intel_adsp::InputPinFormat input_pins[1]; + /*! + * \brief Specifies format of output pins. + */ + intel_adsp::OutputPinFormat output_pins[1]; +}; + +/** + * This enum defines short 16bit parameters common for all modules. + * Value of module specific parameters have to be less than 0x3000. + */ +enum BaseModuleParams +{ + /** + * Handled inside LargeConfigGet of module instance + */ + MOD_INST_PROPS = 0xFE, + /** + * Handled inside ConfigSet of module instance + */ + MOD_INST_ENABLE = 0x3000 +}; + +static const uint32_t INVALID_QUEUE_ID = 0xFFFFFFFF; + +/*! + \struct PinProps + Properties of a pin. +*/ +struct PinProps +{ + /*! Type of the connected stream. */ + StreamType stream_type; + + /*! Audio format of the stream. + The content is valid in case of ePcm stream_type. */ + AudioDataFormatIpc format; + + /*! Unique ID of the physical queue connected to the pin. + If there is no queue connected, then -1 (invalid queue ID) is set. */ + uint32_t phys_queue_id; +}; + + +struct PinListInfo +{ + uint32_t pin_count; + PinProps pin_info[1]; +}; + +/** + * Helper structure definition. + * Reflects the last two entries in ModuleInstanceProps sttructure. + */ +struct InOutGateway +{ + uint32_t input_gateway; + uint32_t output_gateway; +}; + +/** + * Structure describing module instance properties used in response + * to module LargeConfigGet with MOD_INST_PROPS parameter. + */ +struct ModuleInstanceProps +{ + uint32_t id; + uint32_t dp_queue_type; + uint32_t queue_alignment; + uint32_t cp_usage_mask; + uint32_t stack_bytes; + uint32_t bss_total_bytes; + uint32_t bss_used_bytes; + uint32_t ibs_bytes; + uint32_t obs_bytes; + uint32_t cpc; + uint32_t cpc_peak; + // TODO: uncomment or remove once performance measurements collection mechanism + // is agreed and aligned between debugAgent, OED and FW + // uint32_t cpc_avg; + // uint32_t cpc_last; + PinListInfo input_queues; + PinListInfo output_queues; + uint32_t input_gateway; + uint32_t output_gateway; +}; + +/** + * This structure may be used by modules to carry + * short 16bit parameters as part of the IxC + * register content. + */ +union CfgParamIdData +{ + uint32_t dw; + struct + { + uint32_t data16 : 16; ///< Input/Output small config data + uint32_t id : 14; ///< input parameter ID + uint32_t _rsvd : 2; + } f; + CfgParamIdData() :dw(0) {} + explicit CfgParamIdData(uint32_t param_id_data) :dw(param_id_data) {} + CfgParamIdData(uint16_t id, uint16_t data16) :dw(0) + { + f.id = id; + f.data16 = data16; + } +}; + +/*! + \name Copier Module Configuration & Interface + + UUID: 9BA00C83-CA12-4A83-943C-1FA2E82F9DDA + + Copier may be instantiated and bound in one of following configurations: + + - case 1: + \dot + digraph Module_Copier_Module { + rankdir = "LR"; + node [shape=box style=rounded, fontsize=10, fontname="Tahoma"]; + edge [fontsize=10, fontname="Tahoma"]; + InputGateway [color=green] + InputGateway -> Copier [color=green] + + DestinationMod [color=red] + Copier -> DestinationMod [color=red] + } + \enddot + + - case 2: + \dot + digraph Module_Copier_Gateways { + rankdir = "LR"; + node [shape=box style=rounded, fontsize=10, fontname="Tahoma"]; + edge [fontsize=10, fontname="Tahoma"]; + SourceMod [color=red] + + SourceMod -> Copier [color=red] + + OutputGateway [color=green] + Copier -> OutputGateway [color=green] + } + \enddot + + - case 3: + \dot + digraph Module_Copier_Module { + rankdir = "LR"; + node [shape=box style=rounded, fontsize=10, fontname="Tahoma"]; + edge [fontsize=10, fontname="Tahoma"]; + SourceMod [color=red] + + SourceMod -> Copier [color=red] + + DestinationMod [color=red] + Copier -> DestinationMod [color=red] + } + \enddot + + - case 4: + \dot + digraph Module_Copier_Module { + rankdir = "LR"; + node [shape=box style=rounded, fontsize=10, fontname="Tahoma"]; + edge [fontsize=10, fontname="Tahoma"]; + SourceMod [color=red] + + SourceMod -> Copier [color=red] + + DestinationMod [color=red] + OutputGateway [color=green] + + Copier -> OutputGateway [color=green] + Copier -> DestinationMod [color=red] + } + \enddot + + In cases 1 and 2, the initial configuration must include Gateway Configuration + data along with valid Node ID of the gateway to be connected on either + Copier's end. + + \attention Gateway can only be connected to input pin "0" or output pin "0". + + Initial configuration data allows setup audio format of main Copier's pins, + input pin "0" and output pin "0" and prepare PCM conversion routine if any is + required. However Copier supports up to #COPIER_MODULE_OUTPUT_PINS_COUNT + output pins. Before any additional output pin is used in binding operation, + the host driver has to send run-time parameter to setup sink formwat + (#COPIER_MODULE_CFG_PARAM_SET_SINK_FORMAT) first to setup a PCM conversion + routine if any is required. + + ------------------------------------------------------------------------------ +*/ + +//! Total number of output pins. +static const size_t COPIER_MODULE_OUTPUT_PINS_COUNT = 4; + +enum CopierFeatures +{ + /*! + If FAST_MODE bit is set in CopierModuleCfg::copier_feature_mask then + copier is able to transfer more than ibs. This bit shall be set only if + all sinks are connected to data processing queue. + */ + FAST_MODE = 0 +}; + +struct CopierGatewayCfg +{ + //! ID of Gateway Node. + /*! + If node_id is valid, i.e. != -1, copier instance is connected to the + specified gateway using either input pin 0 or output pin 0 depending on + the node's direction, otherwise the data in this structure is ignored. + */ + uint32_t node_id; + //! Preferred Gateway DMA buffer size (in bytes). + /*! + FW attempts to allocate DMA buffer according to this value, however it may + fall back to IBS/OBS * 2 in case there is no memory available for deeper + buffering. + */ + uint32_t dma_buffer_size; + //! Length of gateway node configuration blob specified in #config_data. + /*! + \note Length must be specified in number of dwords. + + Refer to the specific gateway documentation for details on the node + configuration blob requirements. + */ + uint32_t config_length; + //! Gateway node configuration blob. + uint32_t config_data[1]; +}; + +struct CopierModuleCfg : BaseModuleCfg +{ + //! Audio format for output pin 0. + AudioDataFormatIpc out_fmt; + //! Mask of allowed copier features. + /*! + \see CopierFeatures + */ + uint32_t copier_feature_mask; + //! Gateway Configuration. + CopierGatewayCfg gtw_cfg; +}; + +enum CopierModuleConfigParams +{ + /*! + Use LARGE_CONFIG_SET to initialize timestamp event. Ipc mailbox must + contain properly built CopierConfigTimestampInitData struct. + */ + COPIER_MODULE_CFG_PARAM_TIMESTAMP_INIT = 1, + /*! + Use LARGE_CONFIG_SET to initialize copier sink. Ipc mailbox must contain + properly built CopierConfigSetSinkFormat struct. + */ + COPIER_MODULE_CFG_PARAM_SET_SINK_FORMAT = 2, + /*! + Use LARGE_CONFIG_SET to initialize and enable on Copier data segment + event. Ipc mailbox must contain properly built DataSegmentEnabled struct. + */ + COPIER_MODULE_CFG_PARAM_DATA_SEGMENT_ENABLED = 3, + /*! + Use LARGE_CONFIG_GET to retrieve Linear Link Position (LLP) value for non + HD-A gateways. + + \see LlpReading + */ + COPIER_MODULE_CFG_PARAM_LLP_READING = 4, + /*! + Use LARGE_CONFIG_GET to retrieve Linear Link Position (LLP) value for non + HD-A gateways and corresponding total processed data + + \see LlpReadingExtended + + Sample code to retrieve LlpReadingExtended: + \code + Message::LargeConfigOp message(true, COPIER_MODULE_ID, KPB_INSTANCE_ID); + message.GetBits().large_param_id = COPIER_MODULE_CFG_PARAM_LLP_READING_EXTENDED; + message.GetBits().init_block = true; + message.GetBits().final_block = true; + message.GetBits().data_off_size = IPC_OUTPUT_MAILBOX; + + LlpReadingExtended* output_mailbox = NULL; + send_ipc(message, input_mailbox, (uint8_t**)&output_mailbox); + + \endcode + */ + COPIER_MODULE_CFG_PARAM_LLP_READING_EXTENDED = 5, + /*! + Use LARGE_CONFIG_SET to setup attenuation on output pins. Data is just + uint32_t. + + \note Config is only allowed when output pin is set up for 32bit and + source is connected to Gateway + */ + COPIER_MODULE_CFG_ATTENUATION = 6 +}; + +struct CopierConfigTimestampInitData +{ + //! Contains low-level configuration for timestamp init. + /*! + Passed-through directly into ifc _LOCAL_TS_Control Register of + corresponding HW i/f from DSP Timestamping Registers. + */ + uint32_t tsctrl_reg; +}; + +struct CopierConfigSetSinkFormat +{ + //! Id of sink + uint32_t sink_id; + //! Input format used by the source + /*! + \attention Must be the same as present if already initialized. + */ + AudioDataFormatIpc source_fmt; + //! Output format used by the sink + AudioDataFormatIpc sink_fmt; +}; + +static const uint32_t COPIER_DATA_SEGMENT_DISABLE = (0 << 0); +static const uint32_t COPIER_DATA_SEGMENT_ENABLE = (1 << 0); +static const uint32_t COPIER_DATA_SEGMENT_RESTART = (1 << 1); + +struct DataSegmentEnabled +{ + //! Gateway node id + uint32_t node_id; + //! Indicates whether notification should be enabled (!=0) or disabled (=0). + /*! + Carries additional information. If bit 1 is set DS will be restarted + immediately. + Use only as logic or of COPIER_DATA_SEGMENT_*. + To disable: + COPIER_DATA_SEGMENT_DISABLE + To enable, but finish previous: + COPIER_DATA_SEGMENT_ENABLE + To enable, and apply right away: + COPIER_DATA_SEGMENT_ENABLE | COPIER_DATA_SEGMENT_RESTART + */ + uint32_t enabled; + //! Data segment size (in bytes). + uint32_t data_seg_size; +}; + +#endif diff --git a/src/include/ipc4/gateway.h b/src/include/ipc4/gateway.h new file mode 100644 index 000000000000..0c34eaeca8ee --- /dev/null +++ b/src/include/ipc4/gateway.h @@ -0,0 +1,191 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + */ + +/** + * \file include/ipc4/header.h + * \brief IPC4 global definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __SOF_IPC4_GATEWAY_H__ +#define __SOF_IPC4_GATEWAY_H__ + +#include + +//! Type of the gateway. +typedef enum _ConnectorNodeIdType +{ + //! HD/A host output (-> DSP). + kHdaHostOutputClass = 0, + //! HD/A host input (<- DSP). + kHdaHostInputClass = 1, + //! HD/A host input/output (rsvd for future use). + kHdaHostInoutClass = 2, + + //! HD/A link output (DSP ->). + kHdaLinkOutputClass = 8, + //! HD/A link input (DSP <-). + kHdaLinkInputClass = 9, + //! HD/A link input/output (rsvd for future use). + kHdaLinkInoutClass = 10, + + //! DMIC link input (DSP <-). + kDmicLinkInputClass = 11, + + //! I2S link output (DSP ->). + kI2sLinkOutputClass = 12, + //! I2S link input (DSP <-). + kI2sLinkInputClass = 13, + + //! ALH link output, legacy for SNDW (DSP ->). + kALHLinkOutputClass = 16, + //! ALH link input, legacy for SNDW (DSP <-). + kALHLinkInputClass = 17, + + //! SNDW link output (DSP ->). + kAlhSndWireStreamLinkOutputClass = 16, + //! SNDW link input (DSP <-). + kAlhSndWireStreamLinkInputClass = 17, + + //! UAOL link output (DSP ->). + kAlhUAOLStreamLinkOutputClass = 18, + //! UAOL link input (DSP <-). + kAlhUAOLStreamLinkInputClass = 19, + + //! IPC output (DSP ->). + kIPCOutputClass = 20, + //! IPC input (DSP <-). + kIPCInputClass = 21, + + //! I2S Multi gtw output (DSP ->). + kI2sMultiLinkOutputClass = 22, + //! I2S Multi gtw input (DSP <-). + kI2sMultiLinkInputClass = 23, + //! GPIO + kGpioClass = 24, + //! SPI + kSpiOutputClass = 25, + kSpiInputClass = 26, + kMaxConnectorNodeIdType +} ConnectorNodeIdType; + +//! Invalid raw node id (to indicate uninitialized node id). +#define kInvalidNodeId 0xffffffff + +//! Base top-level structure of an address of a gateway. +/*! + The virtual index value, presented on the top level as raw 8 bits, + is expected to be encoded in a gateway specific way depending on + the actual type of gateway. +*/ +typedef union _ConnectorNodeId +{ + //! Raw 32-bit value of node id. + uint32_t dw; + //! Bit fields + struct + { + //! Index of the virtual DMA at the gateway. + uint32_t v_index : 8; + + //! Type of the gateway, one of ConnectorNodeId::Type values. + uint32_t dma_type : 5; + + //! Rsvd field. + uint32_t _rsvd : 19; + } f; //!< Bits +} ConnectorNodeId; + +// HD/A Part begins here -> public IO driver + +// TODO: The following HD-A DMA Nodes have IDs defined by c-spec +#define kHwHostOutputNodeIdBase 0x00 +#define kHwCodeLoaderNodeId 0x0F +#define kHwLinkInputNodeIdBase 0x10 + +/*! + Attributes are usually provided along with the gateway configuration + BLOB when the FW is requested to instantiate that gateway. + + There are flags which requests FW to allocate gateway related data + (buffers and other items used while transferring data, like linked list) + to be allocated from a special memory area, e.g low power memory. +*/ +typedef union _GatewayAttributes +{ + //! Raw value + uint32_t dw; + //! Access to the fields + struct + { + //! Gateway data requested in low power memory. + uint32_t lp_buffer_alloc : 1; + + //! Gateway data requested in register file memory. + uint32_t alloc_from_reg_file : 1; + + //! Reserved field + uint32_t _rsvd : 30; + } bits; //!< Bits +} GatewayAttributes; + +//! Configuration for the IPC Gateway +struct IpcGatewayConfigBlob +{ + //! Size of the gateway buffer, specified in bytes + uint32_t buffer_size; + //! Flags + union Flags + { + struct Bits + { + //! Activates high threshold notification + /*! + Indicates whether notification should be sent to the host + when the size of data in the buffer reaches the high threshold + specified by threshold_high parameter. + */ + uint32_t notif_high : 1; + + //! Activates low threshold notification + /*! + Indicates whether notification should be sent to the host + when the size of data in the buffer reaches the low threshold + specified by threshold_low parameter. + */ + uint32_t notif_low : 1; + + //! Reserved field + uint32_t rsvd : 30; + } f; //!< Bits + //! Raw value of flags + uint32_t flags_raw; + } u; //!< Flags + + //! High threshold + /*! + Specifies the high threshold (in bytes) for notifying the host + about the buffered data level. + */ + uint32_t threshold_high; + + //! Low threshold + /*! + Specifies the low threshold (in bytes) for notifying the host + about the buffered data level. + */ + uint32_t threshold_low; +}; + +#endif + diff --git a/src/include/sof/ipc/topology.h b/src/include/sof/ipc/topology.h index 1a1909e3d39f..7356bfdd1db2 100644 --- a/src/include/sof/ipc/topology.h +++ b/src/include/sof/ipc/topology.h @@ -26,6 +26,9 @@ /* generic IPC pipeline regardless of ABI MAJOR type that is always 4 byte aligned */ typedef uint32_t ipc_pipe_new; +typedef uint32_t ipc_pipe_comp_connect; +typedef uint32_t ipc_comp; +typedef uint32_t ipc_dai_config; /* * Topology IPC logic uses standard types for abstract IPC features. This means all ABI MAJOR @@ -33,14 +36,27 @@ typedef uint32_t ipc_pipe_new; */ #if CONFIG_IPC_MAJOR_3 #include -#define ipc_get_pipe_new(x) ((struct sof_ipc_pipe_new *)x) +#define ipc_from_pipe_new(x) ((struct sof_ipc_pipe_new *)x) +#define ipc_from_pipe_connect(x) ((struct sof_ipc_pipe_comp_connect *)x) +#define ipc_from_comp_new(x) ((struct sof_ipc_comp *)x) +#define ipc_from_dai_config(x) ((struct sof_ipc_dai_config *)x) #elif CONFIG_IPC_MAJOR_4 #include -#define ipc_get_pipe_new(x) ((struct ipc4_pipeline_create *)x) +#include +#include +#define ipc_from_pipe_new(x) ((struct ipc4_pipeline_create *)x) +#define ipc_from_pipe_connect(x) ((struct ipc4_module_bind_unbind *)x) +#define ipc_from_comp_new(x) ((struct ipc4_module_init_instance *)x) +#define ipc_from_dai_config(x) ((struct CopierGatewayCfg *)x) #else #error "No or invalid IPC MAJOR version selected." #endif +#define ipc_to_pipe_new(x) ((ipc_pipe_new *)x) +#define ipc_to_pipe_connect(x) ((ipc_pipe_comp_connect *)x) +#define ipc_to_comp_new(x) ((ipc_comp *)x) +#define ipc_to_dai_config(x) ((ipc_dai_config *)x) + struct dai_config; struct ipc_msg; @@ -91,7 +107,7 @@ static inline int32_t ipc_comp_pipe_id(const struct ipc_comp_dev *icd) * @param new New IPC component descriptor. * @return 0 on success or negative error. */ -int ipc_comp_new(struct ipc *ipc, struct sof_ipc_comp *new); +int ipc_comp_new(struct ipc *ipc, ipc_comp *new); /** * \brief Free an IPC component. @@ -147,8 +163,7 @@ int ipc_pipeline_complete(struct ipc *ipc, uint32_t comp_id); * @param connect Components to connect together.. * @return 0 on success or negative error. */ -int ipc_comp_connect(struct ipc *ipc, - struct sof_ipc_pipe_comp_connect *connect); +int ipc_comp_connect(struct ipc *ipc, ipc_pipe_comp_connect *connect); /** * \brief Get component device from component ID. @@ -183,6 +198,6 @@ struct ipc_comp_dev *ipc_get_ppl_comp(struct ipc *ipc, * @param config DAI configuration. * @return 0 on success or negative error. */ -int ipc_comp_dai_config(struct ipc *ipc, struct sof_ipc_dai_config *config); +int ipc_comp_dai_config(struct ipc *ipc, ipc_dai_config *config); #endif diff --git a/src/ipc/handler-ipc3.c b/src/ipc/handler-ipc3.c index 22b39c6fb5f9..38cf4752d738 100644 --- a/src/ipc/handler-ipc3.c +++ b/src/ipc/handler-ipc3.c @@ -501,7 +501,7 @@ static int ipc_dai_config_set(struct sof_ipc_dai_config *config) return 0; } -static int ipc_dai_config(uint32_t header) +static int ipc_msg_dai_config(uint32_t header) { struct ipc *ipc = ipc_get(); struct sof_ipc_dai_config config; @@ -522,7 +522,7 @@ static int ipc_dai_config(uint32_t header) } /* send params to all DAI components who use that physical DAI */ - return ipc_comp_dai_config(ipc, ipc->comp_data); + return ipc_comp_dai_config(ipc, ipc_to_dai_config(ipc->comp_data)); } static int ipc_glb_dai_message(uint32_t header) @@ -531,7 +531,7 @@ static int ipc_glb_dai_message(uint32_t header) switch (cmd) { case SOF_IPC_DAI_CONFIG: - return ipc_dai_config(header); + return ipc_msg_dai_config(header); case SOF_IPC_DAI_LOOPBACK: //return ipc_comp_set_value(header, COMP_CMD_LOOPBACK); default: @@ -1123,7 +1123,7 @@ static int ipc_glb_tplg_comp_new(uint32_t header) comp->pipeline_id, comp->id, comp->type); /* register component */ - ret = ipc_comp_new(ipc, comp); + ret = ipc_comp_new(ipc, ipc_to_comp_new(comp)); if (ret < 0) { tr_err(&ipc_tr, "ipc: pipe %d comp %d creation failed %d", comp->pipeline_id, comp->id, ret); diff --git a/src/ipc/helper-ipc3.c b/src/ipc/helper-ipc3.c index e44d4ff7f460..ce239a02d2c2 100644 --- a/src/ipc/helper-ipc3.c +++ b/src/ipc/helper-ipc3.c @@ -278,7 +278,7 @@ struct comp_dev *comp_new(struct sof_ipc_comp *comp) int ipc_pipeline_new(struct ipc *ipc, ipc_pipe_new *_pipe_desc) { - struct sof_ipc_pipe_new *pipe_desc = ipc_get_pipe_new(_pipe_desc); + struct sof_ipc_pipe_new *pipe_desc = ipc_from_pipe_new(_pipe_desc); struct ipc_comp_dev *ipc_pipe; struct pipeline *pipe; struct ipc_comp_dev *icd; @@ -441,8 +441,9 @@ int ipc_pipeline_complete(struct ipc *ipc, uint32_t comp_id) /* * Configure DAI - TODO: this can be simplified to run only on core 0. */ -int ipc_comp_dai_config(struct ipc *ipc, struct sof_ipc_dai_config *config) +int ipc_comp_dai_config(struct ipc *ipc, ipc_dai_config *_config) { + struct sof_ipc_dai_config *config = ipc_from_dai_config(_config); bool comp_on_core[CONFIG_CORE_COUNT] = { false }; struct sof_ipc_comp_dai *dai; struct sof_ipc_reply reply; @@ -675,9 +676,9 @@ static int ipc_buffer_to_comp_connect(struct ipc_comp_dev *buffer, return ret; } -int ipc_comp_connect(struct ipc *ipc, - struct sof_ipc_pipe_comp_connect *connect) +int ipc_comp_connect(struct ipc *ipc, ipc_pipe_comp_connect *_connect) { + struct sof_ipc_pipe_comp_connect *connect = ipc_from_pipe_connect(_connect); struct ipc_comp_dev *icd_source; struct ipc_comp_dev *icd_sink; @@ -710,8 +711,9 @@ int ipc_comp_connect(struct ipc *ipc, } } -int ipc_comp_new(struct ipc *ipc, struct sof_ipc_comp *comp) +int ipc_comp_new(struct ipc *ipc, ipc_comp *_comp) { + struct sof_ipc_comp *comp = ipc_from_comp_new(_comp); struct comp_dev *cd; struct ipc_comp_dev *icd; diff --git a/src/ipc/helper-ipc4.c b/src/ipc/helper-ipc4.c index 1f3703701de4..4536727e4d42 100644 --- a/src/ipc/helper-ipc4.c +++ b/src/ipc/helper-ipc4.c @@ -65,7 +65,7 @@ struct comp_dev *comp_new(struct sof_ipc_comp *comp) int ipc_pipeline_new(struct ipc *ipc, ipc_pipe_new *_pipe_desc) { - struct ipc4_pipeline_create *pipe_desc = ipc_get_pipe_new(_pipe_desc); + struct ipc4_pipeline_create *pipe_desc = ipc_from_pipe_new(_pipe_desc); struct ipc_comp_dev *ipc_pipe; struct pipeline *pipe; From ed05c682790df2dfc5249f33a5bb4867e9e981d9 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Tue, 27 Apr 2021 10:56:12 +0800 Subject: [PATCH 05/13] ipc4: fix compiling error Port latest change to ipc4-handler Signed-off-by: Rander Wang --- src/ipc/handler-ipc4.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ipc/handler-ipc4.c b/src/ipc/handler-ipc4.c index dbf3cd60c11f..e21a8ceb7407 100644 --- a/src/ipc/handler-ipc4.c +++ b/src/ipc/handler-ipc4.c @@ -98,8 +98,6 @@ static int ipc4_process_glb_message(union ipc4_message_header *ipc4) case SOF_IPC4_GLB_BOOT_CONFIG: case SOF_IPC4_GLB_ROM_CONTROL: case SOF_IPC4_GLB_IPCGATEWAY_CMD: - case SOF_IPC4_GLB_START_RTOS_EDF_TASK: - case SOF_IPC4_GLB_STOP_RTOS_EDF_TASK: case SOF_IPC4_GLB_PERF_MEASUREMENTS_CMD: case SOF_IPC4_GLB_CHAIN_DMA: case SOF_IPC4_GLB_LOAD_MULTIPLE_MODULES: @@ -241,8 +239,8 @@ ipc_cmd_hdr *ipc_compact_read_msg(void) void ipc_cmd(ipc_cmd_hdr *_hdr) { - union ipc4_message_header *in = ipc_get_hdr(_hdr); - union ipc4_message_header *out = ipc_get_hdr(msg_out); + union ipc4_message_header *in = ipc_from_hdr(_hdr); + union ipc4_message_header *out = ipc_from_hdr(msg_out); enum ipc4_message_target target; int err = -EINVAL; From c45a83c37b1dd7cb22dbb189319a4fa25236b9b4 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Mon, 26 Apr 2021 13:05:59 +0800 Subject: [PATCH 06/13] ipc: add fw ready support for ipc4 Signed-off-by: Rander Wang --- src/include/sof/ipc/common.h | 7 +++++++ src/ipc/handler-ipc3.c | 5 +++++ src/ipc/handler-ipc4.c | 6 ++++++ src/platform/intel/cavs/platform.c | 14 ++++++++++---- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/include/sof/ipc/common.h b/src/include/sof/ipc/common.h index f14d470efd44..cee2b67d7263 100644 --- a/src/include/sof/ipc/common.h +++ b/src/include/sof/ipc/common.h @@ -139,6 +139,13 @@ int ipc_process_host_buffer(struct ipc *ipc, */ int ipc_dma_trace_send_position(void); +/** + * \brief create a IPC boot completet message. + * @header[in] msg header. + * @data[in] msg data. + */ +void ipc_boot_complete_msg(ipc_cmd_hdr *header, uint32_t *data); + /** * \brief Read a compact IPC message or return NULL for normal message. * @return Pointer to the compact message data. diff --git a/src/ipc/handler-ipc3.c b/src/ipc/handler-ipc3.c index 38cf4752d738..68b43bda3da4 100644 --- a/src/ipc/handler-ipc3.c +++ b/src/ipc/handler-ipc3.c @@ -1421,6 +1421,11 @@ ipc_cmd_hdr *ipc_compact_read_msg(void) } #endif +void ipc_boot_complete_msg(ipc_cmd_hdr *header, uint32_t *data) +{ + *header = SOF_IPC_FW_READY; +} + /* * Global IPC Operations. */ diff --git a/src/ipc/handler-ipc4.c b/src/ipc/handler-ipc4.c index e21a8ceb7407..e4d5ea9d675e 100644 --- a/src/ipc/handler-ipc4.c +++ b/src/ipc/handler-ipc4.c @@ -237,6 +237,12 @@ ipc_cmd_hdr *ipc_compact_read_msg(void) return ipc_to_hdr(msg_in); } +void ipc_boot_complete_msg(ipc_cmd_hdr *header, uint32_t *data) +{ + *header = SOF_IPC4_FW_READY; + *data = 0; +} + void ipc_cmd(ipc_cmd_hdr *_hdr) { union ipc4_message_header *in = ipc_from_hdr(_hdr); diff --git a/src/platform/intel/cavs/platform.c b/src/platform/intel/cavs/platform.c index f0ae31880c4b..1f01d5535a1f 100644 --- a/src/platform/intel/cavs/platform.c +++ b/src/platform/intel/cavs/platform.c @@ -292,6 +292,9 @@ int platform_boot_complete(uint32_t boot_message) int platform_boot_complete(uint32_t boot_message) { + ipc_cmd_hdr header; + uint32_t data; + #if CONFIG_TIGERLAKE && !CONFIG_CAVS_LPRO_ONLY /* TGL specific HW recommended flow */ pm_runtime_get(PM_RUNTIME_DSP, PWRD_BY_HPRO | (CONFIG_CORE_COUNT - 1)); @@ -299,13 +302,16 @@ int platform_boot_complete(uint32_t boot_message) mailbox_dspbox_write(0, &ready, sizeof(ready)); + data = SRAM_WINDOW_HOST_OFFSET(0) >> 12; + ipc_boot_complete_msg(&header, &data); + /* tell host we are ready */ #if CAVS_VERSION == CAVS_VERSION_1_5 - ipc_write(IPC_DIPCIE, SRAM_WINDOW_HOST_OFFSET(0) >> 12); - ipc_write(IPC_DIPCI, IPC_DIPCI_BUSY | SOF_IPC_FW_READY); + ipc_write(IPC_DIPCIE, data); + ipc_write(IPC_DIPCI, IPC_DIPCI_BUSY | header); #else - ipc_write(IPC_DIPCIDD, SRAM_WINDOW_HOST_OFFSET(0) >> 12); - ipc_write(IPC_DIPCIDR, IPC_DIPCIDR_BUSY | SOF_IPC_FW_READY); + ipc_write(IPC_DIPCIDD, data); + ipc_write(IPC_DIPCIDR, IPC_DIPCIDR_BUSY | header); #endif return 0; } From 1cf4bc3e57de78805ee5554cd77b8fa4cd5ca02b Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Tue, 27 Apr 2021 15:22:30 +0800 Subject: [PATCH 07/13] ipc4: process ipc message for ipc4 Ipc3 only uses DIPCIDR to send dsp message, but ipc4 uses both DIPCIDR and DIPCIDD. Now get DIPCIDD data from msg tx_data. Signed-off-by: Rander Wang --- src/drivers/intel/cavs/ipc.c | 13 +++++++------ src/include/sof/ipc/common.h | 7 +++++++ src/ipc/handler-ipc3.c | 11 +++++++++++ src/ipc/handler-ipc4.c | 12 ++++++++++++ 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/drivers/intel/cavs/ipc.c b/src/drivers/intel/cavs/ipc.c index 74bfbbf7793b..0010688d4e87 100644 --- a/src/drivers/intel/cavs/ipc.c +++ b/src/drivers/intel/cavs/ipc.c @@ -233,6 +233,7 @@ void ipc_platform_complete_cmd(void *data) int ipc_platform_send_msg(struct ipc_msg *msg) { struct ipc *ipc = ipc_get(); + ipc_cmd_hdr *hdr; int ret = 0; if (ipc->is_notification_pending || @@ -246,20 +247,20 @@ int ipc_platform_send_msg(struct ipc_msg *msg) goto out; } - /* now send the message */ - mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); list_item_del(&msg->list); tr_dbg(&ipc_tr, "ipc: msg tx -> 0x%x", msg->header); ipc->is_notification_pending = true; + hdr = ipc_process_msg(msg); + /* now interrupt host to tell it we have message sent */ #if CAVS_VERSION == CAVS_VERSION_1_5 - ipc_write(IPC_DIPCIE, 0); - ipc_write(IPC_DIPCI, IPC_DIPCI_BUSY | msg->header); + ipc_write(IPC_DIPCIE, hdr[1]); + ipc_write(IPC_DIPCI, IPC_DIPCI_BUSY | hdr[0]); #else - ipc_write(IPC_DIPCIDD, 0); - ipc_write(IPC_DIPCIDR, IPC_DIPCIDR_BUSY | msg->header); + ipc_write(IPC_DIPCIDD, hdr[1]); + ipc_write(IPC_DIPCIDR, IPC_DIPCIDR_BUSY | hdr[0]); #endif out: diff --git a/src/include/sof/ipc/common.h b/src/include/sof/ipc/common.h index cee2b67d7263..ed88442ee7fd 100644 --- a/src/include/sof/ipc/common.h +++ b/src/include/sof/ipc/common.h @@ -159,6 +159,13 @@ ipc_cmd_hdr *ipc_compact_read_msg(void); */ int ipc_compact_write_msg(ipc_cmd_hdr *hdr); +/** + * \brief process a dsp IPC message. + * @msg[in] ipc msg. + * @return Number of words written. + */ +ipc_cmd_hdr *ipc_process_msg(struct ipc_msg *msg); + /** * \brief Validate mailbox contents for valid IPC header. * @return pointer to header if valid or NULL. diff --git a/src/ipc/handler-ipc3.c b/src/ipc/handler-ipc3.c index 68b43bda3da4..b40e7774006c 100644 --- a/src/ipc/handler-ipc3.c +++ b/src/ipc/handler-ipc3.c @@ -1421,6 +1421,17 @@ ipc_cmd_hdr *ipc_compact_read_msg(void) } #endif +static uint32_t msg_out[2]; /* local copy of current message to host header */ +ipc_cmd_hdr *ipc_process_msg(struct ipc_msg *msg) +{ + msg_out[0] = msg->header; + msg_out[1] = 0; + + mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); + + return ipc_to_hdr(msg_out); +} + void ipc_boot_complete_msg(ipc_cmd_hdr *header, uint32_t *data) { *header = SOF_IPC_FW_READY; diff --git a/src/ipc/handler-ipc4.c b/src/ipc/handler-ipc4.c index e4d5ea9d675e..c8a8292df501 100644 --- a/src/ipc/handler-ipc4.c +++ b/src/ipc/handler-ipc4.c @@ -237,6 +237,18 @@ ipc_cmd_hdr *ipc_compact_read_msg(void) return ipc_to_hdr(msg_in); } +ipc_cmd_hdr *ipc_process_msg(struct ipc_msg *msg) +{ + msg_out[0] = msg->header; + msg_out[1] = *(uint32_t *)msg->tx_data; + + /* the first uint of msg data is sent by ipc data register for ipc4 */ + msg->tx_size -= sizeof(uint32_t); + mailbox_dspbox_write(0, (uint32_t *)msg->tx_data + 1, msg->tx_size); + + return ipc_to_hdr(msg_out); +} + void ipc_boot_complete_msg(ipc_cmd_hdr *header, uint32_t *data) { *header = SOF_IPC4_FW_READY; From 70772b4f8dbfd222c5a7e15784a1c62226df0f4b Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Tue, 27 Apr 2021 15:57:25 +0800 Subject: [PATCH 08/13] ipc4: reply ipc message status to host Fw creates a dsp ipc message to send status of the last host ipc message. Signed-off-by: Rander Wang --- src/include/ipc4/header.h | 34 ++++++++++++++++++++++++++++++++++ src/ipc/handler-ipc4.c | 26 +++++++++++++++----------- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/src/include/ipc4/header.h b/src/include/ipc4/header.h index 2231fd78cede..d3e6e08bcc45 100644 --- a/src/include/ipc4/header.h +++ b/src/include/ipc4/header.h @@ -109,4 +109,38 @@ union ipc4_message_header { } r; } __attribute__((packed, aligned(4))); +struct ipc4_message_reply { + union { + uint32_t dat; + + struct { + //! Processing status, one of IxcStatus values + uint32_t status :24; + + //! Type, symmetric to Msg + uint32_t type : 5; + + //! MSG_REPLY + uint32_t rsp : 1; + + //! same as request, one of FW_GEN_MSG, MODULE_MSG + uint32_t msg_tgt : 1; + + //! Reserved field (HW ctrl bits) + uint32_t _reserved_0: 1; + } r; + } header; + + union { + uint32_t dat; + + struct { + //! Reserved field + uint32_t rsvd1 : 30; + + //! Reserved field (HW ctrl bits) + uint32_t _reserved_2: 2; + } r; + } data; +} __attribute((packed, aligned(4))); #endif diff --git a/src/ipc/handler-ipc4.c b/src/ipc/handler-ipc4.c index c8a8292df501..382564666fc6 100644 --- a/src/ipc/handler-ipc4.c +++ b/src/ipc/handler-ipc4.c @@ -224,6 +224,8 @@ ipc_cmd_hdr *mailbox_validate(void) */ static uint32_t msg_in[2]; /* local copy of current message from host header */ static uint32_t msg_out[2]; /* local copy of current message to host header */ +static struct ipc_msg msg_reply; +static uint32_t msg_data; ipc_cmd_hdr *ipc_compact_read_msg(void) { @@ -244,7 +246,8 @@ ipc_cmd_hdr *ipc_process_msg(struct ipc_msg *msg) /* the first uint of msg data is sent by ipc data register for ipc4 */ msg->tx_size -= sizeof(uint32_t); - mailbox_dspbox_write(0, (uint32_t *)msg->tx_data + 1, msg->tx_size); + if (msg->tx_size) + mailbox_dspbox_write(0, (uint32_t *)msg->tx_data + 1, msg->tx_size); return ipc_to_hdr(msg_out); } @@ -258,7 +261,6 @@ void ipc_boot_complete_msg(ipc_cmd_hdr *header, uint32_t *data) void ipc_cmd(ipc_cmd_hdr *_hdr) { union ipc4_message_header *in = ipc_from_hdr(_hdr); - union ipc4_message_header *out = ipc_from_hdr(msg_out); enum ipc4_message_target target; int err = -EINVAL; @@ -286,16 +288,18 @@ void ipc_cmd(ipc_cmd_hdr *_hdr) /* FW sends a ipc message to host if request bit is set*/ if (in->r.rsp == SOF_IPC4_MESSAGE_DIR_MSG_REQUEST) { - //struct ipc *ipc = ipc_get(); + struct ipc4_message_reply reply; /* copy contents of message received */ - *out = *in; - out->r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REPLY; - - // TODO: validate and create reply header - err = ipc_platform_compact_write_msg(ipc_to_hdr(out), 2); - if (err != 2) { - tr_err(&ipc_tr, "ipc4: reply %d failed ....", target); - } + reply.header.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REPLY; + reply.header.r.status = err; + reply.header.r.msg_tgt = in->r.msg_tgt; + reply.header.r.type = in->r.type; + reply.data.dat = 0; + + msg_reply.header = reply.header.dat; + msg_reply.tx_data = &msg_data; + msg_reply.tx_size = sizeof(msg_data); + ipc_msg_send(&msg_reply, &reply.data.dat, true); } } From 337a1a8d6bc56ceb5d72ba4dc8f63cf8810d520d Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Tue, 27 Apr 2021 17:00:43 +0800 Subject: [PATCH 09/13] ipc4: add dmic & ssp header file for ipc4 Signed-off-by: Rander Wang --- src/include/ipc4/dmic.h | 118 ++++++++++++++++++++++++++++++++++++++ src/include/ipc4/ssp.h | 124 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 242 insertions(+) create mode 100644 src/include/ipc4/dmic.h create mode 100644 src/include/ipc4/ssp.h diff --git a/src/include/ipc4/dmic.h b/src/include/ipc4/dmic.h new file mode 100644 index 000000000000..46ff2f099161 --- /dev/null +++ b/src/include/ipc4/dmic.h @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + */ + +/** + * \file include/ipc4/dmic.h + * \brief IPC4 global definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __SOF_IPC4_DMIC_H__ +#define __SOF_IPC4_DMIC_H__ + +#include +#include + +/* + * If there is only one PDM controller configuration passed, + * the other (missing) one is configured by the driver just by + * clearing CIC_CONTROL.SOFT_RESET bit. + * The driver needs to make sure that all mics are disabled + * before starting to program PDM controllers. + */ +struct sof_fir_config { + uint32_t fir_control; + uint32_t fir_config; + uint32_t dc_offset_left; + uint32_t dc_offset_right; + uint32_t out_gain_left; + uint32_t out_gain_right; + uint32_t rsvd_2[2]; +} __attribute__((packed, aligned(4))); + +/* + * Note that FIR array may be provided in either packed or unpacked format. + * see FIR_COEFFS_PACKED_TO_24_BITS. + * Since in many cases all PDMs are programmed with the same FIR settings, + * it is possible to provide it in a single copy inside the BLOB and refer + * to that from other PDM configurations \see reuse_fir_from_pdm. + */ +struct sof_pdm_ctrl_cfg { + uint32_t cic_control; + uint32_t cic_config; + uint32_t rsvd_0; + uint32_t mic_control; + /* this field is used on platforms with SoundWire, otherwise ignored */ + uint32_t pdmsm; + //! Index of another PDMCtrlCfg to be used as a source of FIR coefficients. + /*! + \note The index is 1-based, value of 0 means that FIR coefficients + array fir_coeffs is provided by this item. + This is a very common case that the same FIR coefficients are used + to program more than one PDM controller. In this case, fir_coeffs array + may be provided in a single copy following PdmCtrlCfg #0 and be reused + by PdmCtrlCfg #1 by setting reuse_fir_from_pdm to 1 (1-based index). + */ + uint32_t reuse_fir_from_pdm; + uint32_t rsvd_1[2]; + struct sof_fir_config fir_config[2]; + + /* + * Array of FIR coefficients, channel A goes first, then channel B. + * Actual size of the array depends on the number of active taps of the + * FIR filter for channel A plus the number of active taps of the FIR filter + * for channel B (see FIR_CONFIG) as well as on the form (packed/unpacked) + * of values. + */ + uint32_t fir_coeffs[0]; +} __attribute__((packed, aligned(4))); + +struct sof_dmic_config_blob { + /* time-slot mappings */ + uint32_t ts_group[4]; + + /* expected value is 1-3ms. typical value is 1ms */ + uint32_t clock_on_delay; + + /* + * PDM channels to be programmed using data from channel_cfg array. + * i'th bit = 1 means that configuration for PDM channel # i is provided + */ + uint32_t channel_ctrl_mask; + + //! PDM channel configuration settings + /*! + Actual number of items depends on channel_ctrl_mask (# of 1's). + */ + uint32_t channel_cfg; + + //! PDM controllers to be programmed using data from pdm_ctrl_cfg array. + /*! + i'th bit = 1 means that configuration for PDM controller # i is provided. + */ + uint32_t pdm_ctrl_mask; + + //! PDM controller configuration settings + /*! + Actual number of items depends on pdm_ctrl_mask (# of 1's). + */ + struct sof_pdm_ctrl_cfg pdm_ctrl_cfg[0]; +} __attribute__((packed, aligned(4))); + +//DMIC gateway configuration data +struct sof_dmic_config_data { + GatewayAttributes gtw_attributes; + struct sof_dmic_config_blob dmic_config_blob; +} __attribute__((packed, aligned(4))); + +#endif diff --git a/src/include/ipc4/ssp.h b/src/include/ipc4/ssp.h new file mode 100644 index 000000000000..4ab44cb35851 --- /dev/null +++ b/src/include/ipc4/ssp.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + */ + +/** + * \file include/ipc4/ssp.h + * \brief IPC4 global definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __SOF_IPC4_SSP_H__ +#define __SOF_IPC4_SSP_H__ + +#include +#include + +#define I2S_TDM_INVALID_SLOT_MAP1 0xF +#define I2S_TDM_MAX_CHANNEL_COUNT 8 +#define I2S_TDM_MAX_SLOT_MAP_COUNT 8 + +/* i2s Configuration BLOB building blocks */ + +/* i2s registers for i2s Configuration */ +struct sof_i2s_config { + uint32_t ssc0; + uint32_t ssc1; + uint32_t sscto; + uint32_t sspsp; + uint32_t sstsa; + uint32_t ssrsa; + uint32_t ssc2; + uint32_t sspsp2; + uint32_t ssc3; + uint32_t ssioc; +} __attribute__((packed, aligned(4))); + +struct sof_mclk_config { + /* master clock divider control register */ + uint32_t mdivc; + + /* master clock divider ratio register */ + uint32_t mdivr; +} __attribute__((packed, aligned(4))); + +struct sof_i2s_driver_config { + struct sof_i2s_config i2s_config; + struct sof_mclk_config mclk_config; +} __attribute__((packed, aligned(4))); + +struct sof_i2s_start_control { + /* + delay in msec between enabling interface (moment when Copier + instance is being attached to the interface) and actual + interface start. Value of 0 means no delay. + */ + uint32_t clock_warm_up : 16; + + /* specifies if parameters target MCLK (1) or SCLK (0) */ + uint32_t mclk : 1; + + /* + value of 1 means that clock should be started immediately + even if no Copier instance is currently attached to the interface. + */ + uint32_t warm_up_ovr : 1; + uint32_t rsvd0 : 14; +} __attribute__((packed, aligned(4))); + +struct sof_i2s_stop_control { + /* + delay in msec between stopping the interface + (moment when Copier instance is being detached from the interface) + and interface clock stop. Value of 0 means no delay. + */ + uint32_t clock_stop_delay : 16; + + /* + value of 1 means that clock should be kept running (infinite + stop delay) after Copier instance detaches from the interface. + */ + uint32_t keep_running : 1; + + /* + value of 1 means that clock should be stopped immediately. + */ + uint32_t clock_stop_ovr : 1; + uint32_t rsvd1 : 14; +} __attribute__((packed, aligned(4))); + +union sof_i2s_dma_control { + struct ControlData { + struct sof_i2s_start_control start_control; + struct sof_i2s_stop_control stop_control; + } control_data; + + struct MnDivControlData { + uint32_t mval; + uint32_t nval; + } mndiv_control_data; +} __attribute__((packed, aligned(4))); + +struct sof_i2s_configuration_blob { + GatewayAttributes gw_attr; + + /* TDM time slot mappings */ + uint32_t tdm_ts_group[I2S_TDM_MAX_SLOT_MAP_COUNT]; + + /* i2s port configuration */ + struct sof_i2s_driver_config i2s_driver_config; + + /* optional configuration parameters */ + union sof_i2s_dma_control i2s_dma_control[0]; +} __attribute__((packed, aligned(4))); + +#endif From 04779a19210afe30b4fb4ca98ec81198812c1283 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 27 Apr 2021 19:53:51 +0800 Subject: [PATCH 10/13] ipc4: add alh header file for ipc4 Add alh header file for ipc4. Signed-off-by: Bard Liao --- src/include/ipc4/alh.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/include/ipc4/alh.h diff --git a/src/include/ipc4/alh.h b/src/include/ipc4/alh.h new file mode 100644 index 000000000000..3a00cfa94057 --- /dev/null +++ b/src/include/ipc4/alh.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +#ifndef __SOF_IPC4_ALH_H__ +#define __SOF_IPC4_ALH_H__ + +#define ALH_MAX_NUMBER_OF_GTW 16 + +struct AlhMultiGtwCfg { + /* Number of single channels (valid items in mapping array). */ + uint32_t count; + /* Single to multi aggregation mapping item. */ + struct { + /* Vindex of a single ALH channel aggregated. */ + uint32_t alh_id; + /* Channel mask */ + uint32_t channel_mask; + } mapping[ALH_MAX_NUMBER_OF_GTW]; /* < Mapping items */ +} __attribute__((packed, aligned(4))); + +struct sof_alh_configuration_blob { + GatewayAttributes gtw_attributes; + struct AlhMultiGtwCfg alh_cfg; +} __attribute__((packed, aligned(4))); + +#endif From 2f9a09a04352baed5379e5d07609d70bec99a13c Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Tue, 27 Apr 2021 16:04:08 +0100 Subject: [PATCH 11/13] ipc: abstraction: ipc4 header cleanup Signed-off-by: Liam Girdwood --- src/include/ipc4/alh.h | 23 ++++++++++++++++++++--- src/include/ipc4/copier.h | 26 +++++++++++++------------- src/include/ipc4/dmic.h | 16 ++++++++-------- src/include/ipc4/gateway.h | 16 ++++++++-------- src/include/ipc4/ssp.h | 32 ++++++++++++++++---------------- 5 files changed, 65 insertions(+), 48 deletions(-) diff --git a/src/include/ipc4/alh.h b/src/include/ipc4/alh.h index 3a00cfa94057..2320cf2cb035 100644 --- a/src/include/ipc4/alh.h +++ b/src/include/ipc4/alh.h @@ -3,12 +3,29 @@ * Copyright(c) 2021 Intel Corporation. All rights reserved. */ +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + */ + +/** + * \file include/ipc4/alh.h + * \brief IPC4 global definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + #ifndef __SOF_IPC4_ALH_H__ #define __SOF_IPC4_ALH_H__ +#include +#include + #define ALH_MAX_NUMBER_OF_GTW 16 -struct AlhMultiGtwCfg { +struct ipc4_alh_multi_gtw_cfg { /* Number of single channels (valid items in mapping array). */ uint32_t count; /* Single to multi aggregation mapping item. */ @@ -21,8 +38,8 @@ struct AlhMultiGtwCfg { } __attribute__((packed, aligned(4))); struct sof_alh_configuration_blob { - GatewayAttributes gtw_attributes; - struct AlhMultiGtwCfg alh_cfg; + union ipc4_gateway_attributes gtw_attributes; + struct ipc4_alh_multi_gtw_cfg alh_cfg; } __attribute__((packed, aligned(4))); #endif diff --git a/src/include/ipc4/copier.h b/src/include/ipc4/copier.h index e477622cc696..7f06ee442079 100644 --- a/src/include/ipc4/copier.h +++ b/src/include/ipc4/copier.h @@ -46,7 +46,7 @@ struct LlpReading uint32_t wclk_l; //! upper part of 64-bit Wallclock uint32_t wclk_u; -}; +} __attribute__((packed, aligned(4))); struct LlpReadingExtended { @@ -55,7 +55,7 @@ struct LlpReadingExtended uint32_t tpd_low; //! total processed data (high part) uint32_t tpd_high; -}; +} __attribute__((packed, aligned(4))); struct BaseModuleCfgExt { @@ -86,7 +86,7 @@ struct BaseModuleCfgExt * \brief Specifies format of output pins. */ intel_adsp::OutputPinFormat output_pins[1]; -}; +} __attribute__((packed, aligned(4))); /** * This enum defines short 16bit parameters common for all modules. @@ -122,14 +122,14 @@ struct PinProps /*! Unique ID of the physical queue connected to the pin. If there is no queue connected, then -1 (invalid queue ID) is set. */ uint32_t phys_queue_id; -}; +} __attribute__((packed, aligned(4))); struct PinListInfo { uint32_t pin_count; PinProps pin_info[1]; -}; +} __attribute__((packed, aligned(4))); /** * Helper structure definition. @@ -139,7 +139,7 @@ struct InOutGateway { uint32_t input_gateway; uint32_t output_gateway; -}; +} __attribute__((packed, aligned(4))); /** * Structure describing module instance properties used in response @@ -166,7 +166,7 @@ struct ModuleInstanceProps PinListInfo output_queues; uint32_t input_gateway; uint32_t output_gateway; -}; +} __attribute__((packed, aligned(4))); /** * This structure may be used by modules to carry @@ -189,7 +189,7 @@ union CfgParamIdData f.id = id; f.data16 = data16; } -}; +} __attribute__((packed, aligned(4))); /*! \name Copier Module Configuration & Interface @@ -316,7 +316,7 @@ struct CopierGatewayCfg uint32_t config_length; //! Gateway node configuration blob. uint32_t config_data[1]; -}; +} __attribute__((packed, aligned(4))); struct CopierModuleCfg : BaseModuleCfg { @@ -329,7 +329,7 @@ struct CopierModuleCfg : BaseModuleCfg uint32_t copier_feature_mask; //! Gateway Configuration. CopierGatewayCfg gtw_cfg; -}; +} __attribute__((packed, aligned(4))); enum CopierModuleConfigParams { @@ -393,7 +393,7 @@ struct CopierConfigTimestampInitData corresponding HW i/f from DSP Timestamping Registers. */ uint32_t tsctrl_reg; -}; +} __attribute__((packed, aligned(4))); struct CopierConfigSetSinkFormat { @@ -406,7 +406,7 @@ struct CopierConfigSetSinkFormat AudioDataFormatIpc source_fmt; //! Output format used by the sink AudioDataFormatIpc sink_fmt; -}; +} __attribute__((packed, aligned(4))); static const uint32_t COPIER_DATA_SEGMENT_DISABLE = (0 << 0); static const uint32_t COPIER_DATA_SEGMENT_ENABLE = (1 << 0); @@ -431,6 +431,6 @@ struct DataSegmentEnabled uint32_t enabled; //! Data segment size (in bytes). uint32_t data_seg_size; -}; +} __attribute__((packed, aligned(4))); #endif diff --git a/src/include/ipc4/dmic.h b/src/include/ipc4/dmic.h index 46ff2f099161..bb157604d05d 100644 --- a/src/include/ipc4/dmic.h +++ b/src/include/ipc4/dmic.h @@ -30,7 +30,7 @@ * The driver needs to make sure that all mics are disabled * before starting to program PDM controllers. */ -struct sof_fir_config { +struct ipc4_dmic_fir_config { uint32_t fir_control; uint32_t fir_config; uint32_t dc_offset_left; @@ -47,7 +47,7 @@ struct sof_fir_config { * it is possible to provide it in a single copy inside the BLOB and refer * to that from other PDM configurations \see reuse_fir_from_pdm. */ -struct sof_pdm_ctrl_cfg { +struct ipc4_dmic_pdm_ctrl_cfg { uint32_t cic_control; uint32_t cic_config; uint32_t rsvd_0; @@ -65,7 +65,7 @@ struct sof_pdm_ctrl_cfg { */ uint32_t reuse_fir_from_pdm; uint32_t rsvd_1[2]; - struct sof_fir_config fir_config[2]; + struct ipc4_dmic_fir_config fir_config[2]; /* * Array of FIR coefficients, channel A goes first, then channel B. @@ -77,7 +77,7 @@ struct sof_pdm_ctrl_cfg { uint32_t fir_coeffs[0]; } __attribute__((packed, aligned(4))); -struct sof_dmic_config_blob { +struct ipc4_dmic_config_blob { /* time-slot mappings */ uint32_t ts_group[4]; @@ -106,13 +106,13 @@ struct sof_dmic_config_blob { /*! Actual number of items depends on pdm_ctrl_mask (# of 1's). */ - struct sof_pdm_ctrl_cfg pdm_ctrl_cfg[0]; + struct ipc4_dmic_pdm_ctrl_cfg pdm_ctrl_cfg[0]; } __attribute__((packed, aligned(4))); //DMIC gateway configuration data -struct sof_dmic_config_data { - GatewayAttributes gtw_attributes; - struct sof_dmic_config_blob dmic_config_blob; +struct ipc4_dmic_config_data { + union ipc4_gateway_attributes gtw_attributes; + struct ipc4_dmic_config_blob dmic_config_blob; } __attribute__((packed, aligned(4))); #endif diff --git a/src/include/ipc4/gateway.h b/src/include/ipc4/gateway.h index 0c34eaeca8ee..05c026c09c73 100644 --- a/src/include/ipc4/gateway.h +++ b/src/include/ipc4/gateway.h @@ -23,7 +23,7 @@ #include //! Type of the gateway. -typedef enum _ConnectorNodeIdType +enum ipc4_connector_node_id_type { //! HD/A host output (-> DSP). kHdaHostOutputClass = 0, @@ -77,7 +77,7 @@ typedef enum _ConnectorNodeIdType kSpiOutputClass = 25, kSpiInputClass = 26, kMaxConnectorNodeIdType -} ConnectorNodeIdType; +}; //! Invalid raw node id (to indicate uninitialized node id). #define kInvalidNodeId 0xffffffff @@ -88,7 +88,7 @@ typedef enum _ConnectorNodeIdType is expected to be encoded in a gateway specific way depending on the actual type of gateway. */ -typedef union _ConnectorNodeId +union ipc4_connector_node_id { //! Raw 32-bit value of node id. uint32_t dw; @@ -104,11 +104,11 @@ typedef union _ConnectorNodeId //! Rsvd field. uint32_t _rsvd : 19; } f; //!< Bits -} ConnectorNodeId; +} __attribute__((packed, aligned(4))); // HD/A Part begins here -> public IO driver -// TODO: The following HD-A DMA Nodes have IDs defined by c-spec +// TODO: The following HD-A DMA Nodes have IDs defined by spec #define kHwHostOutputNodeIdBase 0x00 #define kHwCodeLoaderNodeId 0x0F #define kHwLinkInputNodeIdBase 0x10 @@ -121,7 +121,7 @@ typedef union _ConnectorNodeId (buffers and other items used while transferring data, like linked list) to be allocated from a special memory area, e.g low power memory. */ -typedef union _GatewayAttributes +union ipc4_gateway_attributes { //! Raw value uint32_t dw; @@ -137,7 +137,7 @@ typedef union _GatewayAttributes //! Reserved field uint32_t _rsvd : 30; } bits; //!< Bits -} GatewayAttributes; +} __attribute__((packed, aligned(4))); //! Configuration for the IPC Gateway struct IpcGatewayConfigBlob @@ -185,7 +185,7 @@ struct IpcGatewayConfigBlob about the buffered data level. */ uint32_t threshold_low; -}; +} __attribute__((packed, aligned(4))); #endif diff --git a/src/include/ipc4/ssp.h b/src/include/ipc4/ssp.h index 4ab44cb35851..db26a4b0589b 100644 --- a/src/include/ipc4/ssp.h +++ b/src/include/ipc4/ssp.h @@ -30,7 +30,7 @@ /* i2s Configuration BLOB building blocks */ /* i2s registers for i2s Configuration */ -struct sof_i2s_config { +struct ipc4_ssp_config { uint32_t ssc0; uint32_t ssc1; uint32_t sscto; @@ -43,7 +43,7 @@ struct sof_i2s_config { uint32_t ssioc; } __attribute__((packed, aligned(4))); -struct sof_mclk_config { +struct ipc4_ssp_mclk_config { /* master clock divider control register */ uint32_t mdivc; @@ -51,12 +51,12 @@ struct sof_mclk_config { uint32_t mdivr; } __attribute__((packed, aligned(4))); -struct sof_i2s_driver_config { - struct sof_i2s_config i2s_config; - struct sof_mclk_config mclk_config; +struct ipc4_ssp_driver_config { + struct ipc4_ssp_config i2s_config; + struct ipc4_ssp_mclk_config mclk_config; } __attribute__((packed, aligned(4))); -struct sof_i2s_start_control { +struct ipc4_ssp_start_control { /* delay in msec between enabling interface (moment when Copier instance is being attached to the interface) and actual @@ -75,7 +75,7 @@ struct sof_i2s_start_control { uint32_t rsvd0 : 14; } __attribute__((packed, aligned(4))); -struct sof_i2s_stop_control { +struct ipc4_ssp_stop_control { /* delay in msec between stopping the interface (moment when Copier instance is being detached from the interface) @@ -96,29 +96,29 @@ struct sof_i2s_stop_control { uint32_t rsvd1 : 14; } __attribute__((packed, aligned(4))); -union sof_i2s_dma_control { - struct ControlData { - struct sof_i2s_start_control start_control; - struct sof_i2s_stop_control stop_control; +union ipc4_ssp_dma_control { + struct ipc4_ssp_control { + struct ipc4_ssp_start_control start_control; + struct ipc4_ssp_stop_control stop_control; } control_data; - struct MnDivControlData { + struct ipc4_mn_div_config { uint32_t mval; uint32_t nval; } mndiv_control_data; } __attribute__((packed, aligned(4))); -struct sof_i2s_configuration_blob { - GatewayAttributes gw_attr; +struct ipc4_ssp_configuration_blob { + union ipc4_gateway_attributes gw_attr; /* TDM time slot mappings */ uint32_t tdm_ts_group[I2S_TDM_MAX_SLOT_MAP_COUNT]; /* i2s port configuration */ - struct sof_i2s_driver_config i2s_driver_config; + struct ipc4_ssp_driver_config i2s_driver_config; /* optional configuration parameters */ - union sof_i2s_dma_control i2s_dma_control[0]; + union ipc4_ssp_dma_control i2s_dma_control[0]; } __attribute__((packed, aligned(4))); #endif From c71da8f07f742bc987af757e5145706de504a8f1 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Tue, 27 Apr 2021 21:02:58 +0100 Subject: [PATCH 12/13] ipc: abstraction: ipc4 use gateway Signed-off-by: Liam Girdwood --- src/include/sof/ipc/topology.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/sof/ipc/topology.h b/src/include/sof/ipc/topology.h index 7356bfdd1db2..4cb525db68f3 100644 --- a/src/include/sof/ipc/topology.h +++ b/src/include/sof/ipc/topology.h @@ -47,7 +47,7 @@ typedef uint32_t ipc_dai_config; #define ipc_from_pipe_new(x) ((struct ipc4_pipeline_create *)x) #define ipc_from_pipe_connect(x) ((struct ipc4_module_bind_unbind *)x) #define ipc_from_comp_new(x) ((struct ipc4_module_init_instance *)x) -#define ipc_from_dai_config(x) ((struct CopierGatewayCfg *)x) +#define ipc_from_dai_config(x) ((union ipc4_gateway_attributes *)x) #else #error "No or invalid IPC MAJOR version selected." #endif From a08969abb6bc9b57839b9dd92d252491d3db39ad Mon Sep 17 00:00:00 2001 From: Jaska Uimonen Date: Wed, 28 Apr 2021 20:39:34 +0300 Subject: [PATCH 13/13] codec adapter: move generic mem alloc to component Codec adapter has a devm_kzalloc type memory allocator to allocate multiple chunks of memory into a list, which can be then freed without explicit pointers in codec deletion. Move this generic mechanism to component class. Signed-off-by: Jaska Uimonen --- src/audio/codec_adapter/codec/cadence.c | 23 ++---- src/audio/codec_adapter/codec/generic.c | 81 +------------------ src/audio/codec_adapter/codec/waves.c | 19 ++--- src/audio/component.c | 54 +++++++++++++ .../sof/audio/codec_adapter/codec/generic.h | 14 ---- src/include/sof/audio/component.h | 11 +++ 6 files changed, 81 insertions(+), 121 deletions(-) diff --git a/src/audio/codec_adapter/codec/cadence.c b/src/audio/codec_adapter/codec/cadence.c index 25cb117d275f..a83b1f463ab2 100644 --- a/src/audio/codec_adapter/codec/cadence.c +++ b/src/audio/codec_adapter/codec/cadence.c @@ -90,7 +90,7 @@ int cadence_codec_init(struct comp_dev *dev) comp_dbg(dev, "cadence_codec_init() start"); - cd = codec_allocate_memory(dev, sizeof(struct cadence_codec_data), 0); + cd = comp_devm_alloc(dev, sizeof(struct cadence_codec_data), 0); if (!cd) { comp_err(dev, "cadence_codec_init(): failed to allocate memory for cadence codec data"); return -ENOMEM; @@ -122,7 +122,7 @@ int cadence_codec_init(struct comp_dev *dev) if (ret != LIB_NO_ERROR) { comp_err(dev, "cadence_codec_init() error %x: failed to get lib name", ret); - codec_free_memory(dev, cd); + comp_devm_free(dev); goto out; } /* Get codec object size */ @@ -130,14 +130,14 @@ int cadence_codec_init(struct comp_dev *dev) if (ret != LIB_NO_ERROR) { comp_err(dev, "cadence_codec_init() error %x: failed to get lib object size", ret); - codec_free_memory(dev, cd); + comp_devm_free(dev); goto out; } /* Allocate space for codec object */ - cd->self = codec_allocate_memory(dev, obj_size, 0); + cd->self = comp_devm_alloc(dev, obj_size, 0); if (!cd->self) { comp_err(dev, "cadence_codec_init(): failed to allocate space for lib object"); - codec_free_memory(dev, cd); + comp_devm_free(dev); goto out; } else { comp_dbg(dev, "cadence_codec_init(): allocated %d bytes for lib object", @@ -254,7 +254,7 @@ static int init_memory_tables(struct comp_dev *dev) goto err; } /* Allocate memory for this type, taking alignment into account */ - ptr = codec_allocate_memory(dev, mem_size, mem_alignment); + ptr = comp_devm_alloc(dev, mem_size, mem_alignment); if (!ptr) { comp_err(dev, "init_memory_tables() error %x: failed to allocate memory for %d", ret, mem_type); @@ -297,14 +297,7 @@ static int init_memory_tables(struct comp_dev *dev) return 0; err: - if (scratch) - codec_free_memory(dev, scratch); - if (persistent) - codec_free_memory(dev, persistent); - if (codec->cpd.in_buff) - codec_free_memory(dev, codec->cpd.in_buff); - if (codec->cpd.out_buff) - codec_free_memory(dev, codec->cpd.out_buff); + comp_devm_free(dev); return ret; } @@ -413,7 +406,7 @@ int cadence_codec_prepare(struct comp_dev *dev) goto err; } - cd->mem_tabs = codec_allocate_memory(dev, mem_tabs_size, 4); + cd->mem_tabs = comp_devm_alloc(dev, mem_tabs_size, 4); if (!cd->mem_tabs) { comp_err(dev, "cadence_codec_prepare() error: failed to allocate space for memtabs"); ret = -ENOMEM; diff --git a/src/audio/codec_adapter/codec/generic.c b/src/audio/codec_adapter/codec/generic.c index 0e480de04dcf..5419161f63c0 100644 --- a/src/audio/codec_adapter/codec/generic.c +++ b/src/audio/codec_adapter/codec/generic.c @@ -124,70 +124,7 @@ int codec_init(struct comp_dev *dev, struct codec_interface *interface) return ret; } -void *codec_allocate_memory(struct comp_dev *dev, uint32_t size, - uint32_t alignment) -{ - struct codec_memory *container; - void *ptr; - struct comp_data *cd = comp_get_drvdata(dev); - - if (!size) { - comp_err(dev, "codec_allocate_memory: requested allocation of 0 bytes."); - return NULL; - } - - /* Allocate memory container */ - container = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - sizeof(struct codec_memory)); - if (!container) { - comp_err(dev, "codec_allocate_memory: failed to allocate memory container."); - return NULL; - } - - /* Allocate memory for codec */ - if (alignment) - ptr = rballoc_align(0, SOF_MEM_CAPS_RAM, size, alignment); - else - ptr = rballoc(0, SOF_MEM_CAPS_RAM, size); - if (!ptr) { - comp_err(dev, "codec_allocate_memory: failed to allocate memory for codec %x.", - cd->ca_config.codec_id); - return NULL; - } - /* Store reference to allocated memory */ - container->ptr = ptr; - list_item_prepend(&container->mem_list, &cd->codec.memory.mem_list); - - return ptr; -} - -int codec_free_memory(struct comp_dev *dev, void *ptr) -{ - struct comp_data *cd = comp_get_drvdata(dev); - struct codec_memory *mem; - struct list_item *mem_list; - struct list_item *_mem_list; - - if (!ptr) - return 0; - - /* Find which container keeps this memory */ - list_for_item_safe(mem_list, _mem_list, &cd->codec.memory.mem_list) { - mem = container_of(mem_list, struct codec_memory, mem_list); - if (mem->ptr == ptr) { - rfree(mem->ptr); - list_item_del(&mem->mem_list); - rfree(mem); - return 0; - } - } - - comp_err(dev, "codec_free_memory: error: could not find memory pointed by %p", - (uint32_t)ptr); - - return -EINVAL; -} static int validate_config(struct codec_config *cfg) { @@ -349,22 +286,6 @@ int codec_reset(struct comp_dev *dev) return 0; } -void codec_free_all_memory(struct comp_dev *dev) -{ - struct comp_data *cd = comp_get_drvdata(dev); - struct codec_memory *mem; - struct list_item *mem_list; - struct list_item *_mem_list; - - /* Find which container keeps this memory */ - list_for_item_safe(mem_list, _mem_list, &cd->codec.memory.mem_list) { - mem = container_of(mem_list, struct codec_memory, mem_list); - rfree(mem->ptr); - list_item_del(&mem->mem_list); - rfree(mem); - } -} - int codec_free(struct comp_dev *dev) { int ret; @@ -377,7 +298,7 @@ int codec_free(struct comp_dev *dev) ret, cd->ca_config.codec_id); } /* Free all memory requested by codec */ - codec_free_all_memory(dev); + comp_devm_free(dev); /* Free all memory shared by codec_adapter & codec */ codec->s_cfg.avail = false; codec->s_cfg.size = 0; diff --git a/src/audio/codec_adapter/codec/waves.c b/src/audio/codec_adapter/codec/waves.c index d61f7c7c73d4..c7952259f689 100644 --- a/src/audio/codec_adapter/codec/waves.c +++ b/src/audio/codec_adapter/codec/waves.c @@ -199,7 +199,7 @@ static int waves_effect_allocate(struct comp_dev *dev) return -EINVAL; } - waves_codec->effect = (MaxxEffect_t *)codec_allocate_memory(dev, + waves_codec->effect = (MaxxEffect_t *)comp_devm_alloc(dev, waves_codec->effect_size, 16); if (!waves_codec->effect) { @@ -375,7 +375,7 @@ static int waves_effect_buffers(struct comp_dev *dev) goto err; } - response = codec_allocate_memory(dev, waves_codec->response_max_bytes, 16); + response = comp_devm_alloc(dev, waves_codec->response_max_bytes, 16); if (!response) { comp_err(dev, "waves_effect_buffers() failed to allocate %d bytes for response", waves_codec->response_max_bytes); @@ -383,7 +383,7 @@ static int waves_effect_buffers(struct comp_dev *dev) goto err; } - i_buffer = codec_allocate_memory(dev, waves_codec->buffer_bytes, 16); + i_buffer = comp_devm_alloc(dev, waves_codec->buffer_bytes, 16); if (!i_buffer) { comp_err(dev, "waves_effect_buffers() failed to allocate %d bytes for i_buffer", waves_codec->buffer_bytes); @@ -391,7 +391,7 @@ static int waves_effect_buffers(struct comp_dev *dev) goto err; } - o_buffer = codec_allocate_memory(dev, waves_codec->buffer_bytes, 16); + o_buffer = comp_devm_alloc(dev, waves_codec->buffer_bytes, 16); if (!o_buffer) { comp_err(dev, "waves_effect_buffers() failed to allocate %d bytes for o_buffer", waves_codec->buffer_bytes); @@ -415,12 +415,7 @@ static int waves_effect_buffers(struct comp_dev *dev) return 0; err: - if (i_buffer) - codec_free_memory(dev, i_buffer); - if (o_buffer) - codec_free_memory(dev, o_buffer); - if (response) - codec_free_memory(dev, response); + comp_devm_free(dev); return ret; } @@ -606,7 +601,7 @@ int waves_codec_init(struct comp_dev *dev) comp_dbg(dev, "waves_codec_init() start"); - waves_codec = codec_allocate_memory(dev, sizeof(struct waves_codec_data), 16); + waves_codec = comp_devm_alloc(dev, sizeof(struct waves_codec_data), 16); if (!waves_codec) { comp_err(dev, "waves_codec_init() failed to allocate %d bytes for waves_codec_data", sizeof(struct waves_codec_data)); @@ -756,7 +751,7 @@ int waves_codec_reset(struct comp_dev *dev) int waves_codec_free(struct comp_dev *dev) { - /* codec is using codec_adapter method codec_allocate_memory for all allocations + /* codec is using codec_adapter method comp_devm_alloc for all allocations * codec_adapter will free it all on component free call * nothing to do here */ diff --git a/src/audio/component.c b/src/audio/component.c index 9406ec69cfda..7aa9108d72a1 100644 --- a/src/audio/component.c +++ b/src/audio/component.c @@ -455,3 +455,57 @@ struct comp_dev *comp_make_shared(struct comp_dev *dev) return dev; } + +void *comp_devm_alloc(struct comp_dev *dev, uint32_t size, + uint32_t alignment) +{ + struct comp_dev_mem *container; + void *ptr; + + if (!size) { + comp_err(dev, "comp_devm_alloc: requested allocation of 0 bytes."); + return NULL; + } + + /* Allocate memory container */ + container = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, + sizeof(struct comp_dev_mem)); + if (!container) { + comp_err(dev, "comp_devm_alloc: failed to allocate memory container."); + return NULL; + } + + /* Allocate memory for codec */ + if (alignment) + ptr = rballoc_align(0, SOF_MEM_CAPS_RAM, size, alignment); + else + ptr = rballoc(0, SOF_MEM_CAPS_RAM, size); + + if (!ptr) { + comp_err(dev, "comp_devm_alloc: failed to allocate memory for comp_dev\n"); + return NULL; + } + + /* Store reference to allocated memory */ + container->ptr = ptr; + list_item_prepend(&container->mem_list, &dev->mem.mem_list); + + return ptr; +} + +int comp_devm_free(struct comp_dev *dev) +{ + struct comp_dev_mem *mem; + struct list_item *mem_list; + struct list_item *_mem_list; + + /* Find which container keeps this memory */ + list_for_item_safe(mem_list, _mem_list, &dev->mem.mem_list) { + mem = container_of(mem_list, struct comp_dev_mem, mem_list); + rfree(mem->ptr); + list_item_del(&mem->mem_list); + rfree(mem); + } + + return 0; +} diff --git a/src/include/sof/audio/codec_adapter/codec/generic.h b/src/include/sof/audio/codec_adapter/codec/generic.h index f77eae6f3b0e..6e6dc64efb3f 100644 --- a/src/include/sof/audio/codec_adapter/codec/generic.h +++ b/src/include/sof/audio/codec_adapter/codec/generic.h @@ -193,15 +193,6 @@ struct codec_config { void *data; /**< tlv config, a pointer to memory where config is stored. */ }; -/** - * \struct codec_memory - * \brief codec memory block - used for every memory allocated by codec - */ -struct codec_memory { - void *ptr; /**< A pointr to particular memory block */ - struct list_item mem_list; /**< list of memory allocated by codec */ -}; - /** * \struct codec_processing_data * \brief Processing data shared between particular codec & codec_adapter @@ -226,7 +217,6 @@ struct codec_data { struct codec_config s_cfg; /**< setup config */ struct codec_config r_cfg; /**< runtime config */ struct codec_interface *ops; /**< codec specific operations */ - struct codec_memory memory; /**< memory allocated by codec */ struct codec_processing_data cpd; /**< shared data comp <-> codec */ }; @@ -249,10 +239,6 @@ struct comp_data { int codec_load_config(struct comp_dev *dev, void *cfg, size_t size, enum codec_cfg_type type); int codec_init(struct comp_dev *dev, struct codec_interface *interface); -void *codec_allocate_memory(struct comp_dev *dev, uint32_t size, - uint32_t alignment); -int codec_free_memory(struct comp_dev *dev, void *ptr); -void codec_free_all_memory(struct comp_dev *dev); int codec_prepare(struct comp_dev *dev); int codec_get_samples(struct comp_dev *dev); int codec_init_process(struct comp_dev *dev); diff --git a/src/include/sof/audio/component.h b/src/include/sof/audio/component.h index 77874a0dbcdf..1c4d04b5471a 100644 --- a/src/include/sof/audio/component.h +++ b/src/include/sof/audio/component.h @@ -425,6 +425,15 @@ struct comp_driver_info { struct list_item list; /**< list of component drivers */ }; +/** + * \struct comp dev memory - used like devm_kzalloc + * \brief comp dev memory block - used for every memory allocated by comp + */ +struct comp_dev_mem { + void *ptr; /**< A pointr to particular memory block */ + struct list_item mem_list; /**< list of memory allocated by codec */ +}; + /** * Audio component base device "class" * - used by other component types. @@ -474,6 +483,8 @@ struct comp_dev { struct perf_cnt_data pcd; #endif + struct comp_dev_mem mem; + /** * IPC config object header - MUST be at end as it's * variable size/type