xref: /netbsd/sys/dev/audio/audio_dai.h (revision b950503f)
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