audio_dai.h revision 1.2 1 1.2 isaki /* $NetBSD: audio_dai.h,v 1.2 2019/05/08 13:40:17 isaki Exp $ */
2 1.2 isaki
3 1.2 isaki /*-
4 1.2 isaki * Copyright (c) 2018 Jared McNeill <jmcneill (at) invisible.ca>
5 1.2 isaki * All rights reserved.
6 1.2 isaki *
7 1.2 isaki * Redistribution and use in source and binary forms, with or without
8 1.2 isaki * modification, are permitted provided that the following conditions
9 1.2 isaki * are met:
10 1.2 isaki * 1. Redistributions of source code must retain the above copyright
11 1.2 isaki * notice, this list of conditions and the following disclaimer.
12 1.2 isaki * 2. Redistributions in binary form must reproduce the above copyright
13 1.2 isaki * notice, this list of conditions and the following disclaimer in the
14 1.2 isaki * documentation and/or other materials provided with the distribution.
15 1.2 isaki *
16 1.2 isaki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 1.2 isaki * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 1.2 isaki * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 1.2 isaki * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 1.2 isaki * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 1.2 isaki * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 1.2 isaki * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 1.2 isaki * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 1.2 isaki * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 1.2 isaki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 1.2 isaki * SUCH DAMAGE.
27 1.2 isaki */
28 1.2 isaki
29 1.2 isaki #ifndef _DEV_AUDIO_AUDIO_DAI_H
30 1.2 isaki #define _DEV_AUDIO_AUDIO_DAI_H
31 1.2 isaki
32 1.2 isaki #include <sys/errno.h>
33 1.2 isaki #include <dev/audio/audio_if.h>
34 1.2 isaki
35 1.2 isaki #define AUDIO_DAI_FORMAT_MASK __BITS(3,0)
36 1.2 isaki #define AUDIO_DAI_FORMAT_I2S 0
37 1.2 isaki #define AUDIO_DAI_FORMAT_RJ 1
38 1.2 isaki #define AUDIO_DAI_FORMAT_LJ 2
39 1.2 isaki #define AUDIO_DAI_FORMAT_DSPA 3
40 1.2 isaki #define AUDIO_DAI_FORMAT_DSPB 4
41 1.2 isaki #define AUDIO_DAI_FORMAT_AC97 5
42 1.2 isaki #define AUDIO_DAI_FORMAT_PDM 6
43 1.2 isaki
44 1.2 isaki #define AUDIO_DAI_POLARITY_MASK __BITS(5,4)
45 1.2 isaki #define AUDIO_DAI_POLARITY_NB_NF 0
46 1.2 isaki #define AUDIO_DAI_POLARITY_NB_IF 1
47 1.2 isaki #define AUDIO_DAI_POLARITY_IB_NF 2
48 1.2 isaki #define AUDIO_DAI_POLARITY_IB_IF 3
49 1.2 isaki #define AUDIO_DAI_POLARITY_F(n) (((n) & 0x1) != 0)
50 1.2 isaki #define AUDIO_DAI_POLARITY_B(n) (((n) & 0x2) != 0)
51 1.2 isaki
52 1.2 isaki #define AUDIO_DAI_CLOCK_MASK __BITS(9,8)
53 1.2 isaki #define AUDIO_DAI_CLOCK_CBM_CFM 0
54 1.2 isaki #define AUDIO_DAI_CLOCK_CBS_CFM 1
55 1.2 isaki #define AUDIO_DAI_CLOCK_CBM_CFS 2
56 1.2 isaki #define AUDIO_DAI_CLOCK_CBS_CFS 3
57 1.2 isaki
58 1.2 isaki #define AUDIO_DAI_CLOCK_IN 0
59 1.2 isaki #define AUDIO_DAI_CLOCK_OUT 1
60 1.2 isaki
61 1.2 isaki #define AUDIO_DAI_JACK_HP 0
62 1.2 isaki #define AUDIO_DAI_JACK_MIC 1
63 1.2 isaki
64 1.2 isaki typedef struct audio_dai_device {
65 1.2 isaki int (*dai_set_sysclk)(struct audio_dai_device *, u_int, int);
66 1.2 isaki int (*dai_set_format)(struct audio_dai_device *, u_int);
67 1.2 isaki int (*dai_add_device)(struct audio_dai_device *, struct audio_dai_device *);
68 1.2 isaki int (*dai_jack_detect)(struct audio_dai_device *, u_int, int);
69 1.2 isaki
70 1.2 isaki const struct audio_hw_if *dai_hw_if; /* audio driver callbacks */
71 1.2 isaki
72 1.2 isaki device_t dai_dev; /* device */
73 1.2 isaki void *dai_priv; /* driver private data */
74 1.2 isaki } *audio_dai_tag_t;
75 1.2 isaki
76 1.2 isaki static inline device_t
77 1.2 isaki audio_dai_device(audio_dai_tag_t dai)
78 1.2 isaki {
79 1.2 isaki return dai->dai_dev;
80 1.2 isaki }
81 1.2 isaki
82 1.2 isaki static inline void *
83 1.2 isaki audio_dai_private(audio_dai_tag_t dai)
84 1.2 isaki {
85 1.2 isaki return dai->dai_priv;
86 1.2 isaki }
87 1.2 isaki
88 1.2 isaki static inline int
89 1.2 isaki audio_dai_set_sysclk(audio_dai_tag_t dai, u_int rate, int dir)
90 1.2 isaki {
91 1.2 isaki if (!dai->dai_set_sysclk)
92 1.2 isaki return 0;
93 1.2 isaki
94 1.2 isaki return dai->dai_set_sysclk(dai, rate, dir);
95 1.2 isaki }
96 1.2 isaki
97 1.2 isaki static inline int
98 1.2 isaki audio_dai_set_format(audio_dai_tag_t dai, u_int format)
99 1.2 isaki {
100 1.2 isaki if (!dai->dai_set_format)
101 1.2 isaki return 0;
102 1.2 isaki
103 1.2 isaki return dai->dai_set_format(dai, format);
104 1.2 isaki }
105 1.2 isaki
106 1.2 isaki static inline int
107 1.2 isaki audio_dai_add_device(audio_dai_tag_t dai, audio_dai_tag_t aux)
108 1.2 isaki {
109 1.2 isaki if (!dai->dai_add_device)
110 1.2 isaki return 0;
111 1.2 isaki
112 1.2 isaki return dai->dai_add_device(dai, aux);
113 1.2 isaki }
114 1.2 isaki
115 1.2 isaki static inline int
116 1.2 isaki audio_dai_jack_detect(audio_dai_tag_t dai, u_int jack, bool present)
117 1.2 isaki {
118 1.2 isaki if (!dai->dai_jack_detect)
119 1.2 isaki return 0;
120 1.2 isaki
121 1.2 isaki return dai->dai_jack_detect(dai, jack, present);
122 1.2 isaki }
123 1.2 isaki
124 1.2 isaki static inline int
125 1.2 isaki audio_dai_open(audio_dai_tag_t dai, int flags)
126 1.2 isaki {
127 1.2 isaki if (!dai->dai_hw_if->open)
128 1.2 isaki return 0;
129 1.2 isaki return dai->dai_hw_if->open(dai->dai_priv, flags);
130 1.2 isaki }
131 1.2 isaki
132 1.2 isaki static inline void
133 1.2 isaki audio_dai_close(audio_dai_tag_t dai)
134 1.2 isaki {
135 1.2 isaki if (!dai->dai_hw_if->close)
136 1.2 isaki return;
137 1.2 isaki dai->dai_hw_if->close(dai->dai_priv);
138 1.2 isaki }
139 1.2 isaki
140 1.2 isaki static inline int
141 1.2 isaki audio_dai_query_format(audio_dai_tag_t dai, audio_format_query_t *afp)
142 1.2 isaki {
143 1.2 isaki if (!dai->dai_hw_if->query_format)
144 1.2 isaki return 0;
145 1.2 isaki return dai->dai_hw_if->query_format(dai->dai_priv, afp);
146 1.2 isaki }
147 1.2 isaki
148 1.2 isaki static inline int
149 1.2 isaki audio_dai_mi_set_format(audio_dai_tag_t dai, int setmode,
150 1.2 isaki const audio_params_t *play, const audio_params_t *rec,
151 1.2 isaki audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
152 1.2 isaki {
153 1.2 isaki if (!dai->dai_hw_if->set_format)
154 1.2 isaki return 0;
155 1.2 isaki return dai->dai_hw_if->set_format(dai->dai_priv, setmode,
156 1.2 isaki play, rec, pfil, rfil);
157 1.2 isaki }
158 1.2 isaki
159 1.2 isaki static inline int
160 1.2 isaki audio_dai_round_blocksize(audio_dai_tag_t dai, int bs, int mode,
161 1.2 isaki const audio_params_t *params)
162 1.2 isaki {
163 1.2 isaki if (!dai->dai_hw_if->round_blocksize)
164 1.2 isaki return bs;
165 1.2 isaki return dai->dai_hw_if->round_blocksize(dai->dai_priv, bs,
166 1.2 isaki mode, params);
167 1.2 isaki }
168 1.2 isaki
169 1.2 isaki static inline int
170 1.2 isaki audio_dai_commit_settings(audio_dai_tag_t dai)
171 1.2 isaki {
172 1.2 isaki if (!dai->dai_hw_if->commit_settings)
173 1.2 isaki return 0;
174 1.2 isaki return dai->dai_hw_if->commit_settings(dai->dai_priv);
175 1.2 isaki }
176 1.2 isaki
177 1.2 isaki static inline int
178 1.2 isaki audio_dai_halt(audio_dai_tag_t dai, int dir)
179 1.2 isaki {
180 1.2 isaki switch (dir) {
181 1.2 isaki case AUMODE_PLAY:
182 1.2 isaki if (!dai->dai_hw_if->halt_output)
183 1.2 isaki return 0;
184 1.2 isaki return dai->dai_hw_if->halt_output(dai->dai_priv);
185 1.2 isaki case AUMODE_RECORD:
186 1.2 isaki if (!dai->dai_hw_if->halt_input)
187 1.2 isaki return 0;
188 1.2 isaki return dai->dai_hw_if->halt_input(dai->dai_priv);
189 1.2 isaki default:
190 1.2 isaki return EINVAL;
191 1.2 isaki }
192 1.2 isaki }
193 1.2 isaki
194 1.2 isaki static inline int
195 1.2 isaki audio_dai_trigger(audio_dai_tag_t dai, void *start, void *end, int blksize,
196 1.2 isaki void (*intr)(void *), void *intrarg, const audio_params_t *params,
197 1.2 isaki int dir)
198 1.2 isaki {
199 1.2 isaki switch (dir) {
200 1.2 isaki case AUMODE_PLAY:
201 1.2 isaki if (!dai->dai_hw_if->trigger_output)
202 1.2 isaki return 0;
203 1.2 isaki return dai->dai_hw_if->trigger_output(dai->dai_priv, start,
204 1.2 isaki end, blksize, intr, intrarg, params);
205 1.2 isaki case AUMODE_RECORD:
206 1.2 isaki if (!dai->dai_hw_if->trigger_input)
207 1.2 isaki return 0;
208 1.2 isaki return dai->dai_hw_if->trigger_input(dai->dai_priv, start,
209 1.2 isaki end, blksize, intr, intrarg, params);
210 1.2 isaki default:
211 1.2 isaki return EINVAL;
212 1.2 isaki }
213 1.2 isaki }
214 1.2 isaki
215 1.2 isaki static inline void *
216 1.2 isaki audio_dai_allocm(audio_dai_tag_t dai, int dir, size_t size)
217 1.2 isaki {
218 1.2 isaki if (!dai->dai_hw_if->allocm)
219 1.2 isaki return NULL;
220 1.2 isaki return dai->dai_hw_if->allocm(dai->dai_priv, dir, size);
221 1.2 isaki }
222 1.2 isaki
223 1.2 isaki static inline void
224 1.2 isaki audio_dai_freem(audio_dai_tag_t dai, void *addr, size_t size)
225 1.2 isaki {
226 1.2 isaki if (!dai->dai_hw_if->freem)
227 1.2 isaki return;
228 1.2 isaki dai->dai_hw_if->freem(dai->dai_priv, addr, size);
229 1.2 isaki }
230 1.2 isaki
231 1.2 isaki static inline size_t
232 1.2 isaki audio_dai_round_buffersize(audio_dai_tag_t dai, int dir, size_t bufsize)
233 1.2 isaki {
234 1.2 isaki if (!dai->dai_hw_if->round_buffersize)
235 1.2 isaki return bufsize;
236 1.2 isaki return dai->dai_hw_if->round_buffersize(dai->dai_priv, dir, bufsize);
237 1.2 isaki }
238 1.2 isaki
239 1.2 isaki static inline int
240 1.2 isaki audio_dai_get_props(audio_dai_tag_t dai)
241 1.2 isaki {
242 1.2 isaki if (!dai->dai_hw_if->get_props)
243 1.2 isaki return 0;
244 1.2 isaki return dai->dai_hw_if->get_props(dai->dai_priv);
245 1.2 isaki }
246 1.2 isaki
247 1.2 isaki static inline int
248 1.2 isaki audio_dai_getdev(audio_dai_tag_t dai, struct audio_device *adev)
249 1.2 isaki {
250 1.2 isaki if (!dai->dai_hw_if->getdev)
251 1.2 isaki return ENXIO;
252 1.2 isaki return dai->dai_hw_if->getdev(dai->dai_priv, adev);
253 1.2 isaki }
254 1.2 isaki
255 1.2 isaki static inline int
256 1.2 isaki audio_dai_get_port(audio_dai_tag_t dai, mixer_ctrl_t *mc)
257 1.2 isaki {
258 1.2 isaki if (!dai->dai_hw_if->get_port)
259 1.2 isaki return ENXIO;
260 1.2 isaki return dai->dai_hw_if->get_port(dai->dai_priv, mc);
261 1.2 isaki }
262 1.2 isaki
263 1.2 isaki static inline int
264 1.2 isaki audio_dai_set_port(audio_dai_tag_t dai, mixer_ctrl_t *mc)
265 1.2 isaki {
266 1.2 isaki if (!dai->dai_hw_if->set_port)
267 1.2 isaki return ENXIO;
268 1.2 isaki return dai->dai_hw_if->set_port(dai->dai_priv, mc);
269 1.2 isaki }
270 1.2 isaki
271 1.2 isaki static inline int
272 1.2 isaki audio_dai_query_devinfo(audio_dai_tag_t dai, mixer_devinfo_t *di)
273 1.2 isaki {
274 1.2 isaki if (!dai->dai_hw_if->query_devinfo)
275 1.2 isaki return ENXIO;
276 1.2 isaki return dai->dai_hw_if->query_devinfo(dai->dai_priv, di);
277 1.2 isaki }
278 1.2 isaki
279 1.2 isaki static inline void
280 1.2 isaki audio_dai_get_locks(audio_dai_tag_t dai, kmutex_t **intr, kmutex_t **thread)
281 1.2 isaki {
282 1.2 isaki if (!dai->dai_hw_if->get_locks) {
283 1.2 isaki *intr = NULL;
284 1.2 isaki *thread = NULL;
285 1.2 isaki return;
286 1.2 isaki }
287 1.2 isaki
288 1.2 isaki dai->dai_hw_if->get_locks(dai->dai_priv, intr, thread);
289 1.2 isaki }
290 1.2 isaki
291 1.2 isaki #endif /* _DEV_AUDIO_AUDIO_DAI_H */
292