Line data Source code
1 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 1 : 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 1 : 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 1 : 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 1 : struct pdm_io_cfg {
79 : /**
80 : * @name Parameters common to all PDM controllers
81 : *@{
82 : */
83 : /** Minimum clock frequency supported by the mic */
84 1 : uint32_t min_pdm_clk_freq;
85 : /** Maximum clock frequency supported by the mic */
86 1 : uint32_t max_pdm_clk_freq;
87 : /** Minimum duty cycle in % supported by the mic */
88 1 : uint8_t min_pdm_clk_dc;
89 : /** Maximum duty cycle in % supported by the mic */
90 1 : 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 1 : uint8_t pdm_clk_pol;
101 : /** Bit mask to optionally invert mic data */
102 1 : uint8_t pdm_data_pol;
103 : /** Collection of clock skew values for each PDM port */
104 1 : 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 1 : struct pcm_stream_cfg {
117 : /** PCM sample rate of stream */
118 1 : uint32_t pcm_rate;
119 : /** PCM sample width of stream */
120 1 : uint8_t pcm_width;
121 : /** PCM sample block size per transfer */
122 1 : uint16_t block_size;
123 : /** SLAB for DMIC driver to allocate buffers for stream */
124 1 : 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 1 : struct pdm_chan_cfg {
149 : /**
150 : * @name Requested channel map
151 : * @{
152 : */
153 1 : uint32_t req_chan_map_lo; /**< Channels 0 to 7 */
154 1 : 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 1 : uint32_t act_chan_map_lo; /**< Channels 0 to 7 */
162 1 : uint32_t act_chan_map_hi; /**< Channels 8 to 15 */
163 : /** @} */
164 :
165 : /** Requested number of channels */
166 1 : uint8_t req_num_chan;
167 : /** Actual number of channels that the driver could configure */
168 1 : uint8_t act_num_chan;
169 : /** Requested number of streams for each channel */
170 1 : uint8_t req_num_streams;
171 : /** Actual number of streams that the driver could configure */
172 1 : uint8_t act_num_streams;
173 : };
174 :
175 : /**
176 : * Input configuration structure for the DMIC configuration API
177 : */
178 1 : struct dmic_cfg {
179 0 : struct pdm_io_cfg io;
180 : /**
181 : * Array of pcm_stream_cfg for application to provide
182 : * configuration for each stream
183 : */
184 1 : struct pcm_stream_cfg *streams;
185 0 : 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 : */
210 1 : 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 : */
229 1 : 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 : */
252 1 : 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 : */
268 1 : 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 : */
287 1 : 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 : */
311 1 : 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_ */
|