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