xref: /freebsd/sys/dev/sound/pcm/channel.h (revision 2b743a9e9ddc6736208dc8ca1ce06ce64ad20a19)
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_children {
30 	SLIST_ENTRY(pcmchan_children) link;
31 	struct pcm_channel *channel;
32 };
33 
34 struct pcmchan_caps {
35 	u_int32_t minspeed, maxspeed;
36 	u_int32_t *fmtlist;
37 	u_int32_t caps;
38 };
39 
40 /* Forward declarations */
41 struct pcm_channel;
42 struct pcmchan_syncgroup;
43 struct pcmchan_syncmember;
44 
45 extern struct mtx snd_pcm_syncgroups_mtx;
46 extern SLIST_HEAD(pcm_synclist, pcmchan_syncgroup) snd_pcm_syncgroups;
47 
48 #define PCM_SG_LOCK()	    mtx_lock(&snd_pcm_syncgroups_mtx)
49 #define PCM_SG_TRYLOCK()    mtx_trylock(&snd_pcm_syncgroups_mtx)
50 #define PCM_SG_UNLOCK()	    mtx_unlock(&snd_pcm_syncgroups_mtx)
51 #define PCM_SG_LOCKASSERT(arg)	mtx_assert(&snd_pcm_syncgroups_mtx, arg)
52 
53 /**
54  * @brief Specifies an audio device sync group
55  */
56 struct pcmchan_syncgroup {
57 	SLIST_ENTRY(pcmchan_syncgroup) link;
58 	SLIST_HEAD(, pcmchan_syncmember) members;
59 	int id; /**< Group identifier; set to address of group. */
60 };
61 
62 /**
63  * @brief Specifies a container for members of a sync group
64  */
65 struct pcmchan_syncmember {
66 	SLIST_ENTRY(pcmchan_syncmember) link;
67 	struct pcmchan_syncgroup *parent; /**< group head */
68 	struct pcm_channel *ch;
69 };
70 
71 #define	CHN_NAMELEN	32
72 struct pcm_channel {
73 	kobj_t methods;
74 
75 	int num;
76 	pid_t pid;
77 	int refcount;
78 	struct pcm_feeder *feeder;
79 	u_int32_t align;
80 
81 	int volume;
82 	int latency;
83 	u_int32_t speed;
84 	u_int32_t format;
85 	u_int32_t flags;
86 	u_int32_t feederflags;
87 	u_int32_t blocks;
88 
89 	int direction;
90 	unsigned int interrupts, xruns, feedcount;
91 	unsigned int timeout;
92 	struct snd_dbuf *bufhard, *bufsoft;
93 	struct snddev_info *parentsnddev;
94 	struct pcm_channel *parentchannel;
95 	void *devinfo;
96 	device_t dev;
97 	char name[CHN_NAMELEN];
98 	struct mtx *lock;
99 	/**
100 	 * Increment,decrement this around operations that temporarily yield
101 	 * lock.
102 	 */
103 	unsigned int inprog;
104 	/**
105 	 * Special channel operations should examine @c inprog after acquiring
106 	 * lock.  If zero, operations may continue.  Else, thread should
107 	 * wait on this cv for previous operation to finish.
108 	 */
109 	struct cv cv;
110 	/**
111 	 * Low water mark for select()/poll().
112 	 *
113 	 * This is initialized to the channel's fragment size, and will be
114 	 * overwritten if a new fragment size is set.  Users may alter this
115 	 * value directly with the @c SNDCTL_DSP_LOW_WATER ioctl.
116 	 */
117 	unsigned int lw;
118 	/**
119 	 * If part of a sync group, this will point to the syncmember
120 	 * container.
121 	 */
122 	struct pcmchan_syncmember *sm;
123 #ifdef OSSV4_EXPERIMENT
124 	u_int16_t lpeak, rpeak;	/**< Peak value from 0-32767. */
125 #endif
126 	SLIST_HEAD(, pcmchan_children) children;
127 };
128 
129 #include "channel_if.h"
130 
131 int chn_reinit(struct pcm_channel *c);
132 int chn_write(struct pcm_channel *c, struct uio *buf);
133 int chn_read(struct pcm_channel *c, struct uio *buf);
134 u_int32_t chn_start(struct pcm_channel *c, int force);
135 int chn_sync(struct pcm_channel *c, int threshold);
136 int chn_flush(struct pcm_channel *c);
137 int chn_poll(struct pcm_channel *c, int ev, struct thread *td);
138 
139 int chn_init(struct pcm_channel *c, void *devinfo, int dir, int direction);
140 int chn_kill(struct pcm_channel *c);
141 int chn_setdir(struct pcm_channel *c, int dir);
142 int chn_reset(struct pcm_channel *c, u_int32_t fmt);
143 int chn_setvolume(struct pcm_channel *c, int left, int right);
144 int chn_setspeed(struct pcm_channel *c, int speed);
145 int chn_setformat(struct pcm_channel *c, u_int32_t fmt);
146 int chn_setblocksize(struct pcm_channel *c, int blkcnt, int blksz);
147 int chn_setlatency(struct pcm_channel *c, int latency);
148 int chn_trigger(struct pcm_channel *c, int go);
149 int chn_getptr(struct pcm_channel *c);
150 struct pcmchan_caps *chn_getcaps(struct pcm_channel *c);
151 u_int32_t chn_getformats(struct pcm_channel *c);
152 
153 void chn_resetbuf(struct pcm_channel *c);
154 void chn_intr(struct pcm_channel *c);
155 int chn_wrfeed(struct pcm_channel *c);
156 int chn_rdfeed(struct pcm_channel *c);
157 int chn_abort(struct pcm_channel *c);
158 
159 void chn_wrupdate(struct pcm_channel *c);
160 void chn_rdupdate(struct pcm_channel *c);
161 
162 int chn_notify(struct pcm_channel *c, u_int32_t flags);
163 void chn_lock(struct pcm_channel *c);
164 void chn_unlock(struct pcm_channel *c);
165 
166 int chn_getrates(struct pcm_channel *c, int **rates);
167 int chn_syncdestroy(struct pcm_channel *c);
168 
169 #ifdef OSSV4_EXPERIMENT
170 int chn_getpeaks(struct pcm_channel *c, int *lpeak, int *rpeak);
171 #endif
172 
173 #ifdef	USING_MUTEX
174 #define CHN_LOCK(c) mtx_lock((struct mtx *)((c)->lock))
175 #define CHN_UNLOCK(c) mtx_unlock((struct mtx *)((c)->lock))
176 #define CHN_TRYLOCK(c) mtx_trylock((struct mtx *)((c)->lock))
177 #define CHN_LOCKASSERT(c) mtx_assert((struct mtx *)((c)->lock), MA_OWNED)
178 #else
179 #define CHN_LOCK(c)
180 #define CHN_UNLOCK(c)
181 #define CHN_TRYLOCK(c)
182 #define CHN_LOCKASSERT(c)
183 #endif
184 
185 int fmtvalid(u_int32_t fmt, u_int32_t *fmtlist);
186 
187 #define AFMTSTR_NONE		0 /* "s16le" */
188 #define AFMTSTR_SIMPLE		1 /* "s16le:s" */
189 #define AFMTSTR_NUM		2 /* "s16le:2" */
190 #define AFMTSTR_FULL		3 /* "s16le:stereo" */
191 
192 #define AFMTSTR_MAXSZ		13 /* include null terminator */
193 
194 #define AFMTSTR_MONO_RETURN	0
195 #define AFMTSTR_STEREO_RETURN	1
196 
197 struct afmtstr_table {
198 	char *fmtstr;
199 	u_int32_t format;
200 };
201 
202 int afmtstr_swap_sign(char *);
203 int afmtstr_swap_endian(char *);
204 u_int32_t afmtstr2afmt(struct afmtstr_table *, const char *, int);
205 u_int32_t afmt2afmtstr(struct afmtstr_table *, u_int32_t, char *, size_t, int, int);
206 
207 extern int chn_latency;
208 extern int chn_latency_profile;
209 extern int report_soft_formats;
210 
211 #define PCMDIR_VIRTUAL 2
212 #define PCMDIR_PLAY 1
213 #define PCMDIR_REC -1
214 
215 #define PCMTRIG_START 1
216 #define PCMTRIG_EMLDMAWR 2
217 #define PCMTRIG_EMLDMARD 3
218 #define PCMTRIG_STOP 0
219 #define PCMTRIG_ABORT -1
220 
221 #define CHN_F_CLOSING           0x00000004  /* a pending close */
222 #define CHN_F_ABORTING          0x00000008  /* a pending abort */
223 #define CHN_F_RUNNING		0x00000010  /* dma is running */
224 #define CHN_F_TRIGGERED		0x00000020
225 #define CHN_F_NOTRIGGER		0x00000040
226 
227 #define CHN_F_BUSY              0x00001000  /* has been opened 	*/
228 #define	CHN_F_HAS_SIZE		0x00002000  /* user set block size */
229 #define CHN_F_NBIO              0x00004000  /* do non-blocking i/o */
230 #define CHN_F_MAPPED		0x00010000  /* has been mmap()ed */
231 #define CHN_F_DEAD		0x00020000
232 #define CHN_F_BADSETTING	0x00040000
233 #define CHN_F_SETBLOCKSIZE	0x00080000
234 #define CHN_F_HAS_VCHAN		0x00100000
235 
236 #define	CHN_F_VIRTUAL		0x10000000  /* not backed by hardware */
237 
238 #define CHN_F_RESET		(CHN_F_BUSY | CHN_F_DEAD | \
239 					CHN_F_HAS_VCHAN | CHN_F_VIRTUAL)
240 
241 
242 #define CHN_N_RATE		0x00000001
243 #define CHN_N_FORMAT		0x00000002
244 #define CHN_N_VOLUME		0x00000004
245 #define CHN_N_BLOCKSIZE		0x00000008
246 #define CHN_N_TRIGGER		0x00000010
247 
248 #define CHN_LATENCY_MIN		0
249 #define CHN_LATENCY_MAX		10
250 #define CHN_LATENCY_DEFAULT	5
251 #define CHN_POLICY_MIN		CHN_LATENCY_MIN
252 #define CHN_POLICY_MAX		CHN_LATENCY_MAX
253 #define CHN_POLICY_DEFAULT	CHN_LATENCY_DEFAULT
254 
255 #define CHN_LATENCY_PROFILE_MIN		0
256 #define CHN_LATENCY_PROFILE_MAX		1
257 #define CHN_LATENCY_PROFILE_DEFAULT	CHN_LATENCY_PROFILE_MAX
258 
259 /*
260  * This should be large enough to hold all pcm data between
261  * tsleeps in chn_{read,write} at the highest sample rate.
262  * (which is usually 48kHz * 16bit * stereo = 192000 bytes/sec)
263  */
264 #define CHN_2NDBUFBLKSIZE	(2 * 1024)
265 /* The total number of blocks per secondary bufhard. */
266 #define CHN_2NDBUFBLKNUM	(32)
267 /* The size of a whole secondary bufhard. */
268 #define CHN_2NDBUFMAXSIZE	(131072)
269 
270 #define CHANNEL_DECLARE(name) static DEFINE_CLASS(name, name ## _methods, sizeof(struct kobj))
271