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