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