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