1 /*
2 * Copyright (c) 2018 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief Public API header file for Audio Codec
10 *
11 * This file contains the Audio Codec APIs
12 */
13
14 #ifndef ZEPHYR_INCLUDE_AUDIO_CODEC_H_
15 #define ZEPHYR_INCLUDE_AUDIO_CODEC_H_
16
17 /**
18 * @brief Abstraction for audio codecs
19 *
20 * @defgroup audio_codec_interface Audio Codec Interface
21 * @since 1.13
22 * @version 0.1.0
23 * @ingroup audio_interface
24 * @{
25 */
26
27 #include <errno.h>
28 #include <zephyr/drivers/i2s.h>
29
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33
34 /**
35 * PCM audio sample rates
36 */
37 typedef enum {
38 AUDIO_PCM_RATE_8K = 8000, /**< 8 kHz sample rate */
39 AUDIO_PCM_RATE_11P025K = 11025, /**< 11.025 kHz sample rate */
40 AUDIO_PCM_RATE_16K = 16000, /**< 16 kHz sample rate */
41 AUDIO_PCM_RATE_22P05K = 22050, /**< 22.05 kHz sample rate */
42 AUDIO_PCM_RATE_24K = 24000, /**< 24 kHz sample rate */
43 AUDIO_PCM_RATE_32K = 32000, /**< 32 kHz sample rate */
44 AUDIO_PCM_RATE_44P1K = 44100, /**< 44.1 kHz sample rate */
45 AUDIO_PCM_RATE_48K = 48000, /**< 48 kHz sample rate */
46 AUDIO_PCM_RATE_96K = 96000, /**< 96 kHz sample rate */
47 AUDIO_PCM_RATE_192K = 192000, /**< 192 kHz sample rate */
48 } audio_pcm_rate_t;
49
50 /**
51 * PCM audio sample bit widths
52 */
53 typedef enum {
54 AUDIO_PCM_WIDTH_16_BITS = 16, /**< 16-bit sample width */
55 AUDIO_PCM_WIDTH_20_BITS = 20, /**< 20-bit sample width */
56 AUDIO_PCM_WIDTH_24_BITS = 24, /**< 24-bit sample width */
57 AUDIO_PCM_WIDTH_32_BITS = 32, /**< 32-bit sample width */
58 } audio_pcm_width_t;
59
60 /**
61 * Digital Audio Interface (DAI) type
62 */
63 typedef enum {
64 AUDIO_DAI_TYPE_I2S, /**< I2S Interface */
65 AUDIO_DAI_TYPE_LEFT_JUSTIFIED, /**< I2S Interface, left justified */
66 AUDIO_DAI_TYPE_RIGHT_JUSTIFIED, /**< I2S Interface, right justified */
67 AUDIO_DAI_TYPE_PCMA, /**< PCM Interface, variant A */
68 AUDIO_DAI_TYPE_PCMB, /**< PCM Interface, variant B */
69 AUDIO_DAI_TYPE_INVALID, /**< Other interfaces can be added here */
70 } audio_dai_type_t;
71
72 /**
73 * Codec properties that can be set by audio_codec_set_property().
74 */
75 typedef enum {
76 AUDIO_PROPERTY_OUTPUT_VOLUME, /**< Output volume */
77 AUDIO_PROPERTY_OUTPUT_MUTE, /**< Output mute/unmute */
78 AUDIO_PROPERTY_INPUT_VOLUME, /**< Input volume */
79 AUDIO_PROPERTY_INPUT_MUTE /**< Input mute/unmute */
80 } audio_property_t;
81
82 /**
83 * Audio channel identifiers to use in audio_codec_set_property().
84 */
85 typedef enum {
86 AUDIO_CHANNEL_FRONT_LEFT, /**< Front left channel */
87 AUDIO_CHANNEL_FRONT_RIGHT, /**< Front right channel */
88 AUDIO_CHANNEL_LFE, /**< Low frequency effect channel */
89 AUDIO_CHANNEL_FRONT_CENTER, /**< Front center channel */
90 AUDIO_CHANNEL_REAR_LEFT, /**< Rear left channel */
91 AUDIO_CHANNEL_REAR_RIGHT, /**< Rear right channel */
92 AUDIO_CHANNEL_REAR_CENTER, /**< Rear center channel */
93 AUDIO_CHANNEL_SIDE_LEFT, /**< Side left channel */
94 AUDIO_CHANNEL_SIDE_RIGHT, /**< Side right channel */
95 AUDIO_CHANNEL_HEADPHONE_LEFT, /**< Headphone left */
96 AUDIO_CHANNEL_HEADPHONE_RIGHT, /**< Headphone right */
97 AUDIO_CHANNEL_ALL, /**< All channels */
98
99 /**
100 * Number of all common channel identifiers.
101 */
102 AUDIO_CHANNEL_COMMON_COUNT,
103
104 /**
105 * This and higher values are codec specific.
106 * Refer to the codec's header file.
107 */
108 AUDIO_CHANNEL_PRIV_START = AUDIO_CHANNEL_COMMON_COUNT,
109
110 /**
111 * Maximum value describing an audio codec channel identifier.
112 */
113 AUDIO_CHANNEL_MAX = INT16_MAX
114 } audio_channel_t;
115
116 /**
117 * @brief Digital Audio Interface Configuration.
118 *
119 * Configuration is dependent on DAI type
120 */
121 typedef union {
122 struct i2s_config i2s; /**< I2S configuration */
123 /* Other DAI types go here */
124 } audio_dai_cfg_t;
125
126 /*
127 * DAI Route types
128 */
129 typedef enum {
130 AUDIO_ROUTE_BYPASS,
131 AUDIO_ROUTE_PLAYBACK,
132 AUDIO_ROUTE_PLAYBACK_CAPTURE,
133 AUDIO_ROUTE_CAPTURE,
134 } audio_route_t;
135
136 /**
137 * Codec configuration parameters
138 */
139 struct audio_codec_cfg {
140 uint32_t mclk_freq; /**< MCLK input frequency in Hz */
141 audio_dai_type_t dai_type; /**< Digital interface type */
142 audio_dai_cfg_t dai_cfg; /**< DAI configuration info */
143 audio_route_t dai_route; /**< Codec route type */
144 };
145
146 /**
147 * Codec property values
148 */
149 typedef union {
150 int vol; /**< Volume level (codec-specific) */
151 bool mute; /**< Mute if @a true, unmute if @a false */
152 } audio_property_value_t;
153
154 /**
155 * @brief Codec error type
156 */
157 enum audio_codec_error_type {
158 /** Output over-current */
159 AUDIO_CODEC_ERROR_OVERCURRENT = BIT(0),
160
161 /** Codec over-temperature */
162 AUDIO_CODEC_ERROR_OVERTEMPERATURE = BIT(1),
163
164 /** Power low voltage */
165 AUDIO_CODEC_ERROR_UNDERVOLTAGE = BIT(2),
166
167 /** Power high voltage */
168 AUDIO_CODEC_ERROR_OVERVOLTAGE = BIT(3),
169
170 /** Output direct-current */
171 AUDIO_CODEC_ERROR_DC = BIT(4),
172 };
173
174 /**
175 * @typedef audio_codec_error_callback_t
176 * @brief Callback for error interrupt
177 *
178 * @param dev Pointer to the codec device
179 * @param errors Device errors (bitmask of @ref audio_codec_error_type values)
180 */
181 typedef void (*audio_codec_error_callback_t)(const struct device *dev, uint32_t errors);
182
183 /**
184 * @cond INTERNAL_HIDDEN
185 *
186 * For internal use only, skip these in public documentation.
187 */
188 struct audio_codec_api {
189 int (*configure)(const struct device *dev,
190 struct audio_codec_cfg *cfg);
191 void (*start_output)(const struct device *dev);
192 void (*stop_output)(const struct device *dev);
193 int (*set_property)(const struct device *dev,
194 audio_property_t property,
195 audio_channel_t channel,
196 audio_property_value_t val);
197 int (*apply_properties)(const struct device *dev);
198 int (*clear_errors)(const struct device *dev);
199 int (*register_error_callback)(const struct device *dev,
200 audio_codec_error_callback_t cb);
201 int (*route_input)(const struct device *dev, audio_channel_t channel, uint32_t input);
202 int (*route_output)(const struct device *dev, audio_channel_t channel, uint32_t output);
203 };
204 /**
205 * @endcond
206 */
207
208 /**
209 * @brief Configure the audio codec
210 *
211 * Configure the audio codec device according to the configuration
212 * parameters provided as input
213 *
214 * @param dev Pointer to the device structure for codec driver instance.
215 * @param cfg Pointer to the structure containing the codec configuration.
216 *
217 * @return 0 on success, negative error code on failure
218 */
audio_codec_configure(const struct device * dev,struct audio_codec_cfg * cfg)219 static inline int audio_codec_configure(const struct device *dev,
220 struct audio_codec_cfg *cfg)
221 {
222 const struct audio_codec_api *api =
223 (const struct audio_codec_api *)dev->api;
224
225 return api->configure(dev, cfg);
226 }
227
228 /**
229 * @brief Set codec to start output audio playback
230 *
231 * Setup the audio codec device to start the audio playback
232 *
233 * @param dev Pointer to the device structure for codec driver instance.
234 */
audio_codec_start_output(const struct device * dev)235 static inline void audio_codec_start_output(const struct device *dev)
236 {
237 const struct audio_codec_api *api =
238 (const struct audio_codec_api *)dev->api;
239
240 api->start_output(dev);
241 }
242
243 /**
244 * @brief Set codec to stop output audio playback
245 *
246 * Setup the audio codec device to stop the audio playback
247 *
248 * @param dev Pointer to the device structure for codec driver instance.
249 */
audio_codec_stop_output(const struct device * dev)250 static inline void audio_codec_stop_output(const struct device *dev)
251 {
252 const struct audio_codec_api *api =
253 (const struct audio_codec_api *)dev->api;
254
255 api->stop_output(dev);
256 }
257
258 /**
259 * @brief Set a codec property defined by audio_property_t
260 *
261 * Set a property such as volume level, clock configuration etc.
262 *
263 * @param dev Pointer to the device structure for codec driver instance.
264 * @param property The codec property to set
265 * @param channel The audio channel for which the property has to be set
266 * @param val pointer to a property value of type audio_codec_property_value_t
267 *
268 * @return 0 on success, negative error code on failure
269 */
audio_codec_set_property(const struct device * dev,audio_property_t property,audio_channel_t channel,audio_property_value_t val)270 static inline int audio_codec_set_property(const struct device *dev,
271 audio_property_t property,
272 audio_channel_t channel,
273 audio_property_value_t val)
274 {
275 const struct audio_codec_api *api =
276 (const struct audio_codec_api *)dev->api;
277
278 return api->set_property(dev, property, channel, val);
279 }
280
281 /**
282 * @brief Atomically apply any cached properties
283 *
284 * Following one or more invocations of audio_codec_set_property, that may have
285 * been cached by the driver, audio_codec_apply_properties can be invoked to
286 * apply all the properties as atomic as possible
287 *
288 * @param dev Pointer to the device structure for codec driver instance.
289 *
290 * @return 0 on success, negative error code on failure
291 */
audio_codec_apply_properties(const struct device * dev)292 static inline int audio_codec_apply_properties(const struct device *dev)
293 {
294 const struct audio_codec_api *api =
295 (const struct audio_codec_api *)dev->api;
296
297 return api->apply_properties(dev);
298 }
299
300 /**
301 * @brief Clear any codec errors
302 *
303 * Clear all codec errors.
304 * If an error interrupt exists, it will be de-asserted.
305 *
306 * @param dev Pointer to the device structure for codec driver instance.
307 *
308 * @return 0 on success, negative error code on failure
309 */
audio_codec_clear_errors(const struct device * dev)310 static inline int audio_codec_clear_errors(const struct device *dev)
311 {
312 const struct audio_codec_api *api =
313 (const struct audio_codec_api *)dev->api;
314
315 if (api->clear_errors == NULL) {
316 return -ENOSYS;
317 }
318
319 return api->clear_errors(dev);
320 }
321
322 /**
323 * @brief Register a callback function for codec error
324 *
325 * The callback will be called from a thread, so I2C or SPI operations are
326 * safe. However, the thread's stack is limited and defined by the
327 * driver. It is currently up to the caller to ensure that the callback
328 * does not overflow the stack.
329 *
330 * @param dev Pointer to the audio codec device
331 * @param cb The function that should be called when an error is detected
332 * fires
333 *
334 * @return 0 if successful, negative errno code if failure.
335 */
audio_codec_register_error_callback(const struct device * dev,audio_codec_error_callback_t cb)336 static inline int audio_codec_register_error_callback(const struct device *dev,
337 audio_codec_error_callback_t cb)
338 {
339 const struct audio_codec_api *api =
340 (const struct audio_codec_api *)dev->api;
341
342 if (api->register_error_callback == NULL) {
343 return -ENOSYS;
344 }
345
346 return api->register_error_callback(dev, cb);
347 }
348
349 /**
350 * @brief Sets up signal routing for a given input channel.
351 *
352 * Some codecs can do input routing (multiplexing) from a chosen set of
353 * physical inputs. This function maps a given audio (stream) channel to
354 * a given physical input terminal.
355 *
356 * @param dev Pointer to the audio codec device
357 * @param channel The channel to map
358 * @param input The input terminal index, codec-specific
359 *
360 * @return 0 if successful, negative errno code if failure.
361 */
audio_codec_route_input(const struct device * dev,audio_channel_t channel,uint32_t input)362 static inline int audio_codec_route_input(const struct device *dev, audio_channel_t channel,
363 uint32_t input)
364 {
365 const struct audio_codec_api *api = (const struct audio_codec_api *)dev->api;
366
367 if (api->route_input == NULL) {
368 return -ENOSYS;
369 }
370
371 return api->route_input(dev, channel, input);
372 }
373
374 /**
375 * @brief Sets up signal routing for a given output channel.
376 *
377 * Some codecs can do output routing (multiplexing) from a chosen set of
378 * physical output. This function maps a given audio (stream) channel to
379 * a given physical output terminal.
380 *
381 * @param dev Pointer to the audio codec device
382 * @param channel The channel to map
383 * @param output The output terminal index, codec-specific
384 *
385 * @return 0 if successful, negative errno code if failure.
386 */
audio_codec_route_output(const struct device * dev,audio_channel_t channel,uint32_t output)387 static inline int audio_codec_route_output(const struct device *dev, audio_channel_t channel,
388 uint32_t output)
389 {
390 const struct audio_codec_api *api = (const struct audio_codec_api *)dev->api;
391
392 if (api->route_output == NULL) {
393 return -ENOSYS;
394 }
395
396 return api->route_output(dev, channel, output);
397 }
398
399 #ifdef __cplusplus
400 }
401 #endif
402
403 /**
404 * @}
405 */
406
407 #endif /* ZEPHYR_INCLUDE_AUDIO_CODEC_H_ */
408