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 /**
10   * \file include/sof/lib/dai.h
11   * \brief DAI Drivers definition
12   * \author Liam Girdwood <liam.r.girdwood@linux.intel.com>
13   * \author Keyon Jie <yang.jie@linux.intel.com>
14   */
15 
16 #ifndef __SOF_LIB_DAI_H__
17 #define __SOF_LIB_DAI_H__
18 
19 #include <platform/lib/dai.h>
20 #include <sof/bit.h>
21 #include <sof/list.h>
22 #include <sof/lib/io.h>
23 #include <sof/lib/memory.h>
24 #include <sof/lib/dma.h>
25 #include <sof/list.h>
26 #include <sof/sof.h>
27 #include <sof/spinlock.h>
28 #include <sof/trace/trace.h>
29 #include <sof/ipc/topology.h>
30 #include <sof/audio/pcm_converter.h>
31 #include <sof/audio/ipc-config.h>
32 #include <errno.h>
33 #include <stddef.h>
34 #include <stdint.h>
35 
36 struct dai;
37 struct sof_ipc_stream_params;
38 
39 /** \addtogroup sof_dai_drivers DAI Drivers
40  *  DAI Drivers API specification.
41  *  @{
42  */
43 
44 #define DAI_CLOCK_IN		0
45 #define DAI_CLOCK_OUT		1
46 
47 #define DAI_DIR_PLAYBACK	0
48 #define DAI_DIR_CAPTURE		1
49 
50 #define DAI_NUM_SLOT_MAPS	8
51 
52 #define DAI_INFO_TYPE		0
53 #define DAI_INFO_DMA_CAPS	1
54 #define DAI_INFO_DMA_DEV	2
55 
56 /* DAI flags */
57 
58 /** \brief IRQ used for copy() timer */
59 #define DAI_FLAGS_IRQ_CB	BIT(0)
60 
61 /* DAI get() flags */
62 
63 /** \brief If the device does not exist it will be created */
64 #define DAI_CREAT		BIT(0)
65 
66 /**
67  * \brief DAI operations - all optional
68  *
69  * DAI drivers may allocate private data,
70  * which can be set with 'dai_set_drvdata' and retrieved with 'dai_get_drvdata'.
71  * If a single DAI instance can have multiple DMA links and/or there is
72  * some other possibility of the same instance being used in multiple
73  * contexts at the same time, the private data should be allocated in the
74  * SOF_MEM_ZONE_SHARED.
75  */
76 struct dai_ops {
77 	int (*set_config)(struct dai *dai, struct ipc_config_dai *config,
78 			  void *spec_config);
79 	int (*trigger)(struct dai *dai, int cmd, int direction);
80 	int (*pm_context_restore)(struct dai *dai);
81 	int (*pm_context_store)(struct dai *dai);
82 	int (*get_hw_params)(struct dai *dai,
83 			     struct sof_ipc_stream_params *params, int dir);
84 	int (*hw_params)(struct dai *dai, struct sof_ipc_stream_params *params);
85 	int (*get_handshake)(struct dai *dai, int direction, int stream_id);
86 	int (*get_fifo)(struct dai *dai, int direction, int stream_id);
87 	int (*probe)(struct dai *dai);
88 	int (*remove)(struct dai *dai);
89 };
90 
91 struct timestamp_cfg {
92 	uint32_t walclk_rate; /* Rate in Hz, e.g. 19200000 */
93 	int type; /* SSP, DMIC, HDA, etc. */
94 	int direction; /* Playback, capture */
95 	int index; /* For SSPx to select correct timestamp register */
96 	int dma_id; /* GPDMA id*/
97 	int dma_chan_index; /* Used GPDMA channel */
98 	int dma_chan_count; /* Channels in single GPDMA */
99 };
100 
101 struct timestamp_data {
102 	uint64_t walclk; /* Wall clock */
103 	uint64_t sample; /* Sample count */
104 	uint32_t walclk_rate; /* Rate in Hz, e.g. 19200000 */
105 };
106 
107 struct timestamp_ops {
108 	int (*ts_config)(struct dai *dai, struct timestamp_cfg *cfg);
109 	int (*ts_start)(struct dai *dai, struct timestamp_cfg *cfg);
110 	int (*ts_stop)(struct dai *dai, struct timestamp_cfg *cfg);
111 	int (*ts_get)(struct dai *dai, struct timestamp_cfg *cfg,
112 		      struct timestamp_data *tsd);
113 };
114 
115 struct dai_driver {
116 	uint32_t type;	/**< type, one of SOF_DAI_... */
117 	const struct sof_uuid_entry *uid;
118 	struct tr_ctx *tctx;
119 	uint32_t dma_caps;
120 	uint32_t dma_dev;
121 	struct dai_ops ops;
122 	struct timestamp_ops ts_ops;
123 };
124 
125 /**
126  * \brief DAI slot map to audio channel
127  */
128 struct dai_slot_map {
129 	uint32_t channel;	/**< channel ID - CHAN_ID_ */
130 	uint32_t slot;		/**< physical slot index */
131 };
132 
133 struct dai_plat_fifo_data {
134 	uint32_t offset;
135 	uint32_t width;
136 	uint32_t depth;
137 	uint32_t watermark;
138 	uint32_t handshake;
139 };
140 
141 /**
142  * \brief DAI platform data
143  */
144 struct dai_plat_data {
145 	uint32_t base;
146 	int irq;
147 	const char *irq_name;
148 	uint32_t flags;
149 	struct dai_plat_fifo_data fifo[2];
150 };
151 
152 /**
153  * \brief DAI runtime data
154  */
155 struct dai_data {
156 	/* local DMA config */
157 	struct dma_chan_data *chan;
158 	uint32_t stream_id;
159 	struct dma_sg_config config;
160 	struct comp_buffer *dma_buffer;
161 	struct comp_buffer *local_buffer;
162 	struct timestamp_cfg ts_config;
163 	struct dai *dai;
164 	struct dma *dma;
165 	struct dai_group *group;	/**< NULL if no group assigned */
166 	int xrun;		/* true if we are doing xrun recovery */
167 
168 	pcm_converter_func process;	/* processing function */
169 
170 	uint32_t dai_pos_blks;	/* position in bytes (nearest block) */
171 	uint64_t start_position;	/* position on start */
172 	uint32_t period_bytes;	/**< number of bytes per one period */
173 
174 	/* host can read back this value without IPC */
175 	uint64_t *dai_pos;
176 
177 	struct ipc_config_dai ipc_config;	/* generic common config */
178 	void *dai_spec_config;	/* dai specific config from the host */
179 
180 	uint64_t wallclock;	/* wall clock at stream start */
181 };
182 
183 struct dai {
184 	uint32_t index;		/**< index */
185 	spinlock_t lock;	/**< locking mechanism */
186 	int sref;		/**< simple ref counter, guarded by lock */
187 	struct dai_plat_data plat_data;
188 	const struct dai_driver *drv;
189 	void *priv_data;
190 };
191 
192 /**
193  * \brief Array of DAIs grouped by type.
194  */
195 struct dai_type_info {
196 	uint32_t type;		/**< Type */
197 	struct dai *dai_array;	/**< Array of DAIs */
198 	size_t num_dais;	/**< Number of elements in dai_array */
199 };
200 
201 /* dai tracing */
202 #define trace_dai_drv_get_tr_ctx(drv_p) ((drv_p)->tctx)
203 #define trace_dai_drv_get_id(drv_p) (-1)
204 #define trace_dai_drv_get_subid(drv_p) (-1)
205 
206 #define trace_dai_get_tr_ctx(dai_p) ((dai_p)->drv->tctx)
207 #define trace_dai_get_id(dai_p) ((dai_p)->drv->type)
208 #define trace_dai_get_subid(dai_p) ((dai_p)->index)
209 
210 /* class (driver) level (no device object) tracing */
211 
212 #define dai_cl_err(drv_p, __e, ...)		\
213 	trace_dev_err(trace_dai_dvr_get_tr_ctx,	\
214 		      trace_dai_drv_get_id,	\
215 		      trace_dai_drv_get_subid,	\
216 		      drv_p, __e, ##__VA_ARGS__)
217 
218 #define dai_cl_warn(drv_p, __e, ...)		\
219 	trace_dev_warn(trace_dai_drv_get_tr_ctx,\
220 		       trace_dai_drv_get_id,	\
221 		       trace_dai_drv_get_subid,	\
222 		       drv_p, __e, ##__VA_ARGS__)
223 
224 #define dai_cl_info(drv_p, __e, ...)		\
225 	trace_dev_info(trace_dai_drv_get_tr_ctx,\
226 		       trace_dai_drv_get_id,	\
227 		       trace_dai_drv_get_subid,	\
228 		       drv_p, __e, ##__VA_ARGS__)
229 
230 #define dai_cl_dbg(drv_p, __e, ...)		\
231 	trace_dev_dbg(trace_dai_drv_get_tr_ctx,	\
232 		      trace_dai_drv_get_id,	\
233 		      trace_dai_drv_get_subid,	\
234 		      drv_p, __e, ##__VA_ARGS__)
235 
236 /* device tracing */
237 
238 #define dai_err(dai_p, __e, ...)					\
239 	trace_dev_err(trace_dai_get_tr_ctx,				\
240 		      trace_dai_get_id,					\
241 		      trace_dai_get_subid, dai_p, __e, ##__VA_ARGS__)
242 
243 #define dai_warn(dai_p, __e, ...)					\
244 	trace_dev_warn(trace_dai_get_tr_ctx,				\
245 		       trace_dai_get_id,				\
246 		       trace_dai_get_subid, dai_p, __e, ##__VA_ARGS__)
247 
248 #define dai_info(dai_p, __e, ...)					\
249 	trace_dev_info(trace_dai_get_tr_ctx,				\
250 		       trace_dai_get_id,				\
251 		       trace_dai_get_subid, dai_p, __e, ##__VA_ARGS__)
252 
253 #define dai_dbg(dai_p, __e, ...)					\
254 	trace_dev_dbg(trace_dai_get_tr_ctx,				\
255 		      trace_dai_get_id,					\
256 		      trace_dai_get_subid, dai_p, __e, ##__VA_ARGS__)
257 
258 /**
259  * \brief API to request DAI group
260  *
261  * Returns a DAI group for the given ID and
262  * increments the counter of DAIs in the group.
263  *
264  * If a group for the given ID doesn't exist,
265  * it will either return NULL or allocate a new group structure
266  * if the CREATE flag is supplied.
267  *
268  * \param[in] group_id Group ID
269  * \param[in] flags Flags (CREATE)
270  */
271 struct dai_group *dai_group_get(uint32_t group_id, uint32_t flags);
272 
273 /**
274  * \brief API to release DAI group
275  *
276  * Decrements the DAI counter inside the group.
277  *
278  * \param[in] group Group
279  */
280 void dai_group_put(struct dai_group *group);
281 
282 /**
283  * \brief DAI group information
284  */
285 struct dai_group {
286 	/**
287 	 * Group ID
288 	 */
289 	uint32_t group_id;
290 
291 	/**
292 	 * Number of DAIs in this group
293 	 */
294 	uint32_t num_dais;
295 
296 	/**
297 	 * Number of DAIs to receive a trigger before processing begins
298 	 */
299 	uint32_t trigger_counter;
300 
301 	/**
302 	 * Trigger command to propagate
303 	 */
304 	int trigger_cmd;
305 
306 	/**
307 	 * Last trigger error
308 	 */
309 	int trigger_ret;
310 
311 	/**
312 	 * Group list
313 	 */
314 	struct list_item list;
315 };
316 
317 /**
318  * \brief Holds information about array of DAIs grouped by type.
319  */
320 struct dai_info {
321 	const struct dai_type_info *dai_type_array;
322 	size_t num_dai_types;
323 };
324 
325 /**
326  * \brief API to initialize a platform DAI.
327  *
328  * \param[in] sof Pointer to firmware main context.
329  */
330 int dai_init(struct sof *sof);
331 
332 /**
333  * \brief API to request a platform DAI.
334  *
335  * \param[in] type Type of requested DAI.
336  * \param[in] index Index of requested DAI.
337  * \param[in] flags Flags (CREATE)
338  */
339 struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags);
340 
341 /**
342  * \brief API to release a platform DAI.
343  *
344  * @param[in] dai DAI to relese.
345  */
346 void dai_put(struct dai *dai);
347 
348 #define dai_set_drvdata(dai, data) \
349 	(dai->priv_data = data)
350 #define dai_get_drvdata(dai) \
351 	dai->priv_data
352 #define dai_base(dai) \
353 	dai->plat_data.base
354 #define dai_irq(dai) \
355 	dai->plat_data.irq
356 #define dai_fifo(dai, direction) \
357 	dai->plat_data.fifo[direction].offset
358 
359 /**
360  * \brief Digital Audio interface formatting
361  */
dai_set_config(struct dai * dai,struct ipc_config_dai * config,void * spec_config)362 static inline int dai_set_config(struct dai *dai, struct ipc_config_dai *config,
363 				 void *spec_config)
364 {
365 	int ret = dai->drv->ops.set_config(dai, config, spec_config);
366 
367 	return ret;
368 }
369 
370 /**
371  * \brief Digital Audio interface trigger
372  */
dai_trigger(struct dai * dai,int cmd,int direction)373 static inline int dai_trigger(struct dai *dai, int cmd, int direction)
374 {
375 	int ret = dai->drv->ops.trigger(dai, cmd, direction);
376 
377 	return ret;
378 }
379 
380 /**
381  * \brief Digital Audio interface PM context store
382  */
dai_pm_context_store(struct dai * dai)383 static inline int dai_pm_context_store(struct dai *dai)
384 {
385 	int ret = dai->drv->ops.pm_context_store(dai);
386 
387 	return ret;
388 }
389 
390 /**
391  * \brief Digital Audio interface PM context restore
392  */
dai_pm_context_restore(struct dai * dai)393 static inline int dai_pm_context_restore(struct dai *dai)
394 {
395 	int ret = dai->drv->ops.pm_context_restore(dai);
396 
397 	return ret;
398 }
399 
400 /**
401  * \brief Get Digital Audio interface stream parameters
402  */
dai_get_hw_params(struct dai * dai,struct sof_ipc_stream_params * params,int dir)403 static inline int dai_get_hw_params(struct dai *dai,
404 				    struct sof_ipc_stream_params *params,
405 				    int dir)
406 {
407 	int ret = dai->drv->ops.get_hw_params(dai, params, dir);
408 
409 	return ret;
410 }
411 
412 /**
413  * \brief Configure Digital Audio interface stream parameters
414  */
dai_hw_params(struct dai * dai,struct sof_ipc_stream_params * params)415 static inline int dai_hw_params(struct dai *dai,
416 				struct sof_ipc_stream_params *params)
417 {
418 	int ret = 0;
419 
420 	if (dai->drv->ops.hw_params)
421 		ret = dai->drv->ops.hw_params(dai, params);
422 
423 	return ret;
424 }
425 
426 /**
427  * \brief Get Digital Audio interface DMA Handshake
428  */
dai_get_handshake(struct dai * dai,int direction,int stream_id)429 static inline int dai_get_handshake(struct dai *dai, int direction,
430 				    int stream_id)
431 {
432 	int ret = dai->drv->ops.get_handshake(dai, direction, stream_id);
433 
434 	return ret;
435 }
436 
437 /**
438  * \brief Get Digital Audio interface FIFO address
439  */
dai_get_fifo(struct dai * dai,int direction,int stream_id)440 static inline int dai_get_fifo(struct dai *dai, int direction,
441 			       int stream_id)
442 {
443 	int ret = dai->drv->ops.get_fifo(dai, direction, stream_id);
444 
445 	return ret;
446 }
447 
448 /**
449  * \brief Digital Audio interface Probe
450  */
dai_probe(struct dai * dai)451 static inline int dai_probe(struct dai *dai)
452 {
453 	int ret = dai->drv->ops.probe(dai);
454 
455 	return ret;
456 }
457 
458 /**
459  * \brief Digital Audio interface Remove
460  */
dai_remove(struct dai * dai)461 static inline int dai_remove(struct dai *dai)
462 {
463 	int ret = dai->drv->ops.remove(dai);
464 
465 	return ret;
466 }
467 
468 /**
469  * \brief Get driver specific DAI information
470  */
dai_get_info(struct dai * dai,int info)471 static inline int dai_get_info(struct dai *dai, int info)
472 {
473 	int ret;
474 
475 	switch (info) {
476 	case DAI_INFO_TYPE:
477 		ret = dai->drv->type;
478 		break;
479 	case DAI_INFO_DMA_CAPS:
480 		ret = dai->drv->dma_caps;
481 		break;
482 	case DAI_INFO_DMA_DEV:
483 		ret = dai->drv->dma_dev;
484 		break;
485 	default:
486 		ret = -EINVAL;
487 		break;
488 	}
489 
490 	return ret;
491 }
492 
dai_write(struct dai * dai,uint32_t reg,uint32_t value)493 static inline void dai_write(struct dai *dai, uint32_t reg, uint32_t value)
494 {
495 	io_reg_write(dai_base(dai) + reg, value);
496 }
497 
dai_read(struct dai * dai,uint32_t reg)498 static inline uint32_t dai_read(struct dai *dai, uint32_t reg)
499 {
500 	uint32_t val = io_reg_read(dai_base(dai) + reg);
501 
502 	return val;
503 }
504 
dai_update_bits(struct dai * dai,uint32_t reg,uint32_t mask,uint32_t value)505 static inline void dai_update_bits(struct dai *dai, uint32_t reg,
506 				   uint32_t mask, uint32_t value)
507 {
508 	io_reg_update_bits(dai_base(dai) + reg, mask, value);
509 }
510 
dai_info_get(void)511 static inline const struct dai_info *dai_info_get(void)
512 {
513 	return sof_get()->dai_info;
514 }
515 
516 /**
517  * \brief Configure DMA channel for DAI
518  */
519 int dai_config_dma_channel(struct comp_dev *dev, void *config);
520 
521 /**
522  * \brief Configure DAI physical interface.
523  */
524 int dai_config(struct comp_dev *dev,  struct ipc_config_dai *common_config,
525 	       void *spec_config);
526 
527 /**
528  * \brief Assign DAI to a group for simultaneous triggering.
529  */
530 int dai_assign_group(struct comp_dev *dev, uint32_t group_id);
531 
532 /** @}*/
533 
534 #endif /* __SOF_LIB_DAI_H__ */
535