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