1 /*
2 * Copyright (c) 2019-2025 Allwinner Technology Co., Ltd. ALL rights reserved.
3 *
4 * Allwinner is a trademark of Allwinner Technology Co.,Ltd., registered in
5 * the the people's Republic of China and other countries.
6 * All Allwinner Technology Co.,Ltd. trademarks are used with permission.
7 *
8 * DISCLAIMER
9 * THIRD PARTY LICENCES MAY BE REQUIRED TO IMPLEMENT THE SOLUTION/PRODUCT.
10 * IF YOU NEED TO INTEGRATE THIRD PARTY’S TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.)
11 * IN ALLWINNERS’SDK OR PRODUCTS, YOU SHALL BE SOLELY RESPONSIBLE TO OBTAIN
12 * ALL APPROPRIATELY REQUIRED THIRD PARTY LICENCES.
13 * ALLWINNER SHALL HAVE NO WARRANTY, INDEMNITY OR OTHER OBLIGATIONS WITH RESPECT TO MATTERS
14 * COVERED UNDER ANY REQUIRED THIRD PARTY LICENSE.
15 * YOU ARE SOLELY RESPONSIBLE FOR YOUR USAGE OF THIRD PARTY’S TECHNOLOGY.
16 *
17 *
18 * THIS SOFTWARE IS PROVIDED BY ALLWINNER"AS IS" AND TO THE MAXIMUM EXTENT
19 * PERMITTED BY LAW, ALLWINNER EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY KIND,
20 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION REGARDING
21 * THE TITLE, NON-INFRINGEMENT, ACCURACY, CONDITION, COMPLETENESS, PERFORMANCE
22 * OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 * IN NO EVENT SHALL ALLWINNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 * OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 #ifndef __AW_ALSA_PCM_H
33 #define __AW_ALSA_PCM_H
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
38 #include <sound/ksound.h>
39 #include <sound/card.h>
40 #include <sound/pcm_common.h>
41 #include <alloca.h>
42 #include <string.h>
43 #include <sys/types.h>
44 #include <hal_mutex.h>
45 
46 #ifndef snd_malloc
47 #define snd_malloc(size)    calloc(size, 1)
48 #endif
49 
50 #ifndef snd_free
51 #define snd_free(ptr)       free(ptr)
52 #endif
53 
54 
55 /* debug option */
56 #define AW_ALSA_LOG_COLOR_NONE      "\e[0m"
57 #define AW_ALSA_LOG_COLOR_RED       "\e[31m"
58 #define AW_ALSA_LOG_COLOR_GREEN     "\e[32m"
59 #define AW_ALSA_LOG_COLOR_YELLOW    "\e[33m"
60 #define AW_ALSA_LOG_COLOR_BLUE      "\e[34m"
61 
62 //#define AW_ALSA_DEBUG
63 #ifdef AW_ALSA_DEBUG
64 #define awalsa_debug(fmt, args...) \
65     printf(AW_ALSA_LOG_COLOR_GREEN "[AWALSA_DEBUG][%s:%u]" fmt \
66         AW_ALSA_LOG_COLOR_NONE, __FUNCTION__, __LINE__, ##args)
67 #else
68 #define awalsa_debug(fmt, args...)
69 #endif
70 
71 //#define AW_ALSA_PRINT
72 #ifdef AW_ALSA_PRINT
73 #define awalsa_print(fmt, args...) \
74     printf("[AWALSA_PRINT][%s:%u]" fmt, \
75         __FUNCTION__, __LINE__, ##args)
76 #else
77 #define awalsa_print(fmt, args...)
78 #endif
79 
80 #define awalsa_info(fmt, args...) \
81     printf(AW_ALSA_LOG_COLOR_BLUE "[AWALSA_INFO][%s:%u]" fmt \
82         AW_ALSA_LOG_COLOR_NONE, __FUNCTION__, __LINE__, ##args)
83 
84 #define awalsa_err(fmt, args...) \
85     printf(AW_ALSA_LOG_COLOR_RED "[AWALSA_ERR][%s:%u]" fmt \
86         AW_ALSA_LOG_COLOR_NONE, __FUNCTION__, __LINE__, ##args)
87 /* end debug option */
88 
89 /** Non blocking mode (flag for open mode) \hideinitializer */
90 //#define SND_PCM_NONBLOCK      0x00000001
91 /** Async notification (flag for open mode) \hideinitializer */
92 //#define SND_PCM_ASYNC         0x00000002
93 /** In an abort state (internal, not allowed for open) */
94 //#define SND_PCM_ABORT         0x00008000
95 /** Disable automatic (but not forced!) rate resamplinig */
96 #define SND_PCM_NO_AUTO_RESAMPLE    0x00010000
97 /** Disable automatic (but not forced!) channel conversion */
98 #define SND_PCM_NO_AUTO_CHANNELS    0x00020000
99 /** Disable automatic (but not forced!) format conversion */
100 #define SND_PCM_NO_AUTO_FORMAT      0x00040000
101 /** Disable soft volume control */
102 //#define SND_PCM_NO_SOFTVOL        0x00080000
103 
104 typedef struct _snd_pcm snd_pcm_t;
105 
106 enum _snd_pcm_type {
107     /** Kernel level PCM */
108     SND_PCM_TYPE_HW = 0,
109     /** One or more linked PCM with exclusive access to selected
110         channels */
111     SND_PCM_TYPE_MULTI,
112     /** File writing plugin */
113     SND_PCM_TYPE_FILE,
114     /** Linear format conversion PCM */
115     SND_PCM_TYPE_LINEAR,
116     /** Rate conversion PCM */
117     SND_PCM_TYPE_RATE,
118     /** Attenuated static route PCM */
119     SND_PCM_TYPE_ROUTE,
120     /** Format adjusted PCM */
121     SND_PCM_TYPE_PLUG,
122     /** Direct Mixing plugin */
123     SND_PCM_TYPE_DMIX,
124     /** Direct Snooping plugin */
125     SND_PCM_TYPE_DSNOOP,
126     /** Soft volume plugin */
127     SND_PCM_TYPE_SOFTVOL,
128     /** External filter plugin */
129     SND_PCM_TYPE_EXTPLUG,
130     SND_PCM_TYPE_LAST = SND_PCM_TYPE_EXTPLUG
131 };
132 
133 /** PCM type */
134 typedef enum _snd_pcm_type snd_pcm_type_t;
135 
136 /** PCM state */
137 typedef enum _snd_pcm_state {
138         /** Open */
139         SND_PCM_STATE_OPEN = 0,
140         /** Setup installed */
141         SND_PCM_STATE_SETUP,
142         /** Ready to start */
143         SND_PCM_STATE_PREPARED,
144         /** Running */
145         SND_PCM_STATE_RUNNING,
146         /** Stopped: underrun (playback) or overrun (capture) detected */
147         SND_PCM_STATE_XRUN,
148         /** Draining: running (playback) or stopped (capture) */
149         SND_PCM_STATE_DRAINING,
150         /** Paused */
151         SND_PCM_STATE_PAUSED,
152         /** Hardware is suspended */
153         SND_PCM_STATE_SUSPENDED,
154         /** Hardware is disconnected */
155         SND_PCM_STATE_DISCONNECTED,
156         SND_PCM_STATE_LAST = 1024,
157 } snd_pcm_state_t;
158 
159 /** PCM stream (direction) */
160 typedef enum _snd_pcm_stream {
161         /** Playback stream */
162         SND_PCM_STREAM_PLAYBACK = 0,
163         /** Capture stream */
164         SND_PCM_STREAM_CAPTURE,
165         SND_PCM_STREAM_LAST = SND_PCM_STREAM_CAPTURE
166 } snd_pcm_stream_t;
167 
168 
169 /** PCM area specification */
170 typedef struct _snd_pcm_channel_area {
171     /** base address of channel samples */
172     void *addr;
173     /** offset to first sample in bits */
174     unsigned int first;
175     /** samples distance in bits */
176     unsigned int step;
177 } snd_pcm_channel_area_t;
178 
179 
180 int snd_pcm_open(snd_pcm_t **pcm, const char *name,
181         snd_pcm_stream_t stream, int mode);
182 int snd_pcm_close(snd_pcm_t *pcm);
183 
184 int snd_pcm_hw_params_malloc(snd_pcm_hw_params_t **ptr);
185 void snd_pcm_hw_params_free(snd_pcm_hw_params_t *obj);
186 int snd_pcm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
187 int snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
188 int snd_pcm_hw_free(snd_pcm_t *pcm);
189 int snd_pcm_reset(snd_pcm_t *pcm);
190 int snd_pcm_start(snd_pcm_t *pcm);
191 int snd_pcm_prepare(snd_pcm_t *pcm);
192 int snd_pcm_drop(snd_pcm_t *pcm);
193 int snd_pcm_drain(snd_pcm_t *pcm);
194 int snd_pcm_pause(snd_pcm_t *pcm, int enable);
195 int snd_pcm_recover(snd_pcm_t *pcm, int err, int silent);
196 int snd_pcm_resume(snd_pcm_t *pcm);
197 snd_pcm_state_t snd_pcm_state(snd_pcm_t *pcm);
198 snd_pcm_stream_t snd_pcm_stream(snd_pcm_t *pcm);
199 int snd_pcm_hwsync(snd_pcm_t *pcm);
200 int snd_pcm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
201 snd_pcm_sframes_t snd_pcm_avail_update(snd_pcm_t *pcm);
202 int snd_pcm_hw_params_can_pause(const snd_pcm_hw_params_t *params);
203 snd_pcm_sframes_t snd_pcm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
204 int snd_pcm_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2);
205 int snd_pcm_unlink(snd_pcm_t *pcm);
206 
207 snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size);
208 snd_pcm_sframes_t snd_pcm_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size);
209 
210 int snd_pcm_wait(snd_pcm_t *pcm, int timeout);
211 
212 int snd_pcm_dump(snd_pcm_t *pcm);
213 int snd_pcm_dump_setup(snd_pcm_t *pcm);
214 int snd_pcm_dump_hw_setup(snd_pcm_t *pcm);
215 int snd_pcm_dump_sw_setup(snd_pcm_t *pcm);
216 int snd_pcm_hw_params_dump(snd_pcm_hw_params_t *params);
217 
218 /** channel positions */
219 enum snd_pcm_chmap_position {
220     SND_CHMAP_UNKNOWN = 0,  /**< unspecified */
221     SND_CHMAP_NA,       /**< N/A, silent */
222     SND_CHMAP_MONO,     /**< mono stream */
223     SND_CHMAP_FL,       /**< front left */
224     SND_CHMAP_FR,       /**< front right */
225     SND_CHMAP_RL,       /**< rear left */
226     SND_CHMAP_RR,       /**< rear right */
227     SND_CHMAP_FC,       /**< front center */
228     SND_CHMAP_LFE,      /**< LFE */
229     SND_CHMAP_SL,       /**< side left */
230     SND_CHMAP_SR,       /**< side right */
231     SND_CHMAP_RC,       /**< rear center */
232     SND_CHMAP_FLC,      /**< front left center */
233     SND_CHMAP_FRC,      /**< front right center */
234     SND_CHMAP_RLC,      /**< rear left center */
235     SND_CHMAP_RRC,      /**< rear right center */
236     SND_CHMAP_FLW,      /**< front left wide */
237     SND_CHMAP_FRW,      /**< front right wide */
238     SND_CHMAP_FLH,      /**< front left high */
239     SND_CHMAP_FCH,      /**< front center high */
240     SND_CHMAP_FRH,      /**< front right high */
241     SND_CHMAP_TC,       /**< top center */
242     SND_CHMAP_TFL,      /**< top front left */
243     SND_CHMAP_TFR,      /**< top front right */
244     SND_CHMAP_TFC,      /**< top front center */
245     SND_CHMAP_TRL,      /**< top rear left */
246     SND_CHMAP_TRR,      /**< top rear right */
247     SND_CHMAP_TRC,      /**< top rear center */
248     SND_CHMAP_TFLC,     /**< top front left center */
249     SND_CHMAP_TFRC,     /**< top front right center */
250     SND_CHMAP_TSL,      /**< top side left */
251     SND_CHMAP_TSR,      /**< top side right */
252     SND_CHMAP_LLFE,     /**< left LFE */
253     SND_CHMAP_RLFE,     /**< right LFE */
254     SND_CHMAP_BC,       /**< bottom center */
255     SND_CHMAP_BLC,      /**< bottom left center */
256     SND_CHMAP_BRC,      /**< bottom right center */
257     SND_CHMAP_LAST = SND_CHMAP_BRC,
258 };
259 
260 /** channel map list type */
261 enum snd_pcm_chmap_type {
262     SND_CHMAP_TYPE_NONE = 0,/**< unspecified channel position */
263     SND_CHMAP_TYPE_FIXED,   /**< fixed channel position */
264     SND_CHMAP_TYPE_VAR, /**< freely swappable channel position */
265     SND_CHMAP_TYPE_PAIRED,  /**< pair-wise swappable channel position */
266     SND_CHMAP_TYPE_LAST = SND_CHMAP_TYPE_PAIRED, /**< last entry */
267 };
268 
269 /** the channel map header */
270 typedef struct snd_pcm_chmap {
271     unsigned int channels;  /**< number of channels */
272     unsigned int pos[0];    /**< channel position array */
273 } snd_pcm_chmap_t;
274 
275 /** the header of array items returned from snd_pcm_query_chmaps() */
276 typedef struct snd_pcm_chmap_query {
277     enum snd_pcm_chmap_type type;   /**< channel map type */
278     snd_pcm_chmap_t map;        /**< available channel map */
279 } snd_pcm_chmap_query_t;
280 
281 snd_pcm_chmap_query_t **snd_pcm_query_chmaps(snd_pcm_t *pcm);
282 void snd_pcm_free_chmaps(snd_pcm_chmap_query_t **maps);
283 snd_pcm_chmap_t *snd_pcm_get_chmap(snd_pcm_t *pcm);
284 int snd_pcm_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
285 
286 /* for pthread mutex lock */
287 typedef hal_mutex_t snd_pcm_mutex_t;
288 snd_pcm_mutex_t snd_thread_mutex_init(void);
289 int snd_thread_mutex_lock_timeout(snd_pcm_mutex_t mutex, long ms);
290 int snd_thread_mutex_lock(snd_pcm_mutex_t mutex);
291 int snd_thread_mutex_unlock(snd_pcm_mutex_t mutex);
292 void snd_thread_mutex_destroy(snd_pcm_mutex_t mutex);
293 
294 size_t snd_pcm_hw_params_sizeof(void);
295 size_t snd_pcm_sw_params_sizeof(void);
296 
297 #define __snd_alloca(ptr,type) do { *ptr = (type##_t *) alloca(type##_sizeof()); memset(*ptr, 0, type##_sizeof()); } while (0)
298 #define snd_pcm_hw_params_alloca(ptr) __snd_alloca(ptr, snd_pcm_hw_params)
299 
300 int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
301 
302 int snd_pcm_hw_params_set_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t val);
303 int snd_pcm_hw_params_get_format(const snd_pcm_hw_params_t *params, snd_pcm_format_t *format);
304 
305 int snd_pcm_hw_params_set_channels(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val);
306 int snd_pcm_hw_params_get_channels(const snd_pcm_hw_params_t *params, unsigned int *val);
307 
308 int snd_pcm_hw_params_set_rate(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int dir);
309 int snd_pcm_hw_params_get_rate(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
310 
311 int snd_pcm_hw_params_set_period_time(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int us, int dir);
312 int snd_pcm_hw_params_set_period_time_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
313 int snd_pcm_hw_params_get_period_time(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
314 
315 int snd_pcm_hw_params_set_period_size(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t val, int dir);
316 int snd_pcm_hw_params_set_period_size_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir);
317 int snd_pcm_hw_params_get_period_size(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir);
318 
319 int snd_pcm_hw_params_set_periods(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int dir);
320 int snd_pcm_hw_params_set_periods_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
321 int snd_pcm_hw_params_get_periods(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
322 
323 int snd_pcm_hw_params_set_buffer_size(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t val);
324 int snd_pcm_hw_params_set_buffer_size_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val);
325 int snd_pcm_hw_params_get_buffer_size(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val);
326 
327 int snd_pcm_hw_params_set_buffer_time(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int us);
328 int snd_pcm_hw_params_set_buffer_time_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
329 
330 int snd_pcm_hw_params_set_access(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t access);
331 int snd_pcm_hw_params_get_access(const snd_pcm_hw_params_t *params, snd_pcm_access_t *access);
332 
333 #define snd_pcm_sw_params_alloca(ptr) __snd_alloca(ptr, snd_pcm_sw_params)
334 
335 int snd_pcm_sw_params_current(snd_pcm_t *pcm, snd_pcm_sw_params_t *params);
336 int snd_pcm_sw_params_set_start_threshold(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val);
337 int snd_pcm_sw_params_get_start_threshold(snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val);
338 int snd_pcm_sw_params_set_stop_threshold(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val);
339 int snd_pcm_sw_params_get_stop_threshold(snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val);
340 int snd_pcm_sw_params_set_silence_size(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val);
341 int snd_pcm_sw_params_get_silence_size(snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val);
342 int snd_pcm_sw_params_set_avail_min(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val);
343 int snd_pcm_sw_params_get_avail_min(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val);
344 int snd_pcm_sw_params_get_boundary(const snd_pcm_sw_params_t *params, snd_pcm_uframes_t *val);
345 int snd_pcm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params);
346 
347 
348 ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples);
349 snd_pcm_sframes_t snd_pcm_bytes_to_frames(snd_pcm_t *pcm, ssize_t bytes);
350 ssize_t snd_pcm_frames_to_bytes(snd_pcm_t *pcm, snd_pcm_sframes_t frames);
351 
352 snd_pcm_type_t snd_pcm_type(snd_pcm_t *pcm);
353 
354 const char *snd_pcm_type_name(snd_pcm_type_t type);
355 const char *snd_pcm_stream_name(snd_pcm_stream_t stream);
356 const char *snd_pcm_access_name(const snd_pcm_access_t _access);
357 const char *snd_pcm_format_name(const snd_pcm_format_t format);
358 const char *snd_pcm_state_name(const snd_pcm_state_t state);
359 
360 /* Direct Access (MMAP) functions */
361 int snd_pcm_mmap_begin(snd_pcm_t *pcm,
362                const snd_pcm_channel_area_t **areas,
363                snd_pcm_uframes_t *offset,
364                snd_pcm_uframes_t *frames);
365 snd_pcm_sframes_t snd_pcm_mmap_commit(snd_pcm_t *pcm,
366                       snd_pcm_uframes_t offset,
367                       snd_pcm_uframes_t frames);
368 snd_pcm_sframes_t snd_pcm_mmap_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size);
369 snd_pcm_sframes_t snd_pcm_mmap_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size);
370 
371 int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_channel, snd_pcm_uframes_t dst_offset,
372              unsigned int samples, snd_pcm_format_t format);
373 int snd_pcm_areas_silence(const snd_pcm_channel_area_t *dst_channels, snd_pcm_uframes_t dst_offset,
374               unsigned int channels, snd_pcm_uframes_t frames, snd_pcm_format_t format);
375 int snd_pcm_area_copy(const snd_pcm_channel_area_t *dst_channel, snd_pcm_uframes_t dst_offset,
376               const snd_pcm_channel_area_t *src_channel, snd_pcm_uframes_t src_offset,
377               unsigned int samples, snd_pcm_format_t format);
378 int snd_pcm_areas_copy(const snd_pcm_channel_area_t *dst_channels, snd_pcm_uframes_t dst_offset,
379                const snd_pcm_channel_area_t *src_channels, snd_pcm_uframes_t src_offset,
380                unsigned int channels, snd_pcm_uframes_t frames, snd_pcm_format_t format);
381 
382 #ifdef __cplusplus
383 }
384 #endif
385 
386 #endif /* __AW_ALSA_PCM_H */
387