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