1139749Simp/*-
2193640Sariff * Copyright (c) 2005-2009 Ariff Abdullah <ariff@FreeBSD.org>
3193640Sariff * Portions Copyright (c) Ryan Beasley <ryan.beasley@gmail.com> - GSoC 2006
4193640Sariff * Copyright (c) 1999 Cameron Grant <cg@FreeBSD.org>
550724Scg * All rights reserved.
650724Scg *
750724Scg * Redistribution and use in source and binary forms, with or without
850724Scg * modification, are permitted provided that the following conditions
950724Scg * are met:
1050724Scg * 1. Redistributions of source code must retain the above copyright
1150724Scg *    notice, this list of conditions and the following disclaimer.
1250724Scg * 2. Redistributions in binary form must reproduce the above copyright
1350724Scg *    notice, this list of conditions and the following disclaimer in the
1450724Scg *    documentation and/or other materials provided with the distribution.
1550724Scg *
1650724Scg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1750724Scg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1850724Scg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1950724Scg * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2050724Scg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2150724Scg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2250724Scg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2350724Scg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2450724Scg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2550724Scg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2650724Scg * SUCH DAMAGE.
2750724Scg *
2850733Speter * $FreeBSD$
2950724Scg */
3050724Scg
3174763Scgstruct pcmchan_caps {
3274763Scg	u_int32_t minspeed, maxspeed;
3374763Scg	u_int32_t *fmtlist;
3474763Scg	u_int32_t caps;
3574763Scg};
3674763Scg
37193640Sariffstruct pcmchan_matrix {
38193640Sariff	int id;
39193640Sariff	uint8_t channels, ext;
40193640Sariff	struct {
41193640Sariff		int type;
42193640Sariff		uint32_t members;
43193640Sariff	} map[SND_CHN_T_MAX + 1];
44193640Sariff	uint32_t mask;
45193640Sariff	int8_t offset[SND_CHN_T_MAX];
46193640Sariff};
47193640Sariff
48162588Snetchild/* Forward declarations */
49162588Snetchildstruct pcm_channel;
50162588Snetchildstruct pcmchan_syncgroup;
51162588Snetchildstruct pcmchan_syncmember;
52162588Snetchild
53162588Snetchildextern struct mtx snd_pcm_syncgroups_mtx;
54162588Snetchildextern SLIST_HEAD(pcm_synclist, pcmchan_syncgroup) snd_pcm_syncgroups;
55162588Snetchild
56162588Snetchild#define PCM_SG_LOCK()	    mtx_lock(&snd_pcm_syncgroups_mtx)
57162588Snetchild#define PCM_SG_TRYLOCK()    mtx_trylock(&snd_pcm_syncgroups_mtx)
58162588Snetchild#define PCM_SG_UNLOCK()	    mtx_unlock(&snd_pcm_syncgroups_mtx)
59162588Snetchild#define PCM_SG_LOCKASSERT(arg)	mtx_assert(&snd_pcm_syncgroups_mtx, arg)
60162588Snetchild
61162588Snetchild/**
62162588Snetchild * @brief Specifies an audio device sync group
63162588Snetchild */
64162588Snetchildstruct pcmchan_syncgroup {
65162588Snetchild	SLIST_ENTRY(pcmchan_syncgroup) link;
66162588Snetchild	SLIST_HEAD(, pcmchan_syncmember) members;
67162588Snetchild	int id; /**< Group identifier; set to address of group. */
68162588Snetchild};
69162588Snetchild
70162588Snetchild/**
71162588Snetchild * @brief Specifies a container for members of a sync group
72162588Snetchild */
73162588Snetchildstruct pcmchan_syncmember {
74162588Snetchild	SLIST_ENTRY(pcmchan_syncmember) link;
75162588Snetchild	struct pcmchan_syncgroup *parent; /**< group head */
76162588Snetchild	struct pcm_channel *ch;
77162588Snetchild};
78162588Snetchild
79193640Sariff#define	CHN_NAMELEN		32
80193640Sariff#define	CHN_COMM_UNUSED		"<UNUSED>"
81193640Sariff#define	CHN_COMM_UNKNOWN	"<UNKNOWN>"
82193640Sariff
8374763Scgstruct pcm_channel {
8474763Scg	kobj_t methods;
8574763Scg
8677269Scg	pid_t pid;
8777269Scg	int refcount;
8874763Scg	struct pcm_feeder *feeder;
8974763Scg	u_int32_t align;
9074763Scg
91164614Sariff	int latency;
9274763Scg	u_int32_t speed;
9374763Scg	u_int32_t format;
9474763Scg	u_int32_t flags;
9574763Scg	u_int32_t feederflags;
96193640Sariff	u_int64_t blocks;
9774763Scg
9874763Scg	int direction;
99164614Sariff	unsigned int interrupts, xruns, feedcount;
100164614Sariff	unsigned int timeout;
10174763Scg	struct snd_dbuf *bufhard, *bufsoft;
10277269Scg	struct snddev_info *parentsnddev;
10377269Scg	struct pcm_channel *parentchannel;
10474763Scg	void *devinfo;
10589774Sscottl	device_t dev;
106170161Sariff	int unit;
10774763Scg	char name[CHN_NAMELEN];
108193640Sariff	char comm[MAXCOMLEN + 1];
109107285Scg	struct mtx *lock;
110170161Sariff	int trigger;
111162588Snetchild	/**
112170815Sariff	 * For interrupt manipulations.
113170815Sariff	 */
114170815Sariff	struct cv intr_cv;
115170815Sariff	/**
116162588Snetchild	 * Increment,decrement this around operations that temporarily yield
117162588Snetchild	 * lock.
118162588Snetchild	 */
119162588Snetchild	unsigned int inprog;
120162588Snetchild	/**
121162588Snetchild	 * Special channel operations should examine @c inprog after acquiring
122162588Snetchild	 * lock.  If zero, operations may continue.  Else, thread should
123162588Snetchild	 * wait on this cv for previous operation to finish.
124162588Snetchild	 */
125162588Snetchild	struct cv cv;
126162588Snetchild	/**
127162588Snetchild	 * Low water mark for select()/poll().
128162588Snetchild	 *
129162588Snetchild	 * This is initialized to the channel's fragment size, and will be
130162588Snetchild	 * overwritten if a new fragment size is set.  Users may alter this
131162588Snetchild	 * value directly with the @c SNDCTL_DSP_LOW_WATER ioctl.
132162588Snetchild	 */
133162588Snetchild	unsigned int lw;
134162588Snetchild	/**
135162588Snetchild	 * If part of a sync group, this will point to the syncmember
136162588Snetchild	 * container.
137162588Snetchild	 */
138162588Snetchild	struct pcmchan_syncmember *sm;
139162588Snetchild#ifdef OSSV4_EXPERIMENT
140162588Snetchild	u_int16_t lpeak, rpeak;	/**< Peak value from 0-32767. */
141162588Snetchild#endif
142170161Sariff
143170161Sariff	struct {
144170161Sariff		SLIST_HEAD(, pcm_channel) head;
145170161Sariff		SLIST_ENTRY(pcm_channel) link;
146170161Sariff		struct {
147170161Sariff			SLIST_HEAD(, pcm_channel) head;
148170161Sariff			SLIST_ENTRY(pcm_channel) link;
149170161Sariff		} busy;
150170161Sariff	} children;
151170161Sariff
152170161Sariff	struct {
153170161Sariff		struct {
154170161Sariff			SLIST_ENTRY(pcm_channel) link;
155170161Sariff			struct {
156170161Sariff				SLIST_ENTRY(pcm_channel) link;
157170161Sariff			} busy;
158193640Sariff			struct {
159193640Sariff				SLIST_ENTRY(pcm_channel) link;
160193640Sariff			} opened;
161170161Sariff		} pcm;
162170161Sariff	} channels;
163170161Sariff
164193640Sariff	struct pcmchan_matrix matrix;
165193640Sariff
166193640Sariff	int volume[SND_VOL_C_MAX][SND_CHN_T_VOL_MAX];
167193640Sariff
168170161Sariff	void *data1, *data2;
16974763Scg};
17074763Scg
171170161Sariff#define CHN_HEAD(x, y)			&(x)->y.head
172170161Sariff#define CHN_INIT(x, y)			SLIST_INIT(CHN_HEAD(x, y))
173170161Sariff#define CHN_LINK(y)			y.link
174170161Sariff#define CHN_EMPTY(x, y)			SLIST_EMPTY(CHN_HEAD(x, y))
175170161Sariff#define CHN_FIRST(x, y)			SLIST_FIRST(CHN_HEAD(x, y))
176170161Sariff
177170161Sariff#define CHN_FOREACH(x, y, z)						\
178170161Sariff	SLIST_FOREACH(x, CHN_HEAD(y, z), CHN_LINK(z))
179170161Sariff
180170161Sariff#define CHN_FOREACH_SAFE(w, x, y, z)					\
181170161Sariff	SLIST_FOREACH_SAFE(w, CHN_HEAD(x, z), CHN_LINK(z), y)
182170161Sariff
183170161Sariff#define CHN_INSERT_HEAD(x, y, z)					\
184170161Sariff	SLIST_INSERT_HEAD(CHN_HEAD(x, z), y, CHN_LINK(z))
185170161Sariff
186170161Sariff#define CHN_INSERT_AFTER(x, y, z)					\
187170161Sariff	SLIST_INSERT_AFTER(x, y, CHN_LINK(z))
188170161Sariff
189170161Sariff#define CHN_REMOVE(x, y, z)						\
190170161Sariff	SLIST_REMOVE(CHN_HEAD(x, z), y, pcm_channel, CHN_LINK(z))
191170161Sariff
192170161Sariff#define CHN_INSERT_HEAD_SAFE(x, y, z)		do {			\
193170161Sariff	struct pcm_channel *t = NULL;					\
194170161Sariff	CHN_FOREACH(t, x, z) {						\
195170161Sariff		if (t == y)						\
196170161Sariff			break;						\
197170161Sariff	} 								\
198193640Sariff	if (t != y)							\
199170161Sariff		CHN_INSERT_HEAD(x, y, z);				\
200193640Sariff} while (0)
201170161Sariff
202170161Sariff#define CHN_INSERT_AFTER_SAFE(w, x, y, z)	do {			\
203170161Sariff	struct pcm_channel *t = NULL;					\
204170161Sariff	CHN_FOREACH(t, w, z) {						\
205170161Sariff		if (t == y)						\
206170161Sariff			break;						\
207170161Sariff	} 								\
208193640Sariff	if (t != y)							\
209170161Sariff		CHN_INSERT_AFTER(x, y, z);				\
210193640Sariff} while (0)
211170161Sariff
212170161Sariff#define CHN_REMOVE_SAFE(x, y, z)		do {			\
213170161Sariff	struct pcm_channel *t = NULL;					\
214170161Sariff	CHN_FOREACH(t, x, z) {						\
215170161Sariff		if (t == y)						\
216170161Sariff			break;						\
217170161Sariff	} 								\
218193640Sariff	if (t == y)							\
219170161Sariff		CHN_REMOVE(x, y, z);					\
220193640Sariff} while (0)
221193640Sariff
222193640Sariff#define CHN_INSERT_SORT(w, x, y, z)		do {			\
223193640Sariff	struct pcm_channel *t, *a = NULL;				\
224193640Sariff	CHN_FOREACH(t, x, z) {						\
225193640Sariff		if ((y)->unit w t->unit)				\
226193640Sariff			a = t;						\
227193640Sariff		else							\
228193640Sariff			break;						\
229170161Sariff	}								\
230193640Sariff	if (a != NULL)							\
231193640Sariff		CHN_INSERT_AFTER(a, y, z);				\
232193640Sariff	else								\
233193640Sariff		CHN_INSERT_HEAD(x, y, z);				\
234193640Sariff} while (0)
235170161Sariff
236193640Sariff#define CHN_INSERT_SORT_ASCEND(x, y, z)		CHN_INSERT_SORT(>, x, y, z)
237193640Sariff#define CHN_INSERT_SORT_DESCEND(x, y, z)	CHN_INSERT_SORT(<, x, y, z)
238193640Sariff
239170161Sariff#define CHN_UNIT(x)	(snd_unit2u((x)->unit))
240170161Sariff#define CHN_DEV(x)	(snd_unit2d((x)->unit))
241170161Sariff#define CHN_CHAN(x)	(snd_unit2c((x)->unit))
242170161Sariff
243170815Sariff#define CHN_BUF_PARENT(x, y)						\
244170815Sariff	(((x) != NULL && (x)->parentchannel != NULL &&			\
245170815Sariff	(x)->parentchannel->bufhard != NULL) ?				\
246170815Sariff	(x)->parentchannel->bufhard : (y))
247170815Sariff
248170815Sariff#define CHN_BROADCAST(x)	do {					\
249170815Sariff	if ((x)->cv_waiters != 0)					\
250170815Sariff		cv_broadcastpri(x, PRIBIO);				\
251193640Sariff} while (0)
252170815Sariff
25370134Scg#include "channel_if.h"
25470134Scg
25574763Scgint chn_reinit(struct pcm_channel *c);
25674763Scgint chn_write(struct pcm_channel *c, struct uio *buf);
25774763Scgint chn_read(struct pcm_channel *c, struct uio *buf);
25874763Scgu_int32_t chn_start(struct pcm_channel *c, int force);
25974763Scgint chn_sync(struct pcm_channel *c, int threshold);
26074763Scgint chn_flush(struct pcm_channel *c);
26183366Sjulianint chn_poll(struct pcm_channel *c, int ev, struct thread *td);
26250724Scg
263126367Struckmanint chn_init(struct pcm_channel *c, void *devinfo, int dir, int direction);
26474763Scgint chn_kill(struct pcm_channel *c);
265193640Sariffint chn_reset(struct pcm_channel *c, u_int32_t fmt, u_int32_t spd);
26674763Scgint chn_setvolume(struct pcm_channel *c, int left, int right);
267193640Sariffint chn_setvolume_multi(struct pcm_channel *c, int vc, int left, int right,
268193640Sariff    int center);
269193640Sariffint chn_setvolume_matrix(struct pcm_channel *c, int vc, int vt, int val);
270193640Sariffint chn_getvolume_matrix(struct pcm_channel *c, int vc, int vt);
271193640Sariffvoid chn_vpc_reset(struct pcm_channel *c, int vc, int force);
272193640Sariffint chn_setparam(struct pcm_channel *c, uint32_t format, uint32_t speed);
273193640Sariffint chn_setspeed(struct pcm_channel *c, uint32_t speed);
274193640Sariffint chn_setformat(struct pcm_channel *c, uint32_t format);
27574763Scgint chn_setblocksize(struct pcm_channel *c, int blkcnt, int blksz);
276164614Sariffint chn_setlatency(struct pcm_channel *c, int latency);
277193640Sariffvoid chn_syncstate(struct pcm_channel *c);
27874763Scgint chn_trigger(struct pcm_channel *c, int go);
27974763Scgint chn_getptr(struct pcm_channel *c);
28074763Scgstruct pcmchan_caps *chn_getcaps(struct pcm_channel *c);
28174763Scgu_int32_t chn_getformats(struct pcm_channel *c);
28250724Scg
283193640Sariffstruct pcmchan_matrix *chn_getmatrix(struct pcm_channel *);
284193640Sariffint chn_setmatrix(struct pcm_channel *, struct pcmchan_matrix *);
285193640Sariff
286193640Sariffint chn_oss_getorder(struct pcm_channel *, unsigned long long *);
287193640Sariffint chn_oss_setorder(struct pcm_channel *, unsigned long long *);
288193640Sariffint chn_oss_getmask(struct pcm_channel *, uint32_t *);
289193640Sariff
29074763Scgvoid chn_resetbuf(struct pcm_channel *c);
291193640Sariffvoid chn_intr_locked(struct pcm_channel *c);
29274763Scgvoid chn_intr(struct pcm_channel *c);
29374763Scgint chn_abort(struct pcm_channel *c);
29450724Scg
29577269Scgint chn_notify(struct pcm_channel *c, u_int32_t flags);
29677269Scg
297162588Snetchildint chn_getrates(struct pcm_channel *c, int **rates);
298162588Snetchildint chn_syncdestroy(struct pcm_channel *c);
299162588Snetchild
300193640Sariff#define CHN_SETVOLUME(...)		chn_setvolume_matrix(__VA_ARGS__)
301193640Sariff#if defined(SND_DIAGNOSTIC) || defined(INVARIANTS)
302193640Sariff#define CHN_GETVOLUME(...)		chn_getvolume_matrix(__VA_ARGS__)
303193640Sariff#else
304193640Sariff#define CHN_GETVOLUME(x, y, z)		((x)->volume[y][z])
305193640Sariff#endif
306193640Sariff
307162588Snetchild#ifdef OSSV4_EXPERIMENT
308162588Snetchildint chn_getpeaks(struct pcm_channel *c, int *lpeak, int *rpeak);
309162588Snetchild#endif
310162588Snetchild
311193640Sariff#define CHN_LOCKOWNED(c)	mtx_owned((c)->lock)
312193640Sariff#define CHN_LOCK(c)		mtx_lock((c)->lock)
313193640Sariff#define CHN_UNLOCK(c)		mtx_unlock((c)->lock)
314193640Sariff#define CHN_TRYLOCK(c)		mtx_trylock((c)->lock)
315193640Sariff#define CHN_LOCKASSERT(c)	mtx_assert((c)->lock, MA_OWNED)
316193640Sariff#define CHN_UNLOCKASSERT(c)	mtx_assert((c)->lock, MA_NOTOWNED)
31774763Scg
318193640Sariffint snd_fmtvalid(uint32_t fmt, uint32_t *fmtlist);
31964881Scg
320193640Sariffuint32_t snd_str2afmt(const char *);
321193640Sariffuint32_t snd_afmt2str(uint32_t, char *, size_t);
322164614Sariff
323193640Sariff#define AFMTSTR_LEN	16
324164614Sariff
325164614Sariff
326164614Sariffextern int chn_latency;
327164614Sariffextern int chn_latency_profile;
328164614Sariffextern int report_soft_formats;
329193640Sariffextern int report_soft_matrix;
330164614Sariff
331170161Sariff#define PCMDIR_PLAY		1
332170161Sariff#define PCMDIR_PLAY_VIRTUAL	2
333170161Sariff#define PCMDIR_REC		-1
334170161Sariff#define PCMDIR_REC_VIRTUAL	-2
33550724Scg
33650724Scg#define PCMTRIG_START 1
33755204Scg#define PCMTRIG_EMLDMAWR 2
33860958Scg#define PCMTRIG_EMLDMARD 3
33950724Scg#define PCMTRIG_STOP 0
34050724Scg#define PCMTRIG_ABORT -1
34150724Scg
342170521Sariff#define PCMTRIG_COMMON(x)	((x) == PCMTRIG_START ||		\
343170521Sariff				 (x) == PCMTRIG_STOP ||			\
344170521Sariff				 (x) == PCMTRIG_ABORT)
345170521Sariff
346193640Sariff#define CHN_F_CLOSING           0x00000001  /* a pending close */
347193640Sariff#define CHN_F_ABORTING          0x00000002  /* a pending abort */
348193640Sariff#define CHN_F_RUNNING		0x00000004  /* dma is running */
349193640Sariff#define CHN_F_TRIGGERED		0x00000008
350193640Sariff#define CHN_F_NOTRIGGER		0x00000010
351193640Sariff#define CHN_F_SLEEPING		0x00000020
35250724Scg
353193640Sariff#define CHN_F_NBIO              0x00000040  /* do non-blocking i/o */
354193640Sariff#define CHN_F_MMAP		0x00000080  /* has been mmap()ed */
35550724Scg
356193640Sariff#define CHN_F_BUSY              0x00000100  /* has been opened 	*/
357193640Sariff#define CHN_F_DIRTY		0x00000200  /* need re-config */
358193640Sariff#define CHN_F_DEAD		0x00000400  /* too many errors, dead, mdk */
359193640Sariff#define CHN_F_SILENCE		0x00000800  /* silence, nil, null, yada */
360193640Sariff
361193640Sariff#define	CHN_F_HAS_SIZE		0x00001000  /* user set block size */
362193640Sariff#define CHN_F_HAS_VCHAN		0x00002000  /* vchan master */
363193640Sariff
364193640Sariff#define CHN_F_VCHAN_PASSTHROUGH	0x00004000  /* digital ac3/dts passthrough */
365193640Sariff#define CHN_F_VCHAN_ADAPTIVE	0x00008000  /* adaptive format/rate selection */
366193640Sariff#define CHN_F_VCHAN_DYNAMIC	(CHN_F_VCHAN_PASSTHROUGH | CHN_F_VCHAN_ADAPTIVE)
367193640Sariff
36877269Scg#define	CHN_F_VIRTUAL		0x10000000  /* not backed by hardware */
369193640Sariff#define CHN_F_BITPERFECT	0x20000000  /* un-cooked, Heh.. */
370193640Sariff#define CHN_F_PASSTHROUGH	0x40000000  /* passthrough re-config */
371193640Sariff#define CHN_F_EXCLUSIVE		0x80000000  /* exclusive access */
37254535Scg
373193640Sariff#define CHN_F_BITS		"\020"					\
374193640Sariff				"\001CLOSING"				\
375193640Sariff				"\002ABORTING"				\
376193640Sariff				"\003RUNNING"				\
377193640Sariff				"\004TRIGGERED"				\
378193640Sariff				"\005NOTRIGGER"				\
379193640Sariff				"\006SLEEPING"				\
380193640Sariff				"\007NBIO"				\
381193640Sariff				"\010MMAP"				\
382193640Sariff				"\011BUSY"				\
383193640Sariff				"\012DIRTY"				\
384193640Sariff				"\013DEAD"				\
385193640Sariff				"\014SILENCE"				\
386193640Sariff				"\015HAS_SIZE"				\
387193640Sariff				"\016HAS_VCHAN"				\
388193640Sariff				"\017VCHAN_PASSTHROUGH"			\
389193640Sariff				"\020VCHAN_ADAPTIVE"			\
390193640Sariff				"\035VIRTUAL"				\
391193640Sariff				"\036BITPERFECT"			\
392193640Sariff				"\037PASSTHROUGH"			\
393193640Sariff				"\040EXCLUSIVE"
394193640Sariff
395193640Sariff
396170815Sariff#define CHN_F_RESET		(CHN_F_BUSY | CHN_F_DEAD |		\
397193640Sariff				 CHN_F_VIRTUAL | CHN_F_HAS_VCHAN |	\
398193640Sariff				 CHN_F_VCHAN_DYNAMIC |			\
399193640Sariff				 CHN_F_PASSTHROUGH | CHN_F_EXCLUSIVE)
400170815Sariff
401170815Sariff#define CHN_F_MMAP_INVALID	(CHN_F_DEAD | CHN_F_RUNNING)
402170815Sariff
403149953Snetchild
40477269Scg
40577269Scg#define CHN_N_RATE		0x00000001
40677269Scg#define CHN_N_FORMAT		0x00000002
40777269Scg#define CHN_N_VOLUME		0x00000004
40877269Scg#define CHN_N_BLOCKSIZE		0x00000008
40977269Scg#define CHN_N_TRIGGER		0x00000010
41077269Scg
411164614Sariff#define CHN_LATENCY_MIN		0
412164614Sariff#define CHN_LATENCY_MAX		10
413164614Sariff#define CHN_LATENCY_DEFAULT	5
414164614Sariff#define CHN_POLICY_MIN		CHN_LATENCY_MIN
415164614Sariff#define CHN_POLICY_MAX		CHN_LATENCY_MAX
416164614Sariff#define CHN_POLICY_DEFAULT	CHN_LATENCY_DEFAULT
417164614Sariff
418164614Sariff#define CHN_LATENCY_PROFILE_MIN		0
419164614Sariff#define CHN_LATENCY_PROFILE_MAX		1
420164614Sariff#define CHN_LATENCY_PROFILE_DEFAULT	CHN_LATENCY_PROFILE_MAX
421164614Sariff
422170815Sariff#define CHN_STARTED(c)		((c)->flags & CHN_F_TRIGGERED)
423170815Sariff#define CHN_STOPPED(c)		(!CHN_STARTED(c))
424170815Sariff#define CHN_DIRSTR(c)		(((c)->direction == PCMDIR_PLAY) ? \
425170815Sariff				"PCMDIR_PLAY" : "PCMDIR_REC")
426193640Sariff#define CHN_BITPERFECT(c)	((c)->flags & CHN_F_BITPERFECT)
427193640Sariff#define CHN_PASSTHROUGH(c)	((c)->flags & CHN_F_PASSTHROUGH)
428170815Sariff
429170815Sariff#define CHN_TIMEOUT		5
430170815Sariff#define CHN_TIMEOUT_MIN		1
431170815Sariff#define CHN_TIMEOUT_MAX		10
432170815Sariff
43354535Scg/*
43454535Scg * This should be large enough to hold all pcm data between
43554535Scg * tsleeps in chn_{read,write} at the highest sample rate.
43654535Scg * (which is usually 48kHz * 16bit * stereo = 192000 bytes/sec)
43754535Scg */
43855204Scg#define CHN_2NDBUFBLKSIZE	(2 * 1024)
43974763Scg/* The total number of blocks per secondary bufhard. */
44059020Scg#define CHN_2NDBUFBLKNUM	(32)
44174763Scg/* The size of a whole secondary bufhard. */
44259246Scg#define CHN_2NDBUFMAXSIZE	(131072)
44370134Scg
44470134Scg#define CHANNEL_DECLARE(name) static DEFINE_CLASS(name, name ## _methods, sizeof(struct kobj))
445