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