1 /*
2  * Copyright (c) 2018, Intel Corporation
3  *
4  * Author:	Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
5  *		Sathish Kuttan <sathish.k.kuttan@intel.com>
6  *
7  * SPDX-License-Identifier: Apache-2.0
8  */
9 
10 /**
11  * @file
12  * @brief Public API header file for Digital Microphones
13  *
14  * This file contains the Digital Microphone APIs
15  */
16 
17 #ifndef ZEPHYR_INCLUDE_AUDIO_DMIC_H_
18 #define ZEPHYR_INCLUDE_AUDIO_DMIC_H_
19 
20 
21 /**
22  * @defgroup audio_interface Audio
23  * @{
24  * @}
25  */
26 
27 /**
28  * @brief Abstraction for digital microphones
29  *
30  * @defgroup audio_dmic_interface Digital Microphone Interface
31  * @since 1.13
32  * @version 0.1.0
33  * @ingroup audio_interface
34  * @{
35  */
36 
37 #include <zephyr/kernel.h>
38 #include <zephyr/device.h>
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 /**
45  * DMIC driver states
46  */
47 enum dmic_state {
48 	DMIC_STATE_UNINIT,	/**< Uninitialized */
49 	DMIC_STATE_INITIALIZED,	/**< Initialized */
50 	DMIC_STATE_CONFIGURED,	/**< Configured */
51 	DMIC_STATE_ACTIVE,	/**< Active */
52 	DMIC_STATE_PAUSED,	/**< Paused */
53 	DMIC_STATE_ERROR,	/**< Error */
54 };
55 
56 /**
57  * DMIC driver trigger commands
58  */
59 enum dmic_trigger {
60 	DMIC_TRIGGER_STOP,	/**< Stop stream */
61 	DMIC_TRIGGER_START,	/**< Start stream */
62 	DMIC_TRIGGER_PAUSE,	/**< Pause stream */
63 	DMIC_TRIGGER_RELEASE,	/**< Release paused stream */
64 	DMIC_TRIGGER_RESET,	/**< Reset stream */
65 };
66 
67 /**
68  * PDM Channels LEFT / RIGHT
69  */
70 enum pdm_lr {
71 	PDM_CHAN_LEFT,	/**< Left channel */
72 	PDM_CHAN_RIGHT, /**< Right channel */
73 };
74 
75 /**
76  * PDM Input/Output signal configuration
77  */
78 struct pdm_io_cfg {
79 	/**
80 	 * @name Parameters common to all PDM controllers
81 	 *@{
82 	 */
83 	/** Minimum clock frequency supported by the mic */
84 	uint32_t	min_pdm_clk_freq;
85 	/** Maximum clock frequency supported by the mic */
86 	uint32_t	max_pdm_clk_freq;
87 	/** Minimum duty cycle in % supported by the mic */
88 	uint8_t	min_pdm_clk_dc;
89 	/** Maximum duty cycle in % supported by the mic */
90 	uint8_t	max_pdm_clk_dc;
91 	/**
92 	 * @}
93 	 */
94 
95 	/**
96 	 * @name Parameters unique to each PDM controller
97 	 * @{
98 	 */
99 	/** Bit mask to optionally invert PDM clock */
100 	uint8_t	pdm_clk_pol;
101 	/** Bit mask to optionally invert mic data */
102 	uint8_t	pdm_data_pol;
103 	/** Collection of clock skew values for each PDM port */
104 	uint32_t	pdm_clk_skew;
105 	/**
106 	 * @}
107 	 */
108 };
109 
110 /**
111  * Configuration of the PCM streams to be output by the PDM hardware
112  *
113  * @note if either \ref pcm_rate or \ref pcm_width is set to 0 for a stream,
114  * the stream would be disabled
115  */
116 struct pcm_stream_cfg {
117 	/** PCM sample rate of stream */
118 	uint32_t			pcm_rate;
119 	/** PCM sample width of stream */
120 	uint8_t			pcm_width;
121 	/** PCM sample block size per transfer */
122 	uint16_t			block_size;
123 	/** SLAB for DMIC driver to allocate buffers for stream */
124 	struct k_mem_slab	*mem_slab;
125 };
126 
127 /**
128  * Mapping/ordering of the PDM channels to logical PCM output channel
129  *
130  * Since each controller can have 2 audio channels (stereo),
131  * there can be a total of 8x2=16 channels. The actual number of channels
132  * shall be described in \ref act_num_chan.
133  *
134  * If 2 streams are enabled, the channel order will be the same for
135  * both streams.
136  *
137  * Each channel is described as a 4-bit number, the least significant
138  * bit indicates LEFT/RIGHT selection of the PDM controller.
139  *
140  * The most significant 3 bits indicate the PDM controller number:
141  *  - bits 0-3 are for channel 0, bit 0 indicates LEFT or RIGHT
142  *  - bits 4-7 are for channel 1, bit 4 indicates LEFT or RIGHT
143  * and so on.
144  *
145  * CONSTRAINT: The LEFT and RIGHT channels of EACH PDM controller needs
146  * to be adjacent to each other.
147  */
148 struct pdm_chan_cfg {
149 	/**
150 	 * @name Requested channel map
151 	 * @{
152 	 */
153 	uint32_t	req_chan_map_lo;	/**< Channels 0 to 7 */
154 	uint32_t	req_chan_map_hi;	/**< Channels 8 to 15 */
155 	/** @} */
156 
157 	/**
158 	 * @name Actual channel map that the driver could configure
159 	 * @{
160 	 */
161 	uint32_t	act_chan_map_lo;	/**< Channels 0 to 7 */
162 	uint32_t	act_chan_map_hi;	/**< Channels 8 to 15 */
163 	/** @} */
164 
165 	/** Requested number of channels */
166 	uint8_t	req_num_chan;
167 	/** Actual number of channels that the driver could configure */
168 	uint8_t	act_num_chan;
169 	/** Requested number of streams for each channel */
170 	uint8_t	req_num_streams;
171 	/** Actual number of streams that the driver could configure */
172 	uint8_t	act_num_streams;
173 };
174 
175 /**
176  * Input configuration structure for the DMIC configuration API
177  */
178 struct dmic_cfg {
179 	struct pdm_io_cfg io;
180 	/**
181 	 * Array of pcm_stream_cfg for application to provide
182 	 * configuration for each stream
183 	 */
184 	struct pcm_stream_cfg *streams;
185 	struct pdm_chan_cfg channel;
186 };
187 
188 /**
189  * Function pointers for the DMIC driver operations
190  */
191 struct _dmic_ops {
192 	int (*configure)(const struct device *dev, struct dmic_cfg *config);
193 	int (*trigger)(const struct device *dev, enum dmic_trigger cmd);
194 	int (*read)(const struct device *dev, uint8_t stream, void **buffer,
195 			size_t *size, int32_t timeout);
196 };
197 
198 /**
199  * Build the channel map to populate struct pdm_chan_cfg
200  *
201  * Returns the map of PDM controller and LEFT/RIGHT channel shifted to
202  * the bit position corresponding to the input logical channel value
203  *
204  * @param channel The logical channel number
205  * @param pdm The PDM hardware controller number
206  * @param lr LEFT/RIGHT channel within the chosen PDM hardware controller
207  *
208  * @return Bit-map containing the PDM and L/R channel information
209  */
dmic_build_channel_map(uint8_t channel,uint8_t pdm,enum pdm_lr lr)210 static inline uint32_t dmic_build_channel_map(uint8_t channel, uint8_t pdm,
211 		enum pdm_lr lr)
212 {
213 	return ((((pdm & BIT_MASK(3)) << 1) | lr) <<
214 			((channel & BIT_MASK(3)) * 4U));
215 }
216 
217 /**
218  * Helper function to parse the channel map in pdm_chan_cfg
219  *
220  * Returns the PDM controller and LEFT/RIGHT channel corresponding to
221  * the channel map and the logical channel provided as input
222  *
223  * @param channel_map_lo Lower order/significant bits of the channel map
224  * @param channel_map_hi Higher order/significant bits of the channel map
225  * @param channel The logical channel number
226  * @param pdm Pointer to the PDM hardware controller number
227  * @param lr Pointer to the LEFT/RIGHT channel within the PDM controller
228  */
dmic_parse_channel_map(uint32_t channel_map_lo,uint32_t channel_map_hi,uint8_t channel,uint8_t * pdm,enum pdm_lr * lr)229 static inline void dmic_parse_channel_map(uint32_t channel_map_lo,
230 		uint32_t channel_map_hi, uint8_t channel, uint8_t *pdm, enum pdm_lr *lr)
231 {
232 	uint32_t channel_map;
233 
234 	channel_map = (channel < 8) ? channel_map_lo : channel_map_hi;
235 	channel_map >>= ((channel & BIT_MASK(3)) * 4U);
236 
237 	*pdm = (channel_map >> 1) & BIT_MASK(3);
238 	*lr = (enum pdm_lr) (channel_map & BIT(0));
239 }
240 
241 /**
242  * Build a bit map of clock skew values for each PDM channel
243  *
244  * Returns the bit-map of clock skew value shifted to the bit position
245  * corresponding to the input PDM controller value
246  *
247  * @param pdm The PDM hardware controller number
248  * @param skew The skew to apply for the clock output from the PDM controller
249  *
250  * @return Bit-map containing the clock skew information
251  */
dmic_build_clk_skew_map(uint8_t pdm,uint8_t skew)252 static inline uint32_t dmic_build_clk_skew_map(uint8_t pdm, uint8_t skew)
253 {
254 	return ((skew & BIT_MASK(4)) << ((pdm & BIT_MASK(3)) * 4U));
255 }
256 
257 /**
258  * Configure the DMIC driver and controller(s)
259  *
260  * Configures the DMIC driver device according to the number of channels,
261  * channel mapping, PDM I/O configuration, PCM stream configuration, etc.
262  *
263  * @param dev Pointer to the device structure for DMIC driver instance
264  * @param cfg Pointer to the structure containing the DMIC configuration
265  *
266  * @return 0 on success, a negative error code on failure
267  */
dmic_configure(const struct device * dev,struct dmic_cfg * cfg)268 static inline int dmic_configure(const struct device *dev,
269 				 struct dmic_cfg *cfg)
270 {
271 	const struct _dmic_ops *api =
272 		(const struct _dmic_ops *)dev->api;
273 
274 	return api->configure(dev, cfg);
275 }
276 
277 /**
278  * Send a command to the DMIC driver
279  *
280  * Sends a command to the driver to perform a specific action
281  *
282  * @param dev Pointer to the device structure for DMIC driver instance
283  * @param cmd The command to be sent to the driver instance
284  *
285  * @return 0 on success, a negative error code on failure
286  */
dmic_trigger(const struct device * dev,enum dmic_trigger cmd)287 static inline int dmic_trigger(const struct device *dev,
288 			       enum dmic_trigger cmd)
289 {
290 	const struct _dmic_ops *api =
291 		(const struct _dmic_ops *)dev->api;
292 
293 	return api->trigger(dev, cmd);
294 }
295 
296 /**
297  * Read received decimated PCM data stream
298  *
299  * Optionally waits for audio to be received and provides the received
300  * audio buffer from the requested stream
301  *
302  * @param dev Pointer to the device structure for DMIC driver instance
303  * @param stream Stream identifier
304  * @param buffer Pointer to the received buffer address
305  * @param size Pointer to the received buffer size
306  * @param timeout Timeout in milliseconds to wait in case audio is not yet
307  * 		  received, or @ref SYS_FOREVER_MS
308  *
309  * @return 0 on success, a negative error code on failure
310  */
dmic_read(const struct device * dev,uint8_t stream,void ** buffer,size_t * size,int32_t timeout)311 static inline int dmic_read(const struct device *dev, uint8_t stream,
312 			    void **buffer,
313 			    size_t *size, int32_t timeout)
314 {
315 	const struct _dmic_ops *api =
316 		(const struct _dmic_ops *)dev->api;
317 
318 	return api->read(dev, stream, buffer, size, timeout);
319 }
320 
321 #ifdef __cplusplus
322 }
323 #endif
324 
325 /**
326  * @}
327  */
328 
329 #endif /* ZEPHYR_INCLUDE_AUDIO_DMIC_H_ */
330