1 /* SPDX-License-Identifier: BSD-3-Clause
2 *
3 * Copyright(c) 2016 Intel Corporation. All rights reserved.
4 *
5 * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
6 * Keyon Jie <yang.jie@linux.intel.com>
7 */
8
9 #ifndef __SOF_IPC_COMMON_H__
10 #define __SOF_IPC_COMMON_H__
11
12 #include <sof/lib/alloc.h>
13 #include <sof/list.h>
14 #include <sof/schedule/task.h>
15 #include <sof/sof.h>
16 #include <user/trace.h>
17 #include <stdbool.h>
18 #include <stdint.h>
19
20 struct dma_sg_elem_array;
21 struct ipc_msg;
22
23 /* generic IPC header regardless of ABI MAJOR type that is always 4 byte aligned */
24 typedef uint32_t ipc_cmd_hdr;
25
26 /*
27 * Common IPC logic uses standard types for abstract IPC features. This means all ABI MAJOR
28 * abstraction is done in the IPC layer only and not in the surrounding infrastructure.
29 */
30 #if CONFIG_IPC_MAJOR_3
31 #include <ipc/header.h>
32 #define ipc_from_hdr(x) ((struct sof_ipc_cmd_hdr *)x)
33 #elif CONFIG_IPC_MAJOR_4
34 #include <ipc4/header.h>
35 #define ipc_from_hdr(x) ((union ipc4_message_header *)x)
36 #else
37 #error "No or invalid IPC MAJOR version selected."
38 #endif
39
40 #define ipc_to_hdr(x) ((ipc_cmd_hdr *)x)
41
42 /* validates internal non tail structures within IPC command structure */
43 #define IPC_IS_SIZE_INVALID(object) \
44 (object).hdr.size == sizeof(object) ? 0 : 1
45
46 /* ipc trace context, used by multiple units */
47 extern struct tr_ctx ipc_tr;
48
49 /* convenience error trace for mismatched internal structures */
50 #define IPC_SIZE_ERROR_TRACE(ctx, object) \
51 tr_err(ctx, "ipc: size %d expected %d", \
52 (object).hdr.size, sizeof(object))
53
54 /* Returns pipeline source component */
55 #define ipc_get_ppl_src_comp(ipc, ppl_id) \
56 ipc_get_ppl_comp(ipc, ppl_id, PPL_DIR_UPSTREAM)
57
58 /* Returns pipeline sink component */
59 #define ipc_get_ppl_sink_comp(ipc, ppl_id) \
60 ipc_get_ppl_comp(ipc, ppl_id, PPL_DIR_DOWNSTREAM)
61
62 struct ipc {
63 spinlock_t lock; /* locking mechanism */
64 void *comp_data;
65
66 /* PM */
67 int pm_prepare_D3; /* do we need to prepare for D3 */
68
69 struct list_item msg_list; /* queue of messages to be sent */
70 bool is_notification_pending; /* notification is being sent to host */
71 unsigned int core; /* core, processing the IPC */
72
73 struct list_item comp_list; /* list of component devices */
74
75 /* processing task */
76 struct task ipc_task;
77
78 void *private;
79 };
80
81 #define ipc_set_drvdata(ipc, data) \
82 ((ipc)->private = data)
83 #define ipc_get_drvdata(ipc) \
84 ((ipc)->private)
85
86 extern struct task_ops ipc_task_ops;
87
88 /**
89 * \brief Get the IPC global context.
90 * @return The global IPC context.
91 */
ipc_get(void)92 static inline struct ipc *ipc_get(void)
93 {
94 return sof_get()->ipc;
95 }
96
97 /**
98 * \brief Initialise global IPC context.
99 * @param[in,out] sof Global SOF context.
100 * @return 0 on success.
101 */
102 int ipc_init(struct sof *sof);
103
104 /**
105 * \brief Free global IPC context.
106 * @param[in] ipc Global IPC context.
107 */
108 void ipc_free(struct ipc *ipc);
109
110 /**
111 * \brief Data provided by the platform which use ipc...page_descriptors().
112 *
113 * Note: this should be made private for ipc-host-ptable.c and ipc
114 * drivers for platforms that use ptables.
115 */
116 struct ipc_data_host_buffer {
117 /* DMA */
118 struct dma *dmac;
119 uint8_t *page_table;
120 };
121
122 /**
123 * \brief Processes page tables for the host buffer.
124 * @param[in] ipc Ipc
125 * @param[in] ring Ring description sent via Ipc
126 * @param[in] direction Direction (playback/capture)
127 * @param[out] elem_array Array of SG elements
128 * @param[out] ring_size Size of the ring
129 * @return Status, 0 if successful, error code otherwise.
130 */
131 int ipc_process_host_buffer(struct ipc *ipc,
132 struct sof_ipc_host_buffer *ring,
133 uint32_t direction,
134 struct dma_sg_elem_array *elem_array,
135 uint32_t *ring_size);
136
137 /**
138 * \brief Send DMA trace host buffer position to host.
139 * @return 0 on success.
140 */
141 int ipc_dma_trace_send_position(void);
142
143 /**
144 * \brief Configure DAI.
145 * @return 0 on success.
146 */
147 int ipc_dai_data_config(struct comp_dev *dev);
148
149 /**
150 * \brief create a IPC boot complete message.
151 * @param[in] header header.
152 * @param[in] data data.
153 */
154 void ipc_boot_complete_msg(ipc_cmd_hdr *header, uint32_t *data);
155
156 /**
157 * \brief Read a compact IPC message or return NULL for normal message.
158 * @return Pointer to the compact message data.
159 */
160 ipc_cmd_hdr *ipc_compact_read_msg(void);
161
162 /**
163 * \brief Write a compact IPC message.
164 * @param[in] hdr Compact message header data.
165 * @return Number of words written.
166 */
167 int ipc_compact_write_msg(ipc_cmd_hdr *hdr);
168
169 /**
170 * \brief Prepare an IPC message for sending.
171 * @param[in] msg The ipc msg.
172 * @return pointer to raw header or NULL.
173 */
174 ipc_cmd_hdr *ipc_prepare_to_send(struct ipc_msg *msg);
175
176 /**
177 * \brief Validate mailbox contents for valid IPC header.
178 * @return pointer to header if valid or NULL.
179 */
180 ipc_cmd_hdr *mailbox_validate(void);
181
182 /**
183 * Generic IPC command handler. Expects that IPC command (the header plus
184 * any optional payload) is deserialized from the IPC HW by the platform
185 * specific method.
186 *
187 * @param hdr Points to the IPC command header.
188 */
189 void ipc_cmd(ipc_cmd_hdr *hdr);
190
191 /**
192 * \brief IPC message to be processed on other core.
193 * @param[in] core Core id for IPC to be processed on.
194 * @param[in] blocking Process in blocking mode: wait for completion.
195 * @return 1 if successful (reply sent by other core), error code otherwise.
196 */
197 int ipc_process_on_core(uint32_t core, bool blocking);
198
199 #endif /* __SOF_DRIVERS_IPC_H__ */
200