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 */
7
8 #ifndef __SOF_AUDIO_PIPELINE_H__
9 #define __SOF_AUDIO_PIPELINE_H__
10
11 #include <sof/lib/cpu.h>
12 #include <sof/lib/mailbox.h>
13 #include <sof/lib/memory.h>
14 #include <sof/list.h>
15 #include <rtos/task.h>
16 #include <rtos/sof.h>
17 #include <rtos/spinlock.h>
18 #include <sof/audio/pipeline-trace.h>
19 #include <ipc/topology.h>
20 #include <user/trace.h>
21 #include <errno.h>
22 #include <stdbool.h>
23 #include <stdint.h>
24
25 struct comp_buffer;
26 struct comp_dev;
27 struct ipc;
28 struct ipc_msg;
29
30 /*
31 * Pipeline status to stop execution of current path, but to keep the
32 * pipeline alive, when processing COMP_TRIGGER_STOP or COMP_TRIGGER_PAUSE
33 */
34 #define PPL_STATUS_PATH_STOP 1
35 /*
36 * Pipeline status to stop execution of current path, and to terminate the
37 * pipeline, when processing COMP_TRIGGER_STOP or COMP_TRIGGER_PAUSE
38 */
39 #define PPL_STATUS_PATH_TERMINATE 2
40
41 /* Pipeline scheduled in another thread other than ipc thread */
42 #define PPL_STATUS_SCHEDULED 2
43
44 /* pipeline connection directions */
45 #define PPL_CONN_DIR_COMP_TO_BUFFER 0
46 #define PPL_CONN_DIR_BUFFER_TO_COMP 1
47
48 /* pipeline processing directions */
49 #define PPL_DIR_DOWNSTREAM 0
50 #define PPL_DIR_UPSTREAM 1
51
52 /*
53 * Audio pipeline.
54 */
55 struct pipeline {
56 uint32_t comp_id; /**< component id for pipeline */
57 uint32_t pipeline_id; /**< pipeline id */
58 uint32_t sched_id; /**< Scheduling component id */
59 uint32_t core; /**< core we run on */
60 uint32_t period; /**< execution period in us*/
61 uint32_t priority; /**< priority level 0 (low) to 10 (max) */
62 uint32_t period_mips; /**< worst case instruction count per period */
63 uint32_t frames_per_sched;/**< output frames of pipeline, 0 is variable */
64 uint32_t xrun_limit_usecs; /**< report xruns greater than limit */
65 uint32_t time_domain; /**< scheduling time domain */
66 uint32_t attributes; /**< pipeline attributes from IPC extension msg/ */
67
68 /* runtime status */
69 int32_t xrun_bytes; /* last xrun length */
70 uint32_t status; /* pipeline status */
71 struct tr_ctx tctx; /* trace settings */
72
73 /* scheduling */
74 struct task *pipe_task; /* pipeline processing task */
75 struct pipeline *sched_next; /* pipeline scheduled after this */
76 struct pipeline *sched_prev; /* pipeline scheduled before this */
77
78 /* component that drives scheduling in this pipe */
79 struct comp_dev *sched_comp;
80 /* source component for this pipe */
81 struct comp_dev *source_comp;
82 /* sink component for this pipe */
83 struct comp_dev *sink_comp;
84
85 struct list_item list; /**< list in walk context */
86
87 /* position update */
88 uint32_t posn_offset; /* position update array offset*/
89 struct ipc_msg *msg;
90 struct {
91 int cmd;
92 struct comp_dev *host;
93 unsigned int delay; /* period count */
94 bool aborted; /* STOP or PAUSE failed, stay active */
95 bool pending; /* trigger scheduled but not executed yet */
96 } trigger;
97 };
98
99 struct pipeline_walk_context {
100 int (*comp_func)(struct comp_dev *cd, struct comp_buffer *buffer,
101 struct pipeline_walk_context *ctx, int dir);
102 void *comp_data;
103 void (*buff_func)(struct comp_buffer __sparse_cache *buffer, void *data);
104 void *buff_data;
105 struct comp_buffer *incoming;
106 /**< pipelines to be scheduled after trigger walk */
107 struct list_item pipelines;
108 /*
109 * If this flag is set, pipeline_for_each_comp() will skip all
110 * incompletely initialised components, i.e. those, whose .pipeline ==
111 * NULL. Such components should not be skipped during initialisation
112 * and clean up, but they should be skipped during streaming.
113 */
114 bool skip_incomplete;
115 };
116
117 /* generic pipeline data used by pipeline_comp_* functions */
118 struct pipeline_data {
119 struct comp_dev *start;
120 struct sof_ipc_pcm_params *params;
121 struct sof_ipc_stream_posn *posn;
122 struct pipeline *p;
123 int cmd;
124 uint32_t delay_ms; /* between PRE_{START,RELEASE} and {START,RELEASE} */
125 };
126
127 /** \brief Task type registered by pipelines. */
128 struct pipeline_task {
129 struct task task; /**< parent structure */
130 bool registrable; /**< should task be registered on irq */
131 struct comp_dev *sched_comp; /**< pipeline scheduling component */
132 };
133
134 #define pipeline_task_get(t) container_of(t, struct pipeline_task, task)
135
136 /*
137 * Pipeline Graph APIs
138 *
139 * These APIs are used to construct and bind pipeline graphs. They are also
140 * used to query pipeline fundamental configuration.
141 */
142
143 /**
144 * \brief Creates a new pipeline.
145 * \param[in] pipeline_id Pipeline ID number.
146 * \param[in] priority Pipeline scheduling priority.
147 * \param[in] comp_id Pipeline component ID number.
148 * \return New pipeline pointer or NULL.
149 */
150 struct pipeline *pipeline_new(uint32_t pipeline_id, uint32_t priority, uint32_t comp_id);
151
152 /**
153 * \brief Free's a pipeline.
154 * \param[in] p pipeline.
155 * \return 0 on success.
156 */
157 int pipeline_free(struct pipeline *p);
158
159 /**
160 * \brief Connect components in a pipeline.
161 * \param[in] comp connecting component.
162 * \param[in] buffer connecting buffer.
163 * \param[in] dir Connection direction.
164 * \return 0 on success.
165 */
166 int pipeline_connect(struct comp_dev *comp, struct comp_buffer *buffer,
167 int dir);
168
169 /**
170 * \brief Creates a new pipeline.
171 * \param[in] comp connecting component.
172 * \param[in] buffer connecting buffer.
173 * \param[in] dir Connection direction.
174 */
175 void pipeline_disconnect(struct comp_dev *comp, struct comp_buffer *buffer,
176 int dir);
177
178 /**
179 * \brief Completes a pipeline.
180 * \param[in] p pipeline.
181 * \param[in] source Pipeline component device.
182 * \param[in] sink Pipeline component device.
183 * \return 0 on success.
184 */
185 int pipeline_complete(struct pipeline *p, struct comp_dev *source,
186 struct comp_dev *sink);
187
188 /**
189 * \brief Initializes pipeline position structure.
190 * \param[in,out] sof Pointer to sof structure.
191 */
192 void pipeline_posn_init(struct sof *sof);
193
194 /**
195 * \brief Resets the pipeline and free runtime resources.
196 * \param[in] p pipeline.
197 * \param[in] host_cd Host DMA component device.
198 * \return 0 on success.
199 */
200 int pipeline_reset(struct pipeline *p, struct comp_dev *host_cd);
201
202 /**
203 * \brief Walks the pipeline graph for each component.
204 * \param[in] current Current pipeline component.
205 * \param[in] ctx Pipeline graph walk context.
206 * \param[in] dir Walk direction.
207 * \return 0 on success.
208 */
209 int pipeline_for_each_comp(struct comp_dev *current,
210 struct pipeline_walk_context *ctx, int dir);
211
212 /**
213 * \brief Walks pipeline graph to find dai component.
214 * \param[in] pipeline_id is the start pipeline id.
215 * \param[in] dir is the direction of the traversal.
216 * \return dai component.
217 */
218 struct comp_dev *pipeline_get_dai_comp(uint32_t pipeline_id, int dir);
219
220 #if CONFIG_IPC_MAJOR_4
221 /**
222 * \brief Walks pipeline graph to find dai component and latency.
223 * \param[in] pipeline_id is the start pipeline id.
224 * \param[out] latency to dai.
225 * \return dai component.
226 */
227 struct comp_dev *pipeline_get_dai_comp_latency(uint32_t pipeline_id, uint32_t *latency);
228 #endif
229
230 /**
231 * Retrieves pipeline id from pipeline.
232 * @param p pipeline.
233 * @return pipeline id.
234 */
pipeline_id(struct pipeline * p)235 static inline uint32_t pipeline_id(struct pipeline *p)
236 {
237 return p->pipeline_id;
238 }
239
240 /*
241 * Pipeline configuration APIs
242 *
243 * These APIs are used to configure the runtime parameters of a pipeline.
244 */
245
246 /**
247 * \brief Creates a new pipeline.
248 * \param[in] p pipeline.
249 * \param[in] cd Pipeline component device.
250 * \param[in] params Pipeline parameters.
251 * \return 0 on success.
252 */
253 int pipeline_params(struct pipeline *p, struct comp_dev *cd,
254 struct sof_ipc_pcm_params *params);
255
256 /**
257 * \brief Creates a new pipeline.
258 * \param[in] p pipeline.
259 * \param[in,out] cd Pipeline component device.
260 * \return 0 on success.
261 */
262 int pipeline_prepare(struct pipeline *p, struct comp_dev *cd);
263
264 /*
265 * Pipeline stream APIs
266 *
267 * These APIs are used to control pipeline processing work.
268 */
269
270 /**
271 * \brief Trigger pipeline - IPC context
272 * \param[in] p pipeline.
273 * \param[in] host Host DMA component.
274 * \param[in] cmd Pipeline trigger command.
275 * \return 0 on success.
276 */
277 int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd);
278
279 /**
280 * \brief Trigger pipeline - either IPC or pipeline task context
281 * \param[in] p pipeline.
282 * \param[in] host Host DMA component.
283 * \param[in] cmd Pipeline trigger command.
284 * \return 0 on success.
285 */
286 int pipeline_trigger_run(struct pipeline *p, struct comp_dev *host, int cmd);
287
288 /**
289 * \brief Copy data along a pipeline.
290 * \param[in] p pipeline.
291 * \return 0 on success.
292 */
293 int pipeline_copy(struct pipeline *p);
294
295 /**
296 * \brief Get time pipeline timestamps from host to dai.
297 * \param[in] p pipeline.
298 * \param[in] host_dev Host DMA component.
299 * \param[in,out] posn Pipeline stream position.
300 */
301 void pipeline_get_timestamp(struct pipeline *p, struct comp_dev *host_dev,
302 struct sof_ipc_stream_posn *posn);
303
304 /*
305 * Pipeline scheduling APIs
306 *
307 * These APIs are used to schedule pipeline processing work.
308 */
309
310 /**
311 * \brief Checks if two pipelines have the same scheduling component.
312 * \param[in] current This pipeline.
313 * \param[in] previous Other pipeline.
314 * \return true if both pipelines are scheduled together.
315 */
pipeline_is_same_sched_comp(struct pipeline * current,struct pipeline * previous)316 static inline bool pipeline_is_same_sched_comp(struct pipeline *current,
317 struct pipeline *previous)
318 {
319 return current->sched_comp == previous->sched_comp;
320 }
321
322 /**
323 * \brief Is pipeline is scheduled with timer.
324 * \param[in] p pipeline.
325 * \return true if pipeline uses timer based scheduling.
326 */
pipeline_is_timer_driven(struct pipeline * p)327 static inline bool pipeline_is_timer_driven(struct pipeline *p)
328 {
329 return p->time_domain == SOF_TIME_DOMAIN_TIMER;
330 }
331
332 /**
333 * \brief Is pipeline is scheduled on this core.
334 * \param[in] p pipeline.
335 * \return true if pipeline core ID == current core ID.
336 */
pipeline_is_this_cpu(struct pipeline * p)337 static inline bool pipeline_is_this_cpu(struct pipeline *p)
338 {
339 return p->core == cpu_get_id();
340 }
341
342 /**
343 * \brief Init an LL task for a pipeline.
344 * \param[in] p pipeline.
345 * \return 0 on success.
346 */
347 int pipeline_comp_ll_task_init(struct pipeline *p);
348
349 /**
350 * \brief Init a DP task for a component
351 * \param[in] comp a component the task is created for
352 * \return 0 on success.
353 */
354 int pipeline_comp_dp_task_init(struct comp_dev *comp);
355
356 /**
357 * \brief Free's a pipeline.
358 * \param[in] p pipeline.
359 * \param[in] start Pipelien start time in microseconds.
360 */
361 void pipeline_schedule_copy(struct pipeline *p, uint64_t start);
362
363 /**
364 * \brief Trigger pipeline's scheduling component.
365 * \param[in] p pipeline.
366 * \param[in,out] comp Pipeline component device.
367 * \param[in] ctx Pipeline graph walk context.
368 */
369 void pipeline_comp_trigger_sched_comp(struct pipeline *p,
370 struct comp_dev *comp,
371 struct pipeline_walk_context *ctx);
372
373 /**
374 * \brief Schedule all triggered pipelines.
375 * \param[in] ctx Pipeline graph walk context.
376 * \param[in] cmd Trigger command.
377 */
378 void pipeline_schedule_triggered(struct pipeline_walk_context *ctx,
379 int cmd);
380
381 /**
382 * \brief Configure pipeline scheduling.
383 * \param[in] p pipeline.
384 * \param[in] sched_id Scheduling component ID.
385 * \param[in] core DSP core pipeline runs on.
386 * \param[in] period Pipeline scheduling period in us.
387 * \param[in] period_mips Pipeline worst case MCPS per period.
388 * \param[in] frames_per_sched Pipeline frames processed per schedule.
389 * \param[in] time_domain Pipeline scheduling time domain.
390 */
391 void pipeline_schedule_config(struct pipeline *p, uint32_t sched_id,
392 uint32_t core, uint32_t period,
393 uint32_t period_mips, uint32_t frames_per_sched,
394 uint32_t time_domain);
395
396 /*
397 * Pipeline error handling APIs
398 *
399 * These APIs are used to handle, report and recover from pipeline errors.
400 */
401
402 /**
403 * \brief Recover the pipeline from a XRUN condition.
404 * \param[in] p pipeline.
405 * \return 0 on success.
406 */
407 int pipeline_xrun_recover(struct pipeline *p);
408
409 /**
410 * \brief Perform xrun recovery.
411 * \param[in] p pipeline.
412 * \param[in] cmd Trigger command.
413 * \return 0 on success.
414 */
415 int pipeline_xrun_handle_trigger(struct pipeline *p, int cmd);
416
417 /**
418 * \brief notify host that we have XRUN.
419 * \param[in] p pipeline.
420 * \param[in] dev Pipeline component device.
421 * \param[in] bytes Number of bytes we have over or under run.
422 */
423 void pipeline_xrun(struct pipeline *p, struct comp_dev *dev, int32_t bytes);
424
425 /**
426 * \brief Set tolerance for pipeline xrun handling.
427 * \param[in] p pipeline.
428 * \param[in] xrun_limit_usecs Limit in micro secs that pipeline will tolerate.
429 */
430 int pipeline_xrun_set_limit(struct pipeline *p, uint32_t xrun_limit_usecs);
431
432 #endif /* __SOF_AUDIO_PIPELINE_H__ */
433