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_DIRECT_H
33 #define __AW_ALSA_PCM_DIRECT_H
34
35 #include <aw-alsa-lib/pcm.h>
36 #include <aw-alsa-lib/plugin/pcm_direct_config.h>
37 #include <semaphore.h>
38
39 #define DIRECT_IPC_SEMS 1
40 #define DIRECT_IPC_SEM_CLIENT 0
41
42 typedef void (mix_areas_t)(unsigned int size,
43 volatile void *dst, void *src,
44 volatile signed int *sum, size_t dst_step,
45 size_t src_step, size_t sum_step);
46
47 typedef void (mix_areas_16_t)(unsigned int size,
48 volatile signed short *dst, signed short *src,
49 volatile signed int *sum, size_t dst_step,
50 size_t src_step, size_t sum_step);
51
52 typedef void (mix_areas_32_t)(unsigned int size,
53 volatile signed int *dst, signed int *src,
54 volatile signed int *sum, size_t dst_step,
55 size_t src_step, size_t sum_step);
56
57 typedef void (mix_areas_24_t)(unsigned int size,
58 volatile unsigned char *dst, unsigned char *src,
59 volatile signed int *sum, size_t dst_step,
60 size_t src_step, size_t sum_step);
61
62 typedef void (mix_areas_u8_t)(unsigned int size,
63 volatile unsigned char *dst, unsigned char *src,
64 volatile signed int *sum, size_t dst_step,
65 size_t src_step, size_t sum_step);
66
67 typedef struct snd_pcm_direct snd_pcm_direct_t;
68
69 /* shared among direct plugin clients - be careful to be 32/64bit compatible! */
70 typedef struct {
71 unsigned int magic; /* magic number */
72 snd_pcm_type_t type; /* PCM type (currently only hw) */
73 struct {
74 snd_pcm_format_t format;
75 snd_interval_t rate;
76 snd_interval_t period_size;
77 snd_interval_t period_time;
78 snd_interval_t periods;
79 snd_interval_t buffer_size;
80 snd_interval_t buffer_time;
81 } hw;
82 struct {
83 /* copied to slave PCMs */
84 snd_pcm_access_t access;
85 snd_pcm_format_t format;
86 unsigned int channels;
87 unsigned int rate;
88 unsigned int period_size;
89 unsigned int period_time;
90 unsigned int periods;
91
92 unsigned int avail_min;
93 unsigned int start_threshold;
94 unsigned int stop_threshold;
95 unsigned int silence_threshold;
96 unsigned int silence_size;
97
98 unsigned int recoveries; /* no of executed recoveries on slave*/
99
100 unsigned long long boundary;
101
102 unsigned int info;
103 unsigned int msbits;
104 unsigned int rate_num;
105 unsigned int rate_den;
106 unsigned int hw_flags;
107 unsigned int fifo_size;
108 unsigned int buffer_size;
109 unsigned int buffer_time;
110
111 unsigned int sample_bits;
112 unsigned int frame_bits;
113 } s;
114 union {
115 struct {
116 unsigned long long chn_mask;
117 } dshare;
118 } u;
119 } snd_pcm_direct_share_t;
120
121 struct snd_pcm_direct {
122 snd_pcm_type_t type;
123 key_t ipc_key;
124
125 sem_t *semid;
126 int poll_index;
127
128 int locked[DIRECT_IPC_SEMS];
129 snd_pcm_t *spcm;
130 snd_pcm_direct_share_t *shmptr;
131 snd_pcm_uframes_t appl_ptr;
132 snd_pcm_uframes_t last_appl_ptr;
133 snd_pcm_uframes_t hw_ptr;
134 snd_pcm_uframes_t avail_max;
135 snd_pcm_uframes_t slave_appl_ptr;
136 snd_pcm_uframes_t slave_hw_ptr;
137 snd_pcm_uframes_t slave_period_size;
138 snd_pcm_uframes_t slave_buffer_size;
139 snd_pcm_uframes_t slave_boundary;
140
141 int (*sync_ptr)(snd_pcm_t *pcm);
142
143 snd_pcm_state_t state;
144
145 int interleaved;
146 int slowptr;
147 int max_periods; /* max periods (-1 = fixed periods, 0 = max buffer size) */
148 int var_periodsize; /* allow variable period size if max_periods is != -1*/
149
150 unsigned int channels;
151 unsigned int *bindings;
152 unsigned int recoveries; /* mirror of executed recoveries on slave */
153
154 union {
155 struct {
156 int shmid_sum; /* IPC global sum ring buffer memory identification */
157 int *shm_sum_id; /* IPC global sum ring buffer memory identification */
158 signed int *sum_buffer; /* shared sum buffer */
159 mix_areas_16_t *mix_areas_16;
160 mix_areas_32_t *mix_areas_32;
161 mix_areas_24_t *mix_areas_24;
162 mix_areas_u8_t *mix_areas_u8;
163 mix_areas_16_t *remix_areas_16;
164 mix_areas_32_t *remix_areas_32;
165 mix_areas_24_t *remix_areas_24;
166 mix_areas_u8_t *remix_areas_u8;
167 } dmix;
168 struct {
169 } dsnoop;
170 struct {
171 unsigned long long chn_mask;
172 } dshare;
173 } u;
174 };
175
176 struct slave_params {
177 snd_pcm_format_t format;
178 int rate;
179 int channels;
180 int period_time;
181 int buffer_time;
182 snd_pcm_sframes_t period_size;
183 snd_pcm_sframes_t buffer_size;
184 unsigned int periods;
185 };
186
snd_pcm_direct_semaphore_down(snd_pcm_direct_t * dmix,int sem_num)187 static inline int snd_pcm_direct_semaphore_down(snd_pcm_direct_t *dmix, int sem_num)
188 {
189 int ret;
190
191 ret = sem_wait(dmix->semid);
192 if (ret != 0) {
193 awalsa_err("sem_wait failed, ret=%d\n", ret);
194 return -1;
195 }
196 dmix->locked[sem_num]++;
197
198 return ret;
199 }
200
snd_pcm_direct_semaphore_up(snd_pcm_direct_t * dmix,int sem_num)201 static inline int snd_pcm_direct_semaphore_up(snd_pcm_direct_t *dmix, int sem_num)
202 {
203 int ret;
204
205 ret = sem_post(dmix->semid);
206 if (ret != 0) {
207 awalsa_err("sem_post failed, ret=%d\n", ret);
208 return -1;
209 }
210
211 dmix->locked[sem_num]--;
212
213 return ret;
214 }
215
216
217 int snd_pcm_slave_conf_hw_params(const snd_pcm_direct_slave_config_t *conf, struct slave_params *params);
218
219 int snd_pcm_direct_semaphore_shm_create_or_connect(snd_pcm_direct_t *dmix);
220 int snd_pcm_direct_semaphore_shm_discard(snd_pcm_direct_t *dmix);
221
222 int snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, struct slave_params *params);
223 int snd_pcm_direct_initialize_secondary_slave(snd_pcm_direct_t *dmix,
224 snd_pcm_t *spcm,
225 struct slave_params *params);
226
227 int snd_pcm_direct_last_pcm(snd_pcm_direct_t *dmix);
228
229 int snd_pcm_direct_check_interleave(snd_pcm_direct_t *dmix, snd_pcm_t *pcm);
230
231 int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
232 int snd_pcm_direct_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params);
233 int snd_pcm_direct_hw_free(snd_pcm_t *pcm);
234 int snd_pcm_direct_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params);
235 int snd_pcm_direct_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info);
236 int snd_pcm_direct_mmap(snd_pcm_t *pcm);
237 int snd_pcm_direct_munmap(snd_pcm_t *pcm);
238 int snd_pcm_direct_prepare(snd_pcm_t *pcm);
239
240 int snd_pcm_direct_slave_recover(snd_pcm_direct_t *direct);
241 int snd_pcm_direct_client_chk_xrun(snd_pcm_direct_t *direct, snd_pcm_t *pcm);
242 int snd_pcm_direct_wait(snd_pcm_t *pcm, int timeout);
243
244 /*TODO*/
245 int snd_pcm_hw_wait_with_index(snd_pcm_t *hw_pcm, int index, int timeout);
246 int snd_pcm_hw_poll_index_init(snd_pcm_t *hw_pcm);
247 int snd_pcm_hw_poll_index_release(snd_pcm_t *hw_pcm, int index);
248
249 int snd_pcm_direct_initialize_poll_index(snd_pcm_direct_t *dmix);
250 int snd_pcm_direct_destroy_poll_index(snd_pcm_direct_t *dmix);
251
252 int snd_pcm_direct_last_pcm_drop(snd_pcm_direct_t *dmix);
253 #endif /* __AW_ALSA_PCM_DIRECT_H */
254