]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/sound/pcm/channel.h
This commit was generated by cvs2svn to compensate for changes in r170256,
[FreeBSD/FreeBSD.git] / sys / dev / sound / pcm / channel.h
1 /*-
2  * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 struct pcmchan_caps {
30         u_int32_t minspeed, maxspeed;
31         u_int32_t *fmtlist;
32         u_int32_t caps;
33 };
34
35 /* Forward declarations */
36 struct pcm_channel;
37 struct pcmchan_syncgroup;
38 struct pcmchan_syncmember;
39
40 extern struct mtx snd_pcm_syncgroups_mtx;
41 extern SLIST_HEAD(pcm_synclist, pcmchan_syncgroup) snd_pcm_syncgroups;
42
43 #define PCM_SG_LOCK()       mtx_lock(&snd_pcm_syncgroups_mtx)
44 #define PCM_SG_TRYLOCK()    mtx_trylock(&snd_pcm_syncgroups_mtx)
45 #define PCM_SG_UNLOCK()     mtx_unlock(&snd_pcm_syncgroups_mtx)
46 #define PCM_SG_LOCKASSERT(arg)  mtx_assert(&snd_pcm_syncgroups_mtx, arg)
47
48 /**
49  * @brief Specifies an audio device sync group
50  */
51 struct pcmchan_syncgroup {
52         SLIST_ENTRY(pcmchan_syncgroup) link;
53         SLIST_HEAD(, pcmchan_syncmember) members;
54         int id; /**< Group identifier; set to address of group. */
55 };
56
57 /**
58  * @brief Specifies a container for members of a sync group
59  */
60 struct pcmchan_syncmember {
61         SLIST_ENTRY(pcmchan_syncmember) link;
62         struct pcmchan_syncgroup *parent; /**< group head */
63         struct pcm_channel *ch;
64 };
65
66 #define CHN_NAMELEN     32
67 struct pcm_channel {
68         kobj_t methods;
69
70         pid_t pid;
71         int refcount;
72         struct pcm_feeder *feeder;
73         u_int32_t align;
74
75         int volume;
76         int latency;
77         u_int32_t speed;
78         u_int32_t format;
79         u_int32_t flags;
80         u_int32_t feederflags;
81         u_int32_t blocks;
82
83         int direction;
84         unsigned int interrupts, xruns, feedcount;
85         unsigned int timeout;
86         struct snd_dbuf *bufhard, *bufsoft;
87         struct snddev_info *parentsnddev;
88         struct pcm_channel *parentchannel;
89         void *devinfo;
90         device_t dev;
91         int unit;
92         char name[CHN_NAMELEN];
93         struct mtx *lock;
94         int trigger;
95         /**
96          * Increment,decrement this around operations that temporarily yield
97          * lock.
98          */
99         unsigned int inprog;
100         /**
101          * Special channel operations should examine @c inprog after acquiring
102          * lock.  If zero, operations may continue.  Else, thread should
103          * wait on this cv for previous operation to finish.
104          */
105         struct cv cv;
106         /**
107          * Low water mark for select()/poll().
108          *
109          * This is initialized to the channel's fragment size, and will be
110          * overwritten if a new fragment size is set.  Users may alter this
111          * value directly with the @c SNDCTL_DSP_LOW_WATER ioctl.
112          */
113         unsigned int lw;
114         /**
115          * If part of a sync group, this will point to the syncmember
116          * container.
117          */
118         struct pcmchan_syncmember *sm;
119 #ifdef OSSV4_EXPERIMENT
120         u_int16_t lpeak, rpeak; /**< Peak value from 0-32767. */
121 #endif
122
123         struct {
124                 SLIST_HEAD(, pcm_channel) head;
125                 SLIST_ENTRY(pcm_channel) link;
126                 struct {
127                         SLIST_HEAD(, pcm_channel) head;
128                         SLIST_ENTRY(pcm_channel) link;
129                 } busy;
130         } children;
131
132         struct {
133                 struct {
134                         SLIST_ENTRY(pcm_channel) link;
135                         struct {
136                                 SLIST_ENTRY(pcm_channel) link;
137                         } busy;
138                 } pcm;
139         } channels;
140
141         void *data1, *data2;
142 };
143
144 #define CHN_HEAD(x, y)                  &(x)->y.head
145 #define CHN_INIT(x, y)                  SLIST_INIT(CHN_HEAD(x, y))
146 #define CHN_LINK(y)                     y.link
147 #define CHN_EMPTY(x, y)                 SLIST_EMPTY(CHN_HEAD(x, y))
148 #define CHN_FIRST(x, y)                 SLIST_FIRST(CHN_HEAD(x, y))
149
150 #define CHN_FOREACH(x, y, z)                                            \
151         SLIST_FOREACH(x, CHN_HEAD(y, z), CHN_LINK(z))
152
153 #define CHN_FOREACH_SAFE(w, x, y, z)                                    \
154         SLIST_FOREACH_SAFE(w, CHN_HEAD(x, z), CHN_LINK(z), y)
155
156 #define CHN_INSERT_HEAD(x, y, z)                                        \
157         SLIST_INSERT_HEAD(CHN_HEAD(x, z), y, CHN_LINK(z))
158
159 #define CHN_INSERT_AFTER(x, y, z)                                       \
160         SLIST_INSERT_AFTER(x, y, CHN_LINK(z))
161
162 #define CHN_REMOVE(x, y, z)                                             \
163         SLIST_REMOVE(CHN_HEAD(x, z), y, pcm_channel, CHN_LINK(z))
164
165 #define CHN_INSERT_HEAD_SAFE(x, y, z)           do {                    \
166         struct pcm_channel *t = NULL;                                   \
167         CHN_FOREACH(t, x, z) {                                          \
168                 if (t == y)                                             \
169                         break;                                          \
170         }                                                               \
171         if (t != y) {                                                   \
172                 CHN_INSERT_HEAD(x, y, z);                               \
173         }                                                               \
174 } while(0)
175
176 #define CHN_INSERT_AFTER_SAFE(w, x, y, z)       do {                    \
177         struct pcm_channel *t = NULL;                                   \
178         CHN_FOREACH(t, w, z) {                                          \
179                 if (t == y)                                             \
180                         break;                                          \
181         }                                                               \
182         if (t != y) {                                                   \
183                 CHN_INSERT_AFTER(x, y, z);                              \
184         }                                                               \
185 } while(0)
186
187 #define CHN_REMOVE_SAFE(x, y, z)                do {                    \
188         struct pcm_channel *t = NULL;                                   \
189         CHN_FOREACH(t, x, z) {                                          \
190                 if (t == y)                                             \
191                         break;                                          \
192         }                                                               \
193         if (t == y) {                                                   \
194                 CHN_REMOVE(x, y, z);                                    \
195         }                                                               \
196 } while(0)
197
198 #define CHN_UNIT(x)     (snd_unit2u((x)->unit))
199 #define CHN_DEV(x)      (snd_unit2d((x)->unit))
200 #define CHN_CHAN(x)     (snd_unit2c((x)->unit))
201
202 #include "channel_if.h"
203
204 int chn_reinit(struct pcm_channel *c);
205 int chn_write(struct pcm_channel *c, struct uio *buf);
206 int chn_read(struct pcm_channel *c, struct uio *buf);
207 u_int32_t chn_start(struct pcm_channel *c, int force);
208 int chn_sync(struct pcm_channel *c, int threshold);
209 int chn_flush(struct pcm_channel *c);
210 int chn_poll(struct pcm_channel *c, int ev, struct thread *td);
211
212 int chn_init(struct pcm_channel *c, void *devinfo, int dir, int direction);
213 int chn_kill(struct pcm_channel *c);
214 int chn_setdir(struct pcm_channel *c, int dir);
215 int chn_reset(struct pcm_channel *c, u_int32_t fmt);
216 int chn_setvolume(struct pcm_channel *c, int left, int right);
217 int chn_setspeed(struct pcm_channel *c, int speed);
218 int chn_setformat(struct pcm_channel *c, u_int32_t fmt);
219 int chn_setblocksize(struct pcm_channel *c, int blkcnt, int blksz);
220 int chn_setlatency(struct pcm_channel *c, int latency);
221 int chn_trigger(struct pcm_channel *c, int go);
222 int chn_getptr(struct pcm_channel *c);
223 struct pcmchan_caps *chn_getcaps(struct pcm_channel *c);
224 u_int32_t chn_getformats(struct pcm_channel *c);
225
226 void chn_resetbuf(struct pcm_channel *c);
227 void chn_intr(struct pcm_channel *c);
228 int chn_wrfeed(struct pcm_channel *c);
229 int chn_rdfeed(struct pcm_channel *c);
230 int chn_abort(struct pcm_channel *c);
231
232 void chn_wrupdate(struct pcm_channel *c);
233 void chn_rdupdate(struct pcm_channel *c);
234
235 int chn_notify(struct pcm_channel *c, u_int32_t flags);
236 void chn_lock(struct pcm_channel *c);
237 void chn_unlock(struct pcm_channel *c);
238
239 int chn_getrates(struct pcm_channel *c, int **rates);
240 int chn_syncdestroy(struct pcm_channel *c);
241
242 #ifdef OSSV4_EXPERIMENT
243 int chn_getpeaks(struct pcm_channel *c, int *lpeak, int *rpeak);
244 #endif
245
246 #ifdef  USING_MUTEX
247 #define CHN_LOCK(c) mtx_lock((struct mtx *)((c)->lock))
248 #define CHN_UNLOCK(c) mtx_unlock((struct mtx *)((c)->lock))
249 #define CHN_TRYLOCK(c) mtx_trylock((struct mtx *)((c)->lock))
250 #define CHN_LOCKASSERT(c) mtx_assert((struct mtx *)((c)->lock), MA_OWNED)
251 #else
252 #define CHN_LOCK(c)
253 #define CHN_UNLOCK(c)
254 #define CHN_TRYLOCK(c)
255 #define CHN_LOCKASSERT(c)
256 #endif
257
258 int fmtvalid(u_int32_t fmt, u_int32_t *fmtlist);
259
260 #define AFMTSTR_NONE            0 /* "s16le" */
261 #define AFMTSTR_SIMPLE          1 /* "s16le:s" */
262 #define AFMTSTR_NUM             2 /* "s16le:2" */
263 #define AFMTSTR_FULL            3 /* "s16le:stereo" */
264
265 #define AFMTSTR_MAXSZ           13 /* include null terminator */
266
267 #define AFMTSTR_MONO_RETURN     0
268 #define AFMTSTR_STEREO_RETURN   1
269
270 struct afmtstr_table {
271         char *fmtstr;
272         u_int32_t format;
273 };
274
275 int afmtstr_swap_sign(char *);
276 int afmtstr_swap_endian(char *);
277 u_int32_t afmtstr2afmt(struct afmtstr_table *, const char *, int);
278 u_int32_t afmt2afmtstr(struct afmtstr_table *, u_int32_t, char *, size_t, int, int);
279
280 extern int chn_latency;
281 extern int chn_latency_profile;
282 extern int report_soft_formats;
283
284 #define PCMDIR_PLAY             1
285 #define PCMDIR_PLAY_VIRTUAL     2
286 #define PCMDIR_REC              -1
287 #define PCMDIR_REC_VIRTUAL      -2
288
289 #define PCMTRIG_START 1
290 #define PCMTRIG_EMLDMAWR 2
291 #define PCMTRIG_EMLDMARD 3
292 #define PCMTRIG_STOP 0
293 #define PCMTRIG_ABORT -1
294
295 #define CHN_F_CLOSING           0x00000004  /* a pending close */
296 #define CHN_F_ABORTING          0x00000008  /* a pending abort */
297 #define CHN_F_RUNNING           0x00000010  /* dma is running */
298 #define CHN_F_TRIGGERED         0x00000020
299 #define CHN_F_NOTRIGGER         0x00000040
300 #define CHN_F_SLEEPING          0x00000080
301
302 #define CHN_F_BUSY              0x00001000  /* has been opened  */
303 #define CHN_F_HAS_SIZE          0x00002000  /* user set block size */
304 #define CHN_F_NBIO              0x00004000  /* do non-blocking i/o */
305 #define CHN_F_MAPPED            0x00010000  /* has been mmap()ed */
306 #define CHN_F_DEAD              0x00020000
307 #define CHN_F_BADSETTING        0x00040000
308 #define CHN_F_SETBLOCKSIZE      0x00080000
309 #define CHN_F_HAS_VCHAN         0x00100000
310
311 #define CHN_F_VIRTUAL           0x10000000  /* not backed by hardware */
312
313 #define CHN_F_RESET             (CHN_F_BUSY | CHN_F_DEAD | \
314                                         CHN_F_HAS_VCHAN | CHN_F_VIRTUAL)
315                                         
316
317 #define CHN_N_RATE              0x00000001
318 #define CHN_N_FORMAT            0x00000002
319 #define CHN_N_VOLUME            0x00000004
320 #define CHN_N_BLOCKSIZE         0x00000008
321 #define CHN_N_TRIGGER           0x00000010
322
323 #define CHN_LATENCY_MIN         0
324 #define CHN_LATENCY_MAX         10
325 #define CHN_LATENCY_DEFAULT     5
326 #define CHN_POLICY_MIN          CHN_LATENCY_MIN
327 #define CHN_POLICY_MAX          CHN_LATENCY_MAX
328 #define CHN_POLICY_DEFAULT      CHN_LATENCY_DEFAULT
329
330 #define CHN_LATENCY_PROFILE_MIN         0
331 #define CHN_LATENCY_PROFILE_MAX         1
332 #define CHN_LATENCY_PROFILE_DEFAULT     CHN_LATENCY_PROFILE_MAX
333
334 /*
335  * This should be large enough to hold all pcm data between
336  * tsleeps in chn_{read,write} at the highest sample rate.
337  * (which is usually 48kHz * 16bit * stereo = 192000 bytes/sec)
338  */
339 #define CHN_2NDBUFBLKSIZE       (2 * 1024)
340 /* The total number of blocks per secondary bufhard. */
341 #define CHN_2NDBUFBLKNUM        (32)
342 /* The size of a whole secondary bufhard. */
343 #define CHN_2NDBUFMAXSIZE       (131072)
344
345 #define CHANNEL_DECLARE(name) static DEFINE_CLASS(name, name ## _methods, sizeof(struct kobj))