nrelease - fix/improve livecd
[dragonfly.git] / sys / dev / sound / pcm / channel.h
CommitLineData
558a398b 1/*-
2a1ad637
FT
2 * Copyright (c) 2005-2009 Ariff Abdullah <ariff@FreeBSD.org>
3 * Portions Copyright (c) Ryan Beasley <ryan.beasley@gmail.com> - GSoC 2006
4 * Copyright (c) 1999 Cameron Grant <cg@FreeBSD.org>
984263bc
MD
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 AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, 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 *
2a1ad637 28 * $FreeBSD: head/sys/dev/sound/pcm/channel.h 193979 2009-06-11 09:06:09Z ariff $
984263bc
MD
29 */
30
984263bc
MD
31struct pcmchan_caps {
32 u_int32_t minspeed, maxspeed;
33 u_int32_t *fmtlist;
34 u_int32_t caps;
35};
36
2a1ad637
FT
37struct pcmchan_matrix {
38 int id;
39 uint8_t channels, ext;
40 struct {
41 int type;
42 uint32_t members;
43 } map[SND_CHN_T_MAX + 1];
44 uint32_t mask;
45 int8_t offset[SND_CHN_T_MAX];
46};
47
48/* Forward declarations */
49struct pcm_channel;
50struct pcmchan_syncgroup;
51struct pcmchan_syncmember;
52
67931cc4 53extern struct lock snd_pcm_syncgroups_mtx;
2a1ad637
FT
54extern SLIST_HEAD(pcm_synclist, pcmchan_syncgroup) snd_pcm_syncgroups;
55
67931cc4 56#define PCM_SG_LOCK() lockmgr(&snd_pcm_syncgroups_mtx, LK_EXCLUSIVE)
833eb915 57#define PCM_SG_TRYLOCK() lockmgr_try(&snd_pcm_syncgroups_mtx, LK_EXCLUSIVE)
67931cc4 58#define PCM_SG_UNLOCK() lockmgr(&snd_pcm_syncgroups_mtx, LK_RELEASE)
5f097292
MD
59#define PCM_SG_ASSERTOWNED KKASSERT(lockstatus(&snd_pcm_syncgroups_mtx, curthread) == LK_EXCLUSIVE)
60#define PCM_SG_ASSERTNOTOWNED KKASSERT(lockstatus(&snd_pcm_syncgroups_mtx, curthread) != LK_EXCLUSIVE)
2a1ad637
FT
61
62/**
63 * @brief Specifies an audio device sync group
64 */
65struct pcmchan_syncgroup {
66 SLIST_ENTRY(pcmchan_syncgroup) link;
67 SLIST_HEAD(, pcmchan_syncmember) members;
68 int id; /**< Group identifier; set to address of group. */
69};
70
71/**
72 * @brief Specifies a container for members of a sync group
73 */
74struct pcmchan_syncmember {
75 SLIST_ENTRY(pcmchan_syncmember) link;
76 struct pcmchan_syncgroup *parent; /**< group head */
77 struct pcm_channel *ch;
78};
79
80#define CHN_NAMELEN 32
81#define CHN_COMM_UNUSED "<UNUSED>"
82#define CHN_COMM_UNKNOWN "<UNKNOWN>"
83
984263bc
MD
84struct pcm_channel {
85 kobj_t methods;
86
984263bc
MD
87 pid_t pid;
88 int refcount;
89 struct pcm_feeder *feeder;
90 u_int32_t align;
91
2a1ad637 92 int latency;
984263bc
MD
93 u_int32_t speed;
94 u_int32_t format;
95 u_int32_t flags;
96 u_int32_t feederflags;
2a1ad637 97 u_int64_t blocks;
984263bc
MD
98
99 int direction;
2a1ad637
FT
100 unsigned int interrupts, xruns, feedcount;
101 unsigned int timeout;
984263bc
MD
102 struct snd_dbuf *bufhard, *bufsoft;
103 struct snddev_info *parentsnddev;
104 struct pcm_channel *parentchannel;
105 void *devinfo;
106 device_t dev;
2a1ad637 107 int unit;
984263bc 108 char name[CHN_NAMELEN];
2a1ad637 109 char comm[MAXCOMLEN + 1];
67931cc4 110 struct lock *lock;
2a1ad637
FT
111 int trigger;
112 /**
113 * For interrupt manipulations.
114 */
115 struct cv intr_cv;
116 /**
117 * Increment,decrement this around operations that temporarily yield
118 * lock.
119 */
120 unsigned int inprog;
121 /**
122 * Special channel operations should examine @c inprog after acquiring
123 * lock. If zero, operations may continue. Else, thread should
124 * wait on this cv for previous operation to finish.
125 */
126 struct cv cv;
127 /**
128 * Low water mark for select()/poll().
129 *
130 * This is initialized to the channel's fragment size, and will be
131 * overwritten if a new fragment size is set. Users may alter this
132 * value directly with the @c SNDCTL_DSP_LOW_WATER ioctl.
133 */
134 unsigned int lw;
135 /**
136 * If part of a sync group, this will point to the syncmember
137 * container.
138 */
139 struct pcmchan_syncmember *sm;
140#ifdef OSSV4_EXPERIMENT
141 u_int16_t lpeak, rpeak; /**< Peak value from 0-32767. */
142#endif
143
144 struct {
145 SLIST_HEAD(, pcm_channel) head;
146 SLIST_ENTRY(pcm_channel) link;
147 struct {
148 SLIST_HEAD(, pcm_channel) head;
149 SLIST_ENTRY(pcm_channel) link;
150 } busy;
151 } children;
152
153 struct {
154 struct {
155 SLIST_ENTRY(pcm_channel) link;
156 struct {
157 SLIST_ENTRY(pcm_channel) link;
158 } busy;
159 struct {
160 SLIST_ENTRY(pcm_channel) link;
161 } opened;
162 } pcm;
163 } channels;
164
165 struct pcmchan_matrix matrix;
166
167 int volume[SND_VOL_C_MAX][SND_CHN_T_VOL_MAX];
168
169 void *data1, *data2;
984263bc
MD
170};
171
2a1ad637
FT
172#define CHN_HEAD(x, y) &(x)->y.head
173#define CHN_INIT(x, y) SLIST_INIT(CHN_HEAD(x, y))
174#define CHN_LINK(y) y.link
175#define CHN_EMPTY(x, y) SLIST_EMPTY(CHN_HEAD(x, y))
176#define CHN_FIRST(x, y) SLIST_FIRST(CHN_HEAD(x, y))
177
178#define CHN_FOREACH(x, y, z) \
179 SLIST_FOREACH(x, CHN_HEAD(y, z), CHN_LINK(z))
180
181#define CHN_FOREACH_SAFE(w, x, y, z) \
67931cc4 182 SLIST_FOREACH_MUTABLE(w, CHN_HEAD(x, z), CHN_LINK(z), y)
2a1ad637
FT
183
184#define CHN_INSERT_HEAD(x, y, z) \
185 SLIST_INSERT_HEAD(CHN_HEAD(x, z), y, CHN_LINK(z))
186
187#define CHN_INSERT_AFTER(x, y, z) \
188 SLIST_INSERT_AFTER(x, y, CHN_LINK(z))
189
190#define CHN_REMOVE(x, y, z) \
191 SLIST_REMOVE(CHN_HEAD(x, z), y, pcm_channel, CHN_LINK(z))
192
193#define CHN_INSERT_HEAD_SAFE(x, y, z) do { \
194 struct pcm_channel *t = NULL; \
195 CHN_FOREACH(t, x, z) { \
196 if (t == y) \
197 break; \
198 } \
199 if (t != y) \
200 CHN_INSERT_HEAD(x, y, z); \
201} while (0)
202
203#define CHN_INSERT_AFTER_SAFE(w, x, y, z) do { \
204 struct pcm_channel *t = NULL; \
205 CHN_FOREACH(t, w, z) { \
206 if (t == y) \
207 break; \
208 } \
209 if (t != y) \
210 CHN_INSERT_AFTER(x, y, z); \
211} while (0)
212
213#define CHN_REMOVE_SAFE(x, y, z) do { \
214 struct pcm_channel *t = NULL; \
215 CHN_FOREACH(t, x, z) { \
216 if (t == y) \
217 break; \
218 } \
219 if (t == y) \
220 CHN_REMOVE(x, y, z); \
221} while (0)
222
223#define CHN_INSERT_SORT(w, x, y, z) do { \
224 struct pcm_channel *t, *a = NULL; \
225 CHN_FOREACH(t, x, z) { \
226 if ((y)->unit w t->unit) \
227 a = t; \
228 else \
229 break; \
230 } \
231 if (a != NULL) \
232 CHN_INSERT_AFTER(a, y, z); \
233 else \
234 CHN_INSERT_HEAD(x, y, z); \
235} while (0)
236
237#define CHN_INSERT_SORT_ASCEND(x, y, z) CHN_INSERT_SORT(>, x, y, z)
238#define CHN_INSERT_SORT_DESCEND(x, y, z) CHN_INSERT_SORT(<, x, y, z)
239
240#define CHN_UNIT(x) (snd_unit2u((x)->unit))
241#define CHN_DEV(x) (snd_unit2d((x)->unit))
242#define CHN_CHAN(x) (snd_unit2c((x)->unit))
243
244#define CHN_BUF_PARENT(x, y) \
245 (((x) != NULL && (x)->parentchannel != NULL && \
246 (x)->parentchannel->bufhard != NULL) ? \
247 (x)->parentchannel->bufhard : (y))
248
249#define CHN_BROADCAST(x) do { \
250 if ((x)->cv_waiters != 0) \
251 cv_broadcastpri(x, PRIBIO); \
252} while (0)
253
984263bc
MD
254#include "channel_if.h"
255
256int chn_reinit(struct pcm_channel *c);
bb3a8342
SZ
257int chn_write(struct pcm_channel *c, struct uio *buf, int ioflags);
258int chn_read(struct pcm_channel *c, struct uio *buf, int ioflags);
984263bc
MD
259u_int32_t chn_start(struct pcm_channel *c, int force);
260int chn_sync(struct pcm_channel *c, int threshold);
261int chn_flush(struct pcm_channel *c);
558a398b 262int chn_poll(struct pcm_channel *c, int ev, struct thread *td);
984263bc 263
558a398b 264int chn_init(struct pcm_channel *c, void *devinfo, int dir, int direction);
984263bc 265int chn_kill(struct pcm_channel *c);
2a1ad637 266int chn_reset(struct pcm_channel *c, u_int32_t fmt, u_int32_t spd);
984263bc 267int chn_setvolume(struct pcm_channel *c, int left, int right);
2a1ad637
FT
268int chn_setvolume_multi(struct pcm_channel *c, int vc, int left, int right,
269 int center);
270int chn_setvolume_matrix(struct pcm_channel *c, int vc, int vt, int val);
271int chn_getvolume_matrix(struct pcm_channel *c, int vc, int vt);
272void chn_vpc_reset(struct pcm_channel *c, int vc, int force);
273int chn_setparam(struct pcm_channel *c, uint32_t format, uint32_t speed);
274int chn_setspeed(struct pcm_channel *c, uint32_t speed);
275int chn_setformat(struct pcm_channel *c, uint32_t format);
984263bc 276int chn_setblocksize(struct pcm_channel *c, int blkcnt, int blksz);
2a1ad637
FT
277int chn_setlatency(struct pcm_channel *c, int latency);
278void chn_syncstate(struct pcm_channel *c);
984263bc
MD
279int chn_trigger(struct pcm_channel *c, int go);
280int chn_getptr(struct pcm_channel *c);
281struct pcmchan_caps *chn_getcaps(struct pcm_channel *c);
282u_int32_t chn_getformats(struct pcm_channel *c);
283
2a1ad637
FT
284struct pcmchan_matrix *chn_getmatrix(struct pcm_channel *);
285int chn_setmatrix(struct pcm_channel *, struct pcmchan_matrix *);
286
287int chn_oss_getorder(struct pcm_channel *, unsigned long long *);
288int chn_oss_setorder(struct pcm_channel *, unsigned long long *);
289int chn_oss_getmask(struct pcm_channel *, uint32_t *);
290
984263bc 291void chn_resetbuf(struct pcm_channel *c);
2a1ad637 292void chn_intr_locked(struct pcm_channel *c);
984263bc 293void chn_intr(struct pcm_channel *c);
984263bc
MD
294int chn_abort(struct pcm_channel *c);
295
984263bc
MD
296int chn_notify(struct pcm_channel *c, u_int32_t flags);
297
2a1ad637
FT
298int chn_getrates(struct pcm_channel *c, int **rates);
299int chn_syncdestroy(struct pcm_channel *c);
300
301#define CHN_SETVOLUME(...) chn_setvolume_matrix(__VA_ARGS__)
302#if defined(SND_DIAGNOSTIC) || defined(INVARIANTS)
303#define CHN_GETVOLUME(...) chn_getvolume_matrix(__VA_ARGS__)
984263bc 304#else
2a1ad637
FT
305#define CHN_GETVOLUME(x, y, z) ((x)->volume[y][z])
306#endif
307
308#ifdef OSSV4_EXPERIMENT
309int chn_getpeaks(struct pcm_channel *c, int *lpeak, int *rpeak);
984263bc
MD
310#endif
311
5f097292 312#define CHN_LOCKOWNED(c) (lockstatus((c)->lock, curthread) == LK_EXCLUSIVE)
67931cc4
FT
313#define CHN_LOCK(c) lockmgr((c)->lock, LK_EXCLUSIVE)
314#define CHN_UNLOCK(c) lockmgr((c)->lock, LK_RELEASE)
7968600a 315#define CHN_TRYLOCK(c) lockmgr_try((c)->lock, LK_EXCLUSIVE)
5f097292
MD
316#define CHN_LOCKASSERT(c) KKASSERT(lockstatus((c)->lock, curthread) == LK_EXCLUSIVE)
317#define CHN_UNLOCKASSERT(c) KKASSERT(lockstatus((c)->lock, curthread) != LK_EXCLUSIVE)
2a1ad637
FT
318
319int snd_fmtvalid(uint32_t fmt, uint32_t *fmtlist);
320
321uint32_t snd_str2afmt(const char *);
322uint32_t snd_afmt2str(uint32_t, char *, size_t);
323
324#define AFMTSTR_LEN 16
984263bc 325
2a1ad637
FT
326
327extern int chn_latency;
328extern int chn_latency_profile;
329extern int report_soft_formats;
330extern int report_soft_matrix;
331
332#define PCMDIR_PLAY 1
333#define PCMDIR_PLAY_VIRTUAL 2
334#define PCMDIR_REC -1
335#define PCMDIR_REC_VIRTUAL -2
984263bc
MD
336
337#define PCMTRIG_START 1
338#define PCMTRIG_EMLDMAWR 2
339#define PCMTRIG_EMLDMARD 3
340#define PCMTRIG_STOP 0
341#define PCMTRIG_ABORT -1
342
d3474664
SW
343#define PCMTRIG_COMMON(x) ((x) == PCMTRIG_START || \
344 (x) == PCMTRIG_STOP || \
345 (x) == PCMTRIG_ABORT)
346
2a1ad637
FT
347#define CHN_F_CLOSING 0x00000001 /* a pending close */
348#define CHN_F_ABORTING 0x00000002 /* a pending abort */
349#define CHN_F_RUNNING 0x00000004 /* dma is running */
350#define CHN_F_TRIGGERED 0x00000008
351#define CHN_F_NOTRIGGER 0x00000010
352#define CHN_F_SLEEPING 0x00000020
353
bb3a8342 354#define CHN_F_UNUSED1 0x00000040
2a1ad637
FT
355#define CHN_F_MMAP 0x00000080 /* has been mmap()ed */
356
357#define CHN_F_BUSY 0x00000100 /* has been opened */
358#define CHN_F_DIRTY 0x00000200 /* need re-config */
359#define CHN_F_DEAD 0x00000400 /* too many errors, dead, mdk */
360#define CHN_F_SILENCE 0x00000800 /* silence, nil, null, yada */
361
362#define CHN_F_HAS_SIZE 0x00001000 /* user set block size */
363#define CHN_F_HAS_VCHAN 0x00002000 /* vchan master */
364
365#define CHN_F_VCHAN_PASSTHROUGH 0x00004000 /* digital ac3/dts passthrough */
366#define CHN_F_VCHAN_ADAPTIVE 0x00008000 /* adaptive format/rate selection */
367#define CHN_F_VCHAN_DYNAMIC (CHN_F_VCHAN_PASSTHROUGH | CHN_F_VCHAN_ADAPTIVE)
984263bc
MD
368
369#define CHN_F_VIRTUAL 0x10000000 /* not backed by hardware */
2a1ad637
FT
370#define CHN_F_BITPERFECT 0x20000000 /* un-cooked, Heh.. */
371#define CHN_F_PASSTHROUGH 0x40000000 /* passthrough re-config */
372#define CHN_F_EXCLUSIVE 0x80000000 /* exclusive access */
373
374#define CHN_F_BITS "\020" \
375 "\001CLOSING" \
376 "\002ABORTING" \
377 "\003RUNNING" \
378 "\004TRIGGERED" \
379 "\005NOTRIGGER" \
380 "\006SLEEPING" \
381 "\007NBIO" \
382 "\010MMAP" \
383 "\011BUSY" \
384 "\012DIRTY" \
385 "\013DEAD" \
386 "\014SILENCE" \
387 "\015HAS_SIZE" \
388 "\016HAS_VCHAN" \
389 "\017VCHAN_PASSTHROUGH" \
390 "\020VCHAN_ADAPTIVE" \
391 "\035VIRTUAL" \
392 "\036BITPERFECT" \
393 "\037PASSTHROUGH" \
394 "\040EXCLUSIVE"
395
396
397#define CHN_F_RESET (CHN_F_BUSY | CHN_F_DEAD | \
398 CHN_F_VIRTUAL | CHN_F_HAS_VCHAN | \
399 CHN_F_VCHAN_DYNAMIC | \
400 CHN_F_PASSTHROUGH | CHN_F_EXCLUSIVE)
401
402#define CHN_F_MMAP_INVALID (CHN_F_DEAD | CHN_F_RUNNING)
984263bc 403
558a398b 404
984263bc
MD
405
406#define CHN_N_RATE 0x00000001
407#define CHN_N_FORMAT 0x00000002
408#define CHN_N_VOLUME 0x00000004
409#define CHN_N_BLOCKSIZE 0x00000008
410#define CHN_N_TRIGGER 0x00000010
411
2a1ad637
FT
412#define CHN_LATENCY_MIN 0
413#define CHN_LATENCY_MAX 10
414#define CHN_LATENCY_DEFAULT 5
415#define CHN_POLICY_MIN CHN_LATENCY_MIN
416#define CHN_POLICY_MAX CHN_LATENCY_MAX
417#define CHN_POLICY_DEFAULT CHN_LATENCY_DEFAULT
418
419#define CHN_LATENCY_PROFILE_MIN 0
420#define CHN_LATENCY_PROFILE_MAX 1
421#define CHN_LATENCY_PROFILE_DEFAULT CHN_LATENCY_PROFILE_MAX
422
423#define CHN_STARTED(c) ((c)->flags & CHN_F_TRIGGERED)
424#define CHN_STOPPED(c) (!CHN_STARTED(c))
425#define CHN_DIRSTR(c) (((c)->direction == PCMDIR_PLAY) ? \
426 "PCMDIR_PLAY" : "PCMDIR_REC")
427#define CHN_BITPERFECT(c) ((c)->flags & CHN_F_BITPERFECT)
428#define CHN_PASSTHROUGH(c) ((c)->flags & CHN_F_PASSTHROUGH)
429
430#define CHN_TIMEOUT 5
431#define CHN_TIMEOUT_MIN 1
432#define CHN_TIMEOUT_MAX 10
433
984263bc
MD
434/*
435 * This should be large enough to hold all pcm data between
436 * tsleeps in chn_{read,write} at the highest sample rate.
437 * (which is usually 48kHz * 16bit * stereo = 192000 bytes/sec)
438 */
439#define CHN_2NDBUFBLKSIZE (2 * 1024)
440/* The total number of blocks per secondary bufhard. */
441#define CHN_2NDBUFBLKNUM (32)
442/* The size of a whole secondary bufhard. */
443#define CHN_2NDBUFMAXSIZE (131072)
444
445#define CHANNEL_DECLARE(name) static DEFINE_CLASS(name, name ## _methods, sizeof(struct kobj))