xref: /freebsd/sys/dev/sound/pcm/channel.c (revision 1e413cf93298b5b97441a21d9a50fdcd0ee9945e)
1 /*-
2  * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
3  * Portions Copyright by Luigi Rizzo - 1997-99
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include "opt_isa.h"
29 
30 #include <dev/sound/pcm/sound.h>
31 
32 #include "feeder_if.h"
33 
34 SND_DECLARE_FILE("$FreeBSD$");
35 
36 int report_soft_formats = 1;
37 SYSCTL_INT(_hw_snd, OID_AUTO, report_soft_formats, CTLFLAG_RW,
38 	&report_soft_formats, 1, "report software-emulated formats");
39 
40 int chn_latency = CHN_LATENCY_DEFAULT;
41 TUNABLE_INT("hw.snd.latency", &chn_latency);
42 
43 static int
44 sysctl_hw_snd_latency(SYSCTL_HANDLER_ARGS)
45 {
46 	int err, val;
47 
48 	val = chn_latency;
49 	err = sysctl_handle_int(oidp, &val, 0, req);
50 	if (err != 0 || req->newptr == NULL)
51 		return err;
52 	if (val < CHN_LATENCY_MIN || val > CHN_LATENCY_MAX)
53 		err = EINVAL;
54 	else
55 		chn_latency = val;
56 
57 	return err;
58 }
59 SYSCTL_PROC(_hw_snd, OID_AUTO, latency, CTLTYPE_INT | CTLFLAG_RW,
60 	0, sizeof(int), sysctl_hw_snd_latency, "I",
61 	"buffering latency (0=low ... 10=high)");
62 
63 int chn_latency_profile = CHN_LATENCY_PROFILE_DEFAULT;
64 TUNABLE_INT("hw.snd.latency_profile", &chn_latency_profile);
65 
66 static int
67 sysctl_hw_snd_latency_profile(SYSCTL_HANDLER_ARGS)
68 {
69 	int err, val;
70 
71 	val = chn_latency_profile;
72 	err = sysctl_handle_int(oidp, &val, 0, req);
73 	if (err != 0 || req->newptr == NULL)
74 		return err;
75 	if (val < CHN_LATENCY_PROFILE_MIN || val > CHN_LATENCY_PROFILE_MAX)
76 		err = EINVAL;
77 	else
78 		chn_latency_profile = val;
79 
80 	return err;
81 }
82 SYSCTL_PROC(_hw_snd, OID_AUTO, latency_profile, CTLTYPE_INT | CTLFLAG_RW,
83 	0, sizeof(int), sysctl_hw_snd_latency_profile, "I",
84 	"buffering latency profile (0=aggresive 1=safe)");
85 
86 static int chn_timeout = CHN_TIMEOUT;
87 TUNABLE_INT("hw.snd.timeout", &chn_timeout);
88 #ifdef SND_DEBUG
89 static int
90 sysctl_hw_snd_timeout(SYSCTL_HANDLER_ARGS)
91 {
92 	int err, val;
93 
94 	val = chn_timeout;
95 	err = sysctl_handle_int(oidp, &val, 0, req);
96 	if (err != 0 || req->newptr == NULL)
97 		return err;
98 	if (val < CHN_TIMEOUT_MIN || val > CHN_TIMEOUT_MAX)
99 		err = EINVAL;
100 	else
101 		chn_timeout = val;
102 
103 	return err;
104 }
105 SYSCTL_PROC(_hw_snd, OID_AUTO, timeout, CTLTYPE_INT | CTLFLAG_RW,
106 	0, sizeof(int), sysctl_hw_snd_timeout, "I",
107 	"interrupt timeout (1 - 10) seconds");
108 #endif
109 
110 static int chn_usefrags = 0;
111 TUNABLE_INT("hw.snd.usefrags", &chn_usefrags);
112 static int chn_syncdelay = -1;
113 TUNABLE_INT("hw.snd.syncdelay", &chn_syncdelay);
114 #ifdef SND_DEBUG
115 SYSCTL_INT(_hw_snd, OID_AUTO, usefrags, CTLFLAG_RW,
116 	&chn_usefrags, 1, "prefer setfragments() over setblocksize()");
117 SYSCTL_INT(_hw_snd, OID_AUTO, syncdelay, CTLFLAG_RW,
118 	&chn_syncdelay, 1,
119 	"append (0-1000) millisecond trailing buffer delay on each sync");
120 #endif
121 
122 /**
123  * @brief Channel sync group lock
124  *
125  * Clients should acquire this lock @b without holding any channel locks
126  * before touching syncgroups or the main syncgroup list.
127  */
128 struct mtx snd_pcm_syncgroups_mtx;
129 MTX_SYSINIT(pcm_syncgroup, &snd_pcm_syncgroups_mtx, "PCM channel sync group lock", MTX_DEF);
130 /**
131  * @brief syncgroups' master list
132  *
133  * Each time a channel syncgroup is created, it's added to this list.  This
134  * list should only be accessed with @sa snd_pcm_syncgroups_mtx held.
135  *
136  * See SNDCTL_DSP_SYNCGROUP for more information.
137  */
138 struct pcm_synclist snd_pcm_syncgroups = SLIST_HEAD_INITIALIZER(head);
139 
140 static int chn_buildfeeder(struct pcm_channel *c);
141 
142 static void
143 chn_lockinit(struct pcm_channel *c, int dir)
144 {
145 	switch (dir) {
146 	case PCMDIR_PLAY:
147 		c->lock = snd_mtxcreate(c->name, "pcm play channel");
148 		cv_init(&c->intr_cv, "pcmwr");
149 		break;
150 	case PCMDIR_PLAY_VIRTUAL:
151 		c->lock = snd_mtxcreate(c->name, "pcm virtual play channel");
152 		cv_init(&c->intr_cv, "pcmwrv");
153 		break;
154 	case PCMDIR_REC:
155 		c->lock = snd_mtxcreate(c->name, "pcm record channel");
156 		cv_init(&c->intr_cv, "pcmrd");
157 		break;
158 	case PCMDIR_REC_VIRTUAL:
159 		c->lock = snd_mtxcreate(c->name, "pcm virtual record channel");
160 		cv_init(&c->intr_cv, "pcmrdv");
161 		break;
162 	case 0:
163 		c->lock = snd_mtxcreate(c->name, "pcm fake channel");
164 		cv_init(&c->intr_cv, "pcmfk");
165 		break;
166 	}
167 
168 	cv_init(&c->cv, "pcmchn");
169 }
170 
171 static void
172 chn_lockdestroy(struct pcm_channel *c)
173 {
174 	CHN_LOCKASSERT(c);
175 
176 	CHN_BROADCAST(&c->cv);
177 	CHN_BROADCAST(&c->intr_cv);
178 
179 	cv_destroy(&c->cv);
180 	cv_destroy(&c->intr_cv);
181 
182 	snd_mtxfree(c->lock);
183 }
184 
185 /**
186  * @brief Determine channel is ready for I/O
187  *
188  * @retval 1 = ready for I/O
189  * @retval 0 = not ready for I/O
190  */
191 static int
192 chn_polltrigger(struct pcm_channel *c)
193 {
194 	struct snd_dbuf *bs = c->bufsoft;
195 	unsigned amt, lim;
196 
197 	CHN_LOCKASSERT(c);
198 	if (c->flags & CHN_F_MAPPED) {
199 		if (sndbuf_getprevblocks(bs) == 0)
200 			return 1;
201 		else
202 			return (sndbuf_getblocks(bs) > sndbuf_getprevblocks(bs))? 1 : 0;
203 	} else {
204 		amt = (c->direction == PCMDIR_PLAY)? sndbuf_getfree(bs) : sndbuf_getready(bs);
205 #if 0
206 		lim = (c->flags & CHN_F_HAS_SIZE)? sndbuf_getblksz(bs) : 1;
207 #endif
208 		lim = c->lw;
209 		return (amt >= lim) ? 1 : 0;
210 	}
211 	return 0;
212 }
213 
214 static int
215 chn_pollreset(struct pcm_channel *c)
216 {
217 	struct snd_dbuf *bs = c->bufsoft;
218 
219 	CHN_LOCKASSERT(c);
220 	sndbuf_updateprevtotal(bs);
221 	return 1;
222 }
223 
224 static void
225 chn_wakeup(struct pcm_channel *c)
226 {
227 	struct snd_dbuf *bs;
228 	struct pcm_channel *ch;
229 
230 	CHN_LOCKASSERT(c);
231 
232 	bs = c->bufsoft;
233 
234 	if (CHN_EMPTY(c, children.busy)) {
235 		if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c))
236 			selwakeuppri(sndbuf_getsel(bs), PRIBIO);
237 		if (c->flags & CHN_F_SLEEPING) {
238 			/*
239 			 * Ok, I can just panic it right here since it is
240 			 * quite obvious that we never allow multiple waiters
241 			 * from userland. I'm too generous...
242 			 */
243 			CHN_BROADCAST(&c->intr_cv);
244 		}
245 	} else {
246 		CHN_FOREACH(ch, c, children.busy) {
247 			CHN_LOCK(ch);
248 			chn_wakeup(ch);
249 			CHN_UNLOCK(ch);
250 		}
251 	}
252 }
253 
254 static int
255 chn_sleep(struct pcm_channel *c, int timeout)
256 {
257 	int ret;
258 
259 	CHN_LOCKASSERT(c);
260 
261 	if (c->flags & CHN_F_DEAD)
262 		return (EINVAL);
263 
264 	c->flags |= CHN_F_SLEEPING;
265 	ret = cv_timedwait_sig(&c->intr_cv, c->lock, timeout);
266 	c->flags &= ~CHN_F_SLEEPING;
267 
268 	return ((c->flags & CHN_F_DEAD) ? EINVAL : ret);
269 }
270 
271 /*
272  * chn_dmaupdate() tracks the status of a dma transfer,
273  * updating pointers.
274  */
275 
276 static unsigned int
277 chn_dmaupdate(struct pcm_channel *c)
278 {
279 	struct snd_dbuf *b = c->bufhard;
280 	unsigned int delta, old, hwptr, amt;
281 
282 	KASSERT(sndbuf_getsize(b) > 0, ("bufsize == 0"));
283 	CHN_LOCKASSERT(c);
284 
285 	old = sndbuf_gethwptr(b);
286 	hwptr = chn_getptr(c);
287 	delta = (sndbuf_getsize(b) + hwptr - old) % sndbuf_getsize(b);
288 	sndbuf_sethwptr(b, hwptr);
289 
290 	if (c->direction == PCMDIR_PLAY) {
291 		amt = min(delta, sndbuf_getready(b));
292 		amt -= amt % sndbuf_getbps(b);
293 		if (amt > 0)
294 			sndbuf_dispose(b, NULL, amt);
295 	} else {
296 		amt = min(delta, sndbuf_getfree(b));
297 		amt -= amt % sndbuf_getbps(b);
298 		if (amt > 0)
299 		       sndbuf_acquire(b, NULL, amt);
300 	}
301 	if (snd_verbose > 3 && CHN_STARTED(c) && delta == 0) {
302 		device_printf(c->dev, "WARNING: %s DMA completion "
303 			"too fast/slow ! hwptr=%u, old=%u "
304 			"delta=%u amt=%u ready=%u free=%u\n",
305 			CHN_DIRSTR(c), hwptr, old, delta, amt,
306 			sndbuf_getready(b), sndbuf_getfree(b));
307 	}
308 
309 	return delta;
310 }
311 
312 void
313 chn_wrupdate(struct pcm_channel *c)
314 {
315 	int ret;
316 
317 	CHN_LOCKASSERT(c);
318 	KASSERT(c->direction == PCMDIR_PLAY, ("chn_wrupdate on bad channel"));
319 
320 	if ((c->flags & (CHN_F_MAPPED | CHN_F_VIRTUAL)) || CHN_STOPPED(c))
321 		return;
322 	chn_dmaupdate(c);
323 	ret = chn_wrfeed(c);
324 	/* tell the driver we've updated the primary buffer */
325 	chn_trigger(c, PCMTRIG_EMLDMAWR);
326 	DEB(if (ret)
327 		printf("chn_wrupdate: chn_wrfeed returned %d\n", ret);)
328 
329 }
330 
331 int
332 chn_wrfeed(struct pcm_channel *c)
333 {
334     	struct snd_dbuf *b = c->bufhard;
335     	struct snd_dbuf *bs = c->bufsoft;
336 	unsigned int ret, amt;
337 
338 	CHN_LOCKASSERT(c);
339 
340 	if ((c->flags & CHN_F_MAPPED) && !(c->flags & CHN_F_CLOSING))
341 		sndbuf_acquire(bs, NULL, sndbuf_getfree(bs));
342 
343 	amt = sndbuf_getfree(b);
344 
345 	ret = (amt > 0) ? sndbuf_feed(bs, b, c, c->feeder, amt) : ENOSPC;
346 	/*
347 	 * Possible xruns. There should be no empty space left in buffer.
348 	 */
349 	if (sndbuf_getfree(b) > 0)
350 		c->xruns++;
351 
352 	if (sndbuf_getfree(b) < amt)
353 		chn_wakeup(c);
354 
355 	return ret;
356 }
357 
358 static void
359 chn_wrintr(struct pcm_channel *c)
360 {
361 	int ret;
362 
363 	CHN_LOCKASSERT(c);
364 	/* update pointers in primary buffer */
365 	chn_dmaupdate(c);
366 	/* ...and feed from secondary to primary */
367 	ret = chn_wrfeed(c);
368 	/* tell the driver we've updated the primary buffer */
369 	chn_trigger(c, PCMTRIG_EMLDMAWR);
370 	DEB(if (ret)
371 		printf("chn_wrintr: chn_wrfeed returned %d\n", ret);)
372 }
373 
374 /*
375  * user write routine - uiomove data into secondary buffer, trigger if necessary
376  * if blocking, sleep, rinse and repeat.
377  *
378  * called externally, so must handle locking
379  */
380 
381 int
382 chn_write(struct pcm_channel *c, struct uio *buf)
383 {
384 	struct snd_dbuf *bs = c->bufsoft;
385 	void *off;
386 	int ret, timeout, sz, t, p;
387 
388 	CHN_LOCKASSERT(c);
389 
390 	ret = 0;
391 	timeout = chn_timeout * hz;
392 
393 	while (ret == 0 && buf->uio_resid > 0) {
394 		sz = min(buf->uio_resid, sndbuf_getfree(bs));
395 		if (sz > 0) {
396 			/*
397 			 * The following assumes that the free space in
398 			 * the buffer can never be less around the
399 			 * unlock-uiomove-lock sequence.
400 			 */
401 			while (ret == 0 && sz > 0) {
402 				p = sndbuf_getfreeptr(bs);
403 				t = min(sz, sndbuf_getsize(bs) - p);
404 				off = sndbuf_getbufofs(bs, p);
405 				CHN_UNLOCK(c);
406 				ret = uiomove(off, t, buf);
407 				CHN_LOCK(c);
408 				sz -= t;
409 				sndbuf_acquire(bs, NULL, t);
410 			}
411 			ret = 0;
412 			if (CHN_STOPPED(c) && !(c->flags & CHN_F_NOTRIGGER)) {
413 				ret = chn_start(c, 0);
414 				if (ret != 0)
415 					c->flags |= CHN_F_DEAD;
416 			}
417 		} else if (c->flags & (CHN_F_NBIO | CHN_F_NOTRIGGER)) {
418 			/**
419 			 * @todo Evaluate whether EAGAIN is truly desirable.
420 			 * 	 4Front drivers behave like this, but I'm
421 			 * 	 not sure if it at all violates the "write
422 			 * 	 should be allowed to block" model.
423 			 *
424 			 * 	 The idea is that, while set with CHN_F_NOTRIGGER,
425 			 * 	 a channel isn't playing, *but* without this we
426 			 * 	 end up with "interrupt timeout / channel dead".
427 			 */
428 			ret = EAGAIN;
429 		} else {
430    			ret = chn_sleep(c, timeout);
431 			if (ret == EAGAIN) {
432 				ret = EINVAL;
433 				c->flags |= CHN_F_DEAD;
434 				printf("%s: play interrupt timeout, "
435 				    "channel dead\n", c->name);
436 			} else if (ret == ERESTART || ret == EINTR)
437 				c->flags |= CHN_F_ABORTING;
438 		}
439 	}
440 
441 	return (ret);
442 }
443 
444 /*
445  * Feed new data from the read buffer. Can be called in the bottom half.
446  */
447 int
448 chn_rdfeed(struct pcm_channel *c)
449 {
450     	struct snd_dbuf *b = c->bufhard;
451     	struct snd_dbuf *bs = c->bufsoft;
452 	unsigned int ret, amt;
453 
454 	CHN_LOCKASSERT(c);
455 
456 	if (c->flags & CHN_F_MAPPED)
457 		sndbuf_dispose(bs, NULL, sndbuf_getready(bs));
458 
459 	amt = sndbuf_getfree(bs);
460 	ret = (amt > 0) ? sndbuf_feed(b, bs, c, c->feeder, amt) : ENOSPC;
461 
462 	amt = sndbuf_getready(b);
463 	if (amt > 0) {
464 		c->xruns++;
465 		sndbuf_dispose(b, NULL, amt);
466 	}
467 
468 	if (sndbuf_getready(bs) > 0)
469 		chn_wakeup(c);
470 
471 	return ret;
472 }
473 
474 void
475 chn_rdupdate(struct pcm_channel *c)
476 {
477 	int ret;
478 
479 	CHN_LOCKASSERT(c);
480 	KASSERT(c->direction == PCMDIR_REC, ("chn_rdupdate on bad channel"));
481 
482 	if ((c->flags & (CHN_F_MAPPED | CHN_F_VIRTUAL)) || CHN_STOPPED(c))
483 		return;
484 	chn_trigger(c, PCMTRIG_EMLDMARD);
485 	chn_dmaupdate(c);
486 	ret = chn_rdfeed(c);
487 	DEB(if (ret)
488 		printf("chn_rdfeed: %d\n", ret);)
489 
490 }
491 
492 /* read interrupt routine. Must be called with interrupts blocked. */
493 static void
494 chn_rdintr(struct pcm_channel *c)
495 {
496 	int ret;
497 
498 	CHN_LOCKASSERT(c);
499 	/* tell the driver to update the primary buffer if non-dma */
500 	chn_trigger(c, PCMTRIG_EMLDMARD);
501 	/* update pointers in primary buffer */
502 	chn_dmaupdate(c);
503 	/* ...and feed from primary to secondary */
504 	ret = chn_rdfeed(c);
505 }
506 
507 /*
508  * user read routine - trigger if necessary, uiomove data from secondary buffer
509  * if blocking, sleep, rinse and repeat.
510  *
511  * called externally, so must handle locking
512  */
513 
514 int
515 chn_read(struct pcm_channel *c, struct uio *buf)
516 {
517 	struct snd_dbuf *bs = c->bufsoft;
518 	void *off;
519 	int ret, timeout, sz, t, p;
520 
521 	CHN_LOCKASSERT(c);
522 
523 	if (CHN_STOPPED(c) && !(c->flags & CHN_F_NOTRIGGER)) {
524 		ret = chn_start(c, 0);
525 		if (ret != 0) {
526 			c->flags |= CHN_F_DEAD;
527 			return (ret);
528 		}
529 	}
530 
531 	ret = 0;
532 	timeout = chn_timeout * hz;
533 
534 	while (ret == 0 && buf->uio_resid > 0) {
535 		sz = min(buf->uio_resid, sndbuf_getready(bs));
536 		if (sz > 0) {
537 			/*
538 			 * The following assumes that the free space in
539 			 * the buffer can never be less around the
540 			 * unlock-uiomove-lock sequence.
541 			 */
542 			while (ret == 0 && sz > 0) {
543 				p = sndbuf_getreadyptr(bs);
544 				t = min(sz, sndbuf_getsize(bs) - p);
545 				off = sndbuf_getbufofs(bs, p);
546 				CHN_UNLOCK(c);
547 				ret = uiomove(off, t, buf);
548 				CHN_LOCK(c);
549 				sz -= t;
550 				sndbuf_dispose(bs, NULL, t);
551 			}
552 			ret = 0;
553 		} else if (c->flags & (CHN_F_NBIO | CHN_F_NOTRIGGER))
554 			ret = EAGAIN;
555 		else {
556    			ret = chn_sleep(c, timeout);
557 			if (ret == EAGAIN) {
558 				ret = EINVAL;
559 				c->flags |= CHN_F_DEAD;
560 				printf("%s: record interrupt timeout, "
561 				    "channel dead\n", c->name);
562 			} else if (ret == ERESTART || ret == EINTR)
563 				c->flags |= CHN_F_ABORTING;
564 		}
565 	}
566 
567 	return (ret);
568 }
569 
570 void
571 chn_intr(struct pcm_channel *c)
572 {
573 	CHN_LOCK(c);
574 	c->interrupts++;
575 	if (c->direction == PCMDIR_PLAY)
576 		chn_wrintr(c);
577 	else
578 		chn_rdintr(c);
579 	CHN_UNLOCK(c);
580 }
581 
582 u_int32_t
583 chn_start(struct pcm_channel *c, int force)
584 {
585 	u_int32_t i, j;
586 	struct snd_dbuf *b = c->bufhard;
587 	struct snd_dbuf *bs = c->bufsoft;
588 	int err;
589 
590 	CHN_LOCKASSERT(c);
591 	/* if we're running, or if we're prevented from triggering, bail */
592 	if (CHN_STARTED(c) || ((c->flags & CHN_F_NOTRIGGER) && !force))
593 		return (EINVAL);
594 
595 	err = 0;
596 
597 	if (force) {
598 		i = 1;
599 		j = 0;
600 	} else {
601 		if (c->direction == PCMDIR_REC) {
602 			i = sndbuf_getfree(bs);
603 			j = (i > 0) ? 1 : sndbuf_getready(b);
604 		} else {
605 			if (sndbuf_getfree(bs) == 0) {
606 				i = 1;
607 				j = 0;
608 			} else {
609 				struct snd_dbuf *pb;
610 
611 				pb = CHN_BUF_PARENT(c, b);
612 				i = sndbuf_xbytes(sndbuf_getready(bs), bs, pb);
613 				j = sndbuf_getbps(pb);
614 			}
615 		}
616 		if (snd_verbose > 3 && CHN_EMPTY(c, children))
617 			printf("%s: %s (%s) threshold i=%d j=%d\n",
618 			    __func__, CHN_DIRSTR(c),
619 			    (c->flags & CHN_F_VIRTUAL) ? "virtual" : "hardware",
620 			    i, j);
621 	}
622 
623 	if (i >= j) {
624 		c->flags |= CHN_F_TRIGGERED;
625 		sndbuf_setrun(b, 1);
626 		c->feedcount = (c->flags & CHN_F_CLOSING) ? 2 : 0;
627 		c->interrupts = 0;
628 		c->xruns = 0;
629 		if (c->direction == PCMDIR_PLAY && c->parentchannel == NULL) {
630 			sndbuf_fillsilence(b);
631 			if (snd_verbose > 3)
632 				printf("%s: %s starting! (%s) (ready=%d "
633 				    "force=%d i=%d j=%d intrtimeout=%u "
634 				    "latency=%dms)\n",
635 				    __func__,
636 				    (c->flags & CHN_F_HAS_VCHAN) ?
637 				    "VCHAN" : "HW",
638 				    (c->flags & CHN_F_CLOSING) ? "closing" :
639 				    "running",
640 				    sndbuf_getready(b),
641 				    force, i, j, c->timeout,
642 				    (sndbuf_getsize(b) * 1000) /
643 				    (sndbuf_getbps(b) * sndbuf_getspd(b)));
644 		}
645 		err = chn_trigger(c, PCMTRIG_START);
646 	}
647 
648 	return (err);
649 }
650 
651 void
652 chn_resetbuf(struct pcm_channel *c)
653 {
654 	struct snd_dbuf *b = c->bufhard;
655 	struct snd_dbuf *bs = c->bufsoft;
656 
657 	c->blocks = 0;
658 	sndbuf_reset(b);
659 	sndbuf_reset(bs);
660 }
661 
662 /*
663  * chn_sync waits until the space in the given channel goes above
664  * a threshold. The threshold is checked against fl or rl respectively.
665  * Assume that the condition can become true, do not check here...
666  */
667 int
668 chn_sync(struct pcm_channel *c, int threshold)
669 {
670     	struct snd_dbuf *b, *bs;
671 	int ret, count, hcount, minflush, resid, residp, syncdelay, blksz;
672 	u_int32_t cflag;
673 
674 	CHN_LOCKASSERT(c);
675 
676 	if (c->direction != PCMDIR_PLAY)
677 		return (EINVAL);
678 
679 	bs = c->bufsoft;
680 
681 	if ((c->flags & (CHN_F_DEAD | CHN_F_ABORTING)) ||
682 	    (threshold < 1 && sndbuf_getready(bs) < 1))
683 		return (0);
684 
685 	/* if we haven't yet started and nothing is buffered, else start*/
686 	if (CHN_STOPPED(c)) {
687 		if (threshold > 0 || sndbuf_getready(bs) > 0) {
688 			ret = chn_start(c, 1);
689 			if (ret != 0)
690 				return (ret);
691 		} else
692 			return (0);
693 	}
694 
695 	b = CHN_BUF_PARENT(c, c->bufhard);
696 
697 	minflush = threshold + sndbuf_xbytes(sndbuf_getready(b), b, bs);
698 
699 	syncdelay = chn_syncdelay;
700 
701 	if (syncdelay < 0 && (threshold > 0 || sndbuf_getready(bs) > 0))
702 		minflush += sndbuf_xbytes(sndbuf_getsize(b), b, bs);
703 
704 	/*
705 	 * Append (0-1000) millisecond trailing buffer (if needed)
706 	 * for slower / high latency hardwares (notably USB audio)
707 	 * to avoid audible truncation.
708 	 */
709 	if (syncdelay > 0)
710 		minflush += (sndbuf_getbps(bs) * sndbuf_getspd(bs) *
711 		    ((syncdelay > 1000) ? 1000 : syncdelay)) / 1000;
712 
713 	minflush -= minflush % sndbuf_getbps(bs);
714 
715 	if (minflush > 0) {
716 		threshold = min(minflush, sndbuf_getfree(bs));
717 		sndbuf_clear(bs, threshold);
718 		sndbuf_acquire(bs, NULL, threshold);
719 		minflush -= threshold;
720 	}
721 
722 	resid = sndbuf_getready(bs);
723 	residp = resid;
724 	blksz = sndbuf_getblksz(b);
725 	if (blksz < 1) {
726 		printf("%s: WARNING: blksz < 1 ! maxsize=%d [%d/%d/%d]\n",
727 		    __func__, sndbuf_getmaxsize(b), sndbuf_getsize(b),
728 		    sndbuf_getblksz(b), sndbuf_getblkcnt(b));
729 		if (sndbuf_getblkcnt(b) > 0)
730 			blksz = sndbuf_getsize(b) / sndbuf_getblkcnt(b);
731 		if (blksz < 1)
732 			blksz = 1;
733 	}
734 	count = sndbuf_xbytes(minflush + resid, bs, b) / blksz;
735 	hcount = count;
736 	ret = 0;
737 
738 	if (snd_verbose > 3)
739 		printf("%s: [begin] timeout=%d count=%d "
740 		    "minflush=%d resid=%d\n", __func__, c->timeout, count,
741 		    minflush, resid);
742 
743 	cflag = c->flags & CHN_F_CLOSING;
744 	c->flags |= CHN_F_CLOSING;
745 	while (count > 0 && (resid > 0 || minflush > 0)) {
746 		ret = chn_sleep(c, c->timeout);
747     		if (ret == ERESTART || ret == EINTR) {
748 			c->flags |= CHN_F_ABORTING;
749 			break;
750 		} else if (ret == 0 || ret == EAGAIN) {
751 			resid = sndbuf_getready(bs);
752 			if (resid == residp) {
753 				--count;
754 				if (snd_verbose > 3)
755 					printf("%s: [stalled] timeout=%d "
756 					    "count=%d hcount=%d "
757 					    "resid=%d minflush=%d\n",
758 					    __func__, c->timeout, count,
759 					    hcount, resid, minflush);
760 			} else if (resid < residp && count < hcount) {
761 				++count;
762 				if (snd_verbose > 3)
763 					printf("%s: [resume] timeout=%d "
764 					    "count=%d hcount=%d "
765 					    "resid=%d minflush=%d\n",
766 					    __func__, c->timeout, count,
767 					    hcount, resid, minflush);
768 			}
769 			if (minflush > 0 && sndbuf_getfree(bs) > 0) {
770 				threshold = min(minflush,
771 				    sndbuf_getfree(bs));
772 				sndbuf_clear(bs, threshold);
773 				sndbuf_acquire(bs, NULL, threshold);
774 				resid = sndbuf_getready(bs);
775 				minflush -= threshold;
776 			}
777 			residp = resid;
778 		} else
779 			break;
780 	}
781 	c->flags &= ~CHN_F_CLOSING;
782 	c->flags |= cflag;
783 
784 	if (snd_verbose > 3)
785 		printf("%s: timeout=%d count=%d hcount=%d resid=%d residp=%d "
786 		    "minflush=%d ret=%d\n",
787 		    __func__, c->timeout, count, hcount, resid, residp,
788 		    minflush, ret);
789 
790     	return (0);
791 }
792 
793 /* called externally, handle locking */
794 int
795 chn_poll(struct pcm_channel *c, int ev, struct thread *td)
796 {
797 	struct snd_dbuf *bs = c->bufsoft;
798 	int ret;
799 
800 	CHN_LOCKASSERT(c);
801     	if (!(c->flags & (CHN_F_MAPPED | CHN_F_TRIGGERED))) {
802 		ret = chn_start(c, 1);
803 		if (ret != 0)
804 			return (0);
805 	}
806 	ret = 0;
807 	if (chn_polltrigger(c) && chn_pollreset(c))
808 		ret = ev;
809 	else
810 		selrecord(td, sndbuf_getsel(bs));
811 	return (ret);
812 }
813 
814 /*
815  * chn_abort terminates a running dma transfer.  it may sleep up to 200ms.
816  * it returns the number of bytes that have not been transferred.
817  *
818  * called from: dsp_close, dsp_ioctl, with channel locked
819  */
820 int
821 chn_abort(struct pcm_channel *c)
822 {
823     	int missing = 0;
824     	struct snd_dbuf *b = c->bufhard;
825     	struct snd_dbuf *bs = c->bufsoft;
826 
827 	CHN_LOCKASSERT(c);
828 	if (CHN_STOPPED(c))
829 		return 0;
830 	c->flags |= CHN_F_ABORTING;
831 
832 	c->flags &= ~CHN_F_TRIGGERED;
833 	/* kill the channel */
834 	chn_trigger(c, PCMTRIG_ABORT);
835 	sndbuf_setrun(b, 0);
836 	if (!(c->flags & CHN_F_VIRTUAL))
837 		chn_dmaupdate(c);
838     	missing = sndbuf_getready(bs);
839 
840 	c->flags &= ~CHN_F_ABORTING;
841 	return missing;
842 }
843 
844 /*
845  * this routine tries to flush the dma transfer. It is called
846  * on a close of a playback channel.
847  * first, if there is data in the buffer, but the dma has not yet
848  * begun, we need to start it.
849  * next, we wait for the play buffer to drain
850  * finally, we stop the dma.
851  *
852  * called from: dsp_close, not valid for record channels.
853  */
854 
855 int
856 chn_flush(struct pcm_channel *c)
857 {
858     	struct snd_dbuf *b = c->bufhard;
859 
860 	CHN_LOCKASSERT(c);
861 	KASSERT(c->direction == PCMDIR_PLAY, ("chn_flush on bad channel"));
862     	DEB(printf("chn_flush: c->flags 0x%08x\n", c->flags));
863 
864 	c->flags |= CHN_F_CLOSING;
865 	chn_sync(c, 0);
866 	c->flags &= ~CHN_F_TRIGGERED;
867 	/* kill the channel */
868 	chn_trigger(c, PCMTRIG_ABORT);
869 	sndbuf_setrun(b, 0);
870 
871     	c->flags &= ~CHN_F_CLOSING;
872     	return 0;
873 }
874 
875 int
876 fmtvalid(u_int32_t fmt, u_int32_t *fmtlist)
877 {
878 	int i;
879 
880 	for (i = 0; fmtlist[i]; i++)
881 		if (fmt == fmtlist[i])
882 			return 1;
883 	return 0;
884 }
885 
886 static struct afmtstr_table default_afmtstr_table[] = {
887 	{  "alaw", AFMT_A_LAW  }, { "mulaw", AFMT_MU_LAW },
888 	{    "u8", AFMT_U8     }, {    "s8", AFMT_S8     },
889 	{ "s16le", AFMT_S16_LE }, { "s16be", AFMT_S16_BE },
890 	{ "u16le", AFMT_U16_LE }, { "u16be", AFMT_U16_BE },
891 	{ "s24le", AFMT_S24_LE }, { "s24be", AFMT_S24_BE },
892 	{ "u24le", AFMT_U24_LE }, { "u24be", AFMT_U24_BE },
893 	{ "s32le", AFMT_S32_LE }, { "s32be", AFMT_S32_BE },
894 	{ "u32le", AFMT_U32_LE }, { "u32be", AFMT_U32_BE },
895 	{    NULL, 0           },
896 };
897 
898 int
899 afmtstr_swap_sign(char *s)
900 {
901 	if (s == NULL || strlen(s) < 2) /* full length of "s8" */
902 		return 0;
903 	if (*s == 's')
904 		*s = 'u';
905 	else if (*s == 'u')
906 		*s = 's';
907 	else
908 		return 0;
909 	return 1;
910 }
911 
912 int
913 afmtstr_swap_endian(char *s)
914 {
915 	if (s == NULL || strlen(s) < 5) /* full length of "s16le" */
916 		return 0;
917 	if (s[3] == 'l')
918 		s[3] = 'b';
919 	else if (s[3] == 'b')
920 		s[3] = 'l';
921 	else
922 		return 0;
923 	return 1;
924 }
925 
926 u_int32_t
927 afmtstr2afmt(struct afmtstr_table *tbl, const char *s, int stereo)
928 {
929 	size_t fsz, sz;
930 
931 	sz = (s == NULL) ? 0 : strlen(s);
932 
933 	if (sz > 1) {
934 
935 		if (tbl == NULL)
936 			tbl = default_afmtstr_table;
937 
938 		for (; tbl->fmtstr != NULL; tbl++) {
939 			fsz = strlen(tbl->fmtstr);
940 			if (sz < fsz)
941 				continue;
942 			if (strncmp(s, tbl->fmtstr, fsz) != 0)
943 				continue;
944 			if (fsz == sz)
945 				return tbl->format |
946 					    ((stereo) ? AFMT_STEREO : 0);
947 			if ((sz - fsz) < 2 || s[fsz] != ':')
948 				break;
949 			/*
950 			 * For now, just handle mono/stereo.
951 			 */
952 			if ((s[fsz + 2] == '\0' && (s[fsz + 1] == 'm' ||
953 				    s[fsz + 1] == '1')) ||
954 				    strcmp(s + fsz + 1, "mono") == 0)
955 				return tbl->format;
956 			if ((s[fsz + 2] == '\0' && (s[fsz + 1] == 's' ||
957 				    s[fsz + 1] == '2')) ||
958 				    strcmp(s + fsz + 1, "stereo") == 0)
959 				return tbl->format | AFMT_STEREO;
960 			break;
961 		}
962 	}
963 
964 	return 0;
965 }
966 
967 u_int32_t
968 afmt2afmtstr(struct afmtstr_table *tbl, u_int32_t afmt, char *dst,
969 					size_t len, int type, int stereo)
970 {
971 	u_int32_t fmt = 0;
972 	char *fmtstr = NULL, *tag = "";
973 
974 	if (tbl == NULL)
975 		tbl = default_afmtstr_table;
976 
977 	for (; tbl->format != 0; tbl++) {
978 		if (tbl->format == 0)
979 			break;
980 		if ((afmt & ~AFMT_STEREO) != tbl->format)
981 			continue;
982 		fmt = afmt;
983 		fmtstr = tbl->fmtstr;
984 		break;
985 	}
986 
987 	if (fmt != 0 && fmtstr != NULL && dst != NULL && len > 0) {
988 		strlcpy(dst, fmtstr, len);
989 		switch (type) {
990 		case AFMTSTR_SIMPLE:
991 			tag = (fmt & AFMT_STEREO) ? ":s" : ":m";
992 			break;
993 		case AFMTSTR_NUM:
994 			tag = (fmt & AFMT_STEREO) ? ":2" : ":1";
995 			break;
996 		case AFMTSTR_FULL:
997 			tag = (fmt & AFMT_STEREO) ? ":stereo" : ":mono";
998 			break;
999 		case AFMTSTR_NONE:
1000 		default:
1001 			break;
1002 		}
1003 		if (strlen(tag) > 0 && ((stereo && !(fmt & AFMT_STEREO)) || \
1004 			    (!stereo && (fmt & AFMT_STEREO))))
1005 			strlcat(dst, tag, len);
1006 	}
1007 
1008 	return fmt;
1009 }
1010 
1011 int
1012 chn_reset(struct pcm_channel *c, u_int32_t fmt)
1013 {
1014 	int hwspd, r;
1015 
1016 	CHN_LOCKASSERT(c);
1017 	c->feedcount = 0;
1018 	c->flags &= CHN_F_RESET;
1019 	c->interrupts = 0;
1020 	c->timeout = 1;
1021 	c->xruns = 0;
1022 
1023 	r = CHANNEL_RESET(c->methods, c->devinfo);
1024 	if (fmt != 0) {
1025 #if 0
1026 		hwspd = DSP_DEFAULT_SPEED;
1027 		/* only do this on a record channel until feederbuilder works */
1028 		if (c->direction == PCMDIR_REC)
1029 			RANGE(hwspd, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
1030 		c->speed = hwspd;
1031 #endif
1032 		hwspd = chn_getcaps(c)->minspeed;
1033 		c->speed = hwspd;
1034 
1035 		if (r == 0)
1036 			r = chn_setformat(c, fmt);
1037 		if (r == 0)
1038 			r = chn_setspeed(c, hwspd);
1039 #if 0
1040 		if (r == 0)
1041 			r = chn_setvolume(c, 100, 100);
1042 #endif
1043 	}
1044 	if (r == 0)
1045 		r = chn_setlatency(c, chn_latency);
1046 	if (r == 0) {
1047 		chn_resetbuf(c);
1048 		r = CHANNEL_RESETDONE(c->methods, c->devinfo);
1049 	}
1050 	return r;
1051 }
1052 
1053 int
1054 chn_init(struct pcm_channel *c, void *devinfo, int dir, int direction)
1055 {
1056 	struct feeder_class *fc;
1057 	struct snd_dbuf *b, *bs;
1058 	int ret;
1059 
1060 	if (chn_timeout < CHN_TIMEOUT_MIN || chn_timeout > CHN_TIMEOUT_MAX)
1061 		chn_timeout = CHN_TIMEOUT;
1062 
1063 	chn_lockinit(c, dir);
1064 
1065 	b = NULL;
1066 	bs = NULL;
1067 	CHN_INIT(c, children);
1068 	CHN_INIT(c, children.busy);
1069 	c->devinfo = NULL;
1070 	c->feeder = NULL;
1071 	c->latency = -1;
1072 	c->timeout = 1;
1073 
1074 	ret = ENOMEM;
1075 	b = sndbuf_create(c->dev, c->name, "primary", c);
1076 	if (b == NULL)
1077 		goto out;
1078 	bs = sndbuf_create(c->dev, c->name, "secondary", c);
1079 	if (bs == NULL)
1080 		goto out;
1081 
1082 	CHN_LOCK(c);
1083 
1084 	ret = EINVAL;
1085 	fc = feeder_getclass(NULL);
1086 	if (fc == NULL)
1087 		goto out;
1088 	if (chn_addfeeder(c, fc, NULL))
1089 		goto out;
1090 
1091 	/*
1092 	 * XXX - sndbuf_setup() & sndbuf_resize() expect to be called
1093 	 *	 with the channel unlocked because they are also called
1094 	 *	 from driver methods that don't know about locking
1095 	 */
1096 	CHN_UNLOCK(c);
1097 	sndbuf_setup(bs, NULL, 0);
1098 	CHN_LOCK(c);
1099 	c->bufhard = b;
1100 	c->bufsoft = bs;
1101 	c->flags = 0;
1102 	c->feederflags = 0;
1103 	c->sm = NULL;
1104 
1105 	ret = ENODEV;
1106 	CHN_UNLOCK(c); /* XXX - Unlock for CHANNEL_INIT() malloc() call */
1107 	c->devinfo = CHANNEL_INIT(c->methods, devinfo, b, c, direction);
1108 	CHN_LOCK(c);
1109 	if (c->devinfo == NULL)
1110 		goto out;
1111 
1112 	ret = ENOMEM;
1113 	if ((sndbuf_getsize(b) == 0) && ((c->flags & CHN_F_VIRTUAL) == 0))
1114 		goto out;
1115 
1116 	ret = chn_setdir(c, direction);
1117 	if (ret)
1118 		goto out;
1119 
1120 	ret = sndbuf_setfmt(b, AFMT_U8);
1121 	if (ret)
1122 		goto out;
1123 
1124 	ret = sndbuf_setfmt(bs, AFMT_U8);
1125 	if (ret)
1126 		goto out;
1127 
1128 	/**
1129 	 * @todo Should this be moved somewhere else?  The primary buffer
1130 	 * 	 is allocated by the driver or via DMA map setup, and tmpbuf
1131 	 * 	 seems to only come into existence in sndbuf_resize().
1132 	 */
1133 	if (c->direction == PCMDIR_PLAY) {
1134 		bs->sl = sndbuf_getmaxsize(bs);
1135 		bs->shadbuf = malloc(bs->sl, M_DEVBUF, M_NOWAIT);
1136 		if (bs->shadbuf == NULL) {
1137 			ret = ENOMEM;
1138 			goto out;
1139 		}
1140 	}
1141 
1142 out:
1143 	CHN_UNLOCK(c);
1144 	if (ret) {
1145 		if (c->devinfo) {
1146 			if (CHANNEL_FREE(c->methods, c->devinfo))
1147 				sndbuf_free(b);
1148 		}
1149 		if (bs)
1150 			sndbuf_destroy(bs);
1151 		if (b)
1152 			sndbuf_destroy(b);
1153 		CHN_LOCK(c);
1154 		c->flags |= CHN_F_DEAD;
1155 		chn_lockdestroy(c);
1156 
1157 		return ret;
1158 	}
1159 
1160 	return 0;
1161 }
1162 
1163 int
1164 chn_kill(struct pcm_channel *c)
1165 {
1166     	struct snd_dbuf *b = c->bufhard;
1167     	struct snd_dbuf *bs = c->bufsoft;
1168 
1169 	if (CHN_STARTED(c)) {
1170 		CHN_LOCK(c);
1171 		chn_trigger(c, PCMTRIG_ABORT);
1172 		CHN_UNLOCK(c);
1173 	}
1174 	while (chn_removefeeder(c) == 0)
1175 		;
1176 	if (CHANNEL_FREE(c->methods, c->devinfo))
1177 		sndbuf_free(b);
1178 	sndbuf_destroy(bs);
1179 	sndbuf_destroy(b);
1180 	CHN_LOCK(c);
1181 	c->flags |= CHN_F_DEAD;
1182 	chn_lockdestroy(c);
1183 
1184 	return (0);
1185 }
1186 
1187 int
1188 chn_setdir(struct pcm_channel *c, int dir)
1189 {
1190 #ifdef DEV_ISA
1191     	struct snd_dbuf *b = c->bufhard;
1192 #endif
1193 	int r;
1194 
1195 	CHN_LOCKASSERT(c);
1196 	c->direction = dir;
1197 	r = CHANNEL_SETDIR(c->methods, c->devinfo, c->direction);
1198 #ifdef DEV_ISA
1199 	if (!r && SND_DMA(b))
1200 		sndbuf_dmasetdir(b, c->direction);
1201 #endif
1202 	return r;
1203 }
1204 
1205 int
1206 chn_setvolume(struct pcm_channel *c, int left, int right)
1207 {
1208 	CHN_LOCKASSERT(c);
1209 	/* should add a feeder for volume changing if channel returns -1 */
1210 	if (left > 100)
1211 		left = 100;
1212 	if (left < 0)
1213 		left = 0;
1214 	if (right > 100)
1215 		right = 100;
1216 	if (right < 0)
1217 		right = 0;
1218 	c->volume = left | (right << 8);
1219 	return 0;
1220 }
1221 
1222 static u_int32_t
1223 round_pow2(u_int32_t v)
1224 {
1225 	u_int32_t ret;
1226 
1227 	if (v < 2)
1228 		v = 2;
1229 	ret = 0;
1230 	while (v >> ret)
1231 		ret++;
1232 	ret = 1 << (ret - 1);
1233 	while (ret < v)
1234 		ret <<= 1;
1235 	return ret;
1236 }
1237 
1238 static u_int32_t
1239 round_blksz(u_int32_t v, int round)
1240 {
1241 	u_int32_t ret, tmp;
1242 
1243 	if (round < 1)
1244 		round = 1;
1245 
1246 	ret = min(round_pow2(v), CHN_2NDBUFMAXSIZE >> 1);
1247 
1248 	if (ret > v && (ret >> 1) > 0 && (ret >> 1) >= ((v * 3) >> 2))
1249 		ret >>= 1;
1250 
1251 	tmp = ret - (ret % round);
1252 	while (tmp < 16 || tmp < round) {
1253 		ret <<= 1;
1254 		tmp = ret - (ret % round);
1255 	}
1256 
1257 	return ret;
1258 }
1259 
1260 /*
1261  * 4Front call it DSP Policy, while we call it "Latency Profile". The idea
1262  * is to keep 2nd buffer short so that it doesn't cause long queue during
1263  * buffer transfer.
1264  *
1265  *    Latency reference table for 48khz stereo 16bit: (PLAY)
1266  *
1267  *      +---------+------------+-----------+------------+
1268  *      | Latency | Blockcount | Blocksize | Buffersize |
1269  *      +---------+------------+-----------+------------+
1270  *      |     0   |       2    |   64      |    128     |
1271  *      +---------+------------+-----------+------------+
1272  *      |     1   |       4    |   128     |    512     |
1273  *      +---------+------------+-----------+------------+
1274  *      |     2   |       8    |   512     |    4096    |
1275  *      +---------+------------+-----------+------------+
1276  *      |     3   |      16    |   512     |    8192    |
1277  *      +---------+------------+-----------+------------+
1278  *      |     4   |      32    |   512     |    16384   |
1279  *      +---------+------------+-----------+------------+
1280  *      |     5   |      32    |   1024    |    32768   |
1281  *      +---------+------------+-----------+------------+
1282  *      |     6   |      16    |   2048    |    32768   |
1283  *      +---------+------------+-----------+------------+
1284  *      |     7   |       8    |   4096    |    32768   |
1285  *      +---------+------------+-----------+------------+
1286  *      |     8   |       4    |   8192    |    32768   |
1287  *      +---------+------------+-----------+------------+
1288  *      |     9   |       2    |   16384   |    32768   |
1289  *      +---------+------------+-----------+------------+
1290  *      |    10   |       2    |   32768   |    65536   |
1291  *      +---------+------------+-----------+------------+
1292  *
1293  * Recording need a different reference table. All we care is
1294  * gobbling up everything within reasonable buffering threshold.
1295  *
1296  *    Latency reference table for 48khz stereo 16bit: (REC)
1297  *
1298  *      +---------+------------+-----------+------------+
1299  *      | Latency | Blockcount | Blocksize | Buffersize |
1300  *      +---------+------------+-----------+------------+
1301  *      |     0   |     512    |   32      |    16384   |
1302  *      +---------+------------+-----------+------------+
1303  *      |     1   |     256    |   64      |    16384   |
1304  *      +---------+------------+-----------+------------+
1305  *      |     2   |     128    |   128     |    16384   |
1306  *      +---------+------------+-----------+------------+
1307  *      |     3   |      64    |   256     |    16384   |
1308  *      +---------+------------+-----------+------------+
1309  *      |     4   |      32    |   512     |    16384   |
1310  *      +---------+------------+-----------+------------+
1311  *      |     5   |      32    |   1024    |    32768   |
1312  *      +---------+------------+-----------+------------+
1313  *      |     6   |      16    |   2048    |    32768   |
1314  *      +---------+------------+-----------+------------+
1315  *      |     7   |       8    |   4096    |    32768   |
1316  *      +---------+------------+-----------+------------+
1317  *      |     8   |       4    |   8192    |    32768   |
1318  *      +---------+------------+-----------+------------+
1319  *      |     9   |       2    |   16384   |    32768   |
1320  *      +---------+------------+-----------+------------+
1321  *      |    10   |       2    |   32768   |    65536   |
1322  *      +---------+------------+-----------+------------+
1323  *
1324  * Calculations for other data rate are entirely based on these reference
1325  * tables. For normal operation, Latency 5 seems give the best, well
1326  * balanced performance for typical workload. Anything below 5 will
1327  * eat up CPU to keep up with increasing context switches because of
1328  * shorter buffer space and usually require the application to handle it
1329  * aggresively through possibly real time programming technique.
1330  *
1331  */
1332 #define CHN_LATENCY_PBLKCNT_REF				\
1333 	{{1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 1},		\
1334 	{1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 1}}
1335 #define CHN_LATENCY_PBUFSZ_REF				\
1336 	{{7, 9, 12, 13, 14, 15, 15, 15, 15, 15, 16},	\
1337 	{11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 17}}
1338 
1339 #define CHN_LATENCY_RBLKCNT_REF				\
1340 	{{9, 8, 7, 6, 5, 5, 4, 3, 2, 1, 1},		\
1341 	{9, 8, 7, 6, 5, 5, 4, 3, 2, 1, 1}}
1342 #define CHN_LATENCY_RBUFSZ_REF				\
1343 	{{14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16},	\
1344 	{15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 17}}
1345 
1346 #define CHN_LATENCY_DATA_REF	192000 /* 48khz stereo 16bit ~ 48000 x 2 x 2 */
1347 
1348 static int
1349 chn_calclatency(int dir, int latency, int bps, u_int32_t datarate,
1350 				u_int32_t max, int *rblksz, int *rblkcnt)
1351 {
1352 	static int pblkcnts[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] =
1353 	    CHN_LATENCY_PBLKCNT_REF;
1354 	static int  pbufszs[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] =
1355 	    CHN_LATENCY_PBUFSZ_REF;
1356 	static int rblkcnts[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] =
1357 	    CHN_LATENCY_RBLKCNT_REF;
1358 	static int  rbufszs[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] =
1359 	    CHN_LATENCY_RBUFSZ_REF;
1360 	u_int32_t bufsz;
1361 	int lprofile, blksz, blkcnt;
1362 
1363 	if (latency < CHN_LATENCY_MIN || latency > CHN_LATENCY_MAX ||
1364 	    bps < 1 || datarate < 1 ||
1365 	    !(dir == PCMDIR_PLAY || dir == PCMDIR_REC)) {
1366 		if (rblksz != NULL)
1367 			*rblksz = CHN_2NDBUFMAXSIZE >> 1;
1368 		if (rblkcnt != NULL)
1369 			*rblkcnt = 2;
1370 		printf("%s: FAILED dir=%d latency=%d bps=%d "
1371 		    "datarate=%u max=%u\n",
1372 		    __func__, dir, latency, bps, datarate, max);
1373 		return CHN_2NDBUFMAXSIZE;
1374 	}
1375 
1376 	lprofile = chn_latency_profile;
1377 
1378 	if (dir == PCMDIR_PLAY) {
1379 		blkcnt = pblkcnts[lprofile][latency];
1380 		bufsz = pbufszs[lprofile][latency];
1381 	} else {
1382 		blkcnt = rblkcnts[lprofile][latency];
1383 		bufsz = rbufszs[lprofile][latency];
1384 	}
1385 
1386 	bufsz = round_pow2(snd_xbytes(1 << bufsz, CHN_LATENCY_DATA_REF,
1387 	    datarate));
1388 	if (bufsz > max)
1389 		bufsz = max;
1390 	blksz = round_blksz(bufsz >> blkcnt, bps);
1391 
1392 	if (rblksz != NULL)
1393 		*rblksz = blksz;
1394 	if (rblkcnt != NULL)
1395 		*rblkcnt = 1 << blkcnt;
1396 
1397 	return blksz << blkcnt;
1398 }
1399 
1400 static int
1401 chn_resizebuf(struct pcm_channel *c, int latency,
1402 					int blkcnt, int blksz)
1403 {
1404 	struct snd_dbuf *b, *bs, *pb;
1405 	int sblksz, sblkcnt, hblksz, hblkcnt, limit = 1;
1406 	int ret;
1407 
1408 	CHN_LOCKASSERT(c);
1409 
1410 	if ((c->flags & (CHN_F_MAPPED | CHN_F_TRIGGERED)) ||
1411 	    !(c->direction == PCMDIR_PLAY || c->direction == PCMDIR_REC))
1412 		return EINVAL;
1413 
1414 	if (latency == -1) {
1415 		c->latency = -1;
1416 		latency = chn_latency;
1417 	} else if (latency == -2) {
1418 		latency = c->latency;
1419 		if (latency < CHN_LATENCY_MIN || latency > CHN_LATENCY_MAX)
1420 			latency = chn_latency;
1421 	} else if (latency < CHN_LATENCY_MIN || latency > CHN_LATENCY_MAX)
1422 		return EINVAL;
1423 	else {
1424 		c->latency = latency;
1425 		limit = 0;
1426 	}
1427 
1428 	bs = c->bufsoft;
1429 	b = c->bufhard;
1430 
1431 	if (!(blksz == 0 || blkcnt == -1) &&
1432 	    (blksz < 16 || blksz < sndbuf_getbps(bs) || blkcnt < 2 ||
1433 	    (blksz * blkcnt) > CHN_2NDBUFMAXSIZE))
1434 		return EINVAL;
1435 
1436 	chn_calclatency(c->direction, latency, sndbuf_getbps(bs),
1437 	    sndbuf_getbps(bs) * sndbuf_getspd(bs), CHN_2NDBUFMAXSIZE,
1438 	    &sblksz, &sblkcnt);
1439 
1440 	if (blksz == 0 || blkcnt == -1) {
1441 		if (blkcnt == -1)
1442 			c->flags &= ~CHN_F_HAS_SIZE;
1443 		if (c->flags & CHN_F_HAS_SIZE) {
1444 			blksz = sndbuf_getblksz(bs);
1445 			blkcnt = sndbuf_getblkcnt(bs);
1446 		}
1447 	} else
1448 		c->flags |= CHN_F_HAS_SIZE;
1449 
1450 	if (c->flags & CHN_F_HAS_SIZE) {
1451 		/*
1452 		 * The application has requested their own blksz/blkcnt.
1453 		 * Just obey with it, and let them toast alone. We can
1454 		 * clamp it to the nearest latency profile, but that would
1455 		 * defeat the purpose of having custom control. The least
1456 		 * we can do is round it to the nearest ^2 and align it.
1457 		 */
1458 		sblksz = round_blksz(blksz, sndbuf_getbps(bs));
1459 		sblkcnt = round_pow2(blkcnt);
1460 		limit = 0;
1461 	}
1462 
1463 	if (c->parentchannel != NULL) {
1464 		pb = CHN_BUF_PARENT(c, NULL);
1465 		CHN_UNLOCK(c);
1466 		CHN_LOCK(c->parentchannel);
1467 		chn_notify(c->parentchannel, CHN_N_BLOCKSIZE);
1468 		CHN_UNLOCK(c->parentchannel);
1469 		CHN_LOCK(c);
1470 		limit = (limit != 0 && pb != NULL) ?
1471 		    sndbuf_xbytes(sndbuf_getsize(pb), pb, bs) : 0;
1472 		c->timeout = c->parentchannel->timeout;
1473 	} else {
1474 		hblkcnt = 2;
1475 		if (c->flags & CHN_F_HAS_SIZE) {
1476 			hblksz = round_blksz(sndbuf_xbytes(sblksz, bs, b),
1477 			    sndbuf_getbps(b));
1478 			hblkcnt = round_pow2(sndbuf_getblkcnt(bs));
1479 		} else
1480 			chn_calclatency(c->direction, latency,
1481 			    sndbuf_getbps(b),
1482 			    sndbuf_getbps(b) * sndbuf_getspd(b),
1483 			    CHN_2NDBUFMAXSIZE, &hblksz, &hblkcnt);
1484 
1485 		if ((hblksz << 1) > sndbuf_getmaxsize(b))
1486 			hblksz = round_blksz(sndbuf_getmaxsize(b) >> 1,
1487 			    sndbuf_getbps(b));
1488 
1489 		while ((hblksz * hblkcnt) > sndbuf_getmaxsize(b)) {
1490 			if (hblkcnt < 4)
1491 				hblksz >>= 1;
1492 			else
1493 				hblkcnt >>= 1;
1494 		}
1495 
1496 		hblksz -= hblksz % sndbuf_getbps(b);
1497 
1498 #if 0
1499 		hblksz = sndbuf_getmaxsize(b) >> 1;
1500 		hblksz -= hblksz % sndbuf_getbps(b);
1501 		hblkcnt = 2;
1502 #endif
1503 
1504 		CHN_UNLOCK(c);
1505 		if (chn_usefrags == 0 ||
1506 		    CHANNEL_SETFRAGMENTS(c->methods, c->devinfo,
1507 		    hblksz, hblkcnt) < 1)
1508 			sndbuf_setblksz(b, CHANNEL_SETBLOCKSIZE(c->methods,
1509 			    c->devinfo, hblksz));
1510 		CHN_LOCK(c);
1511 
1512 		if (!CHN_EMPTY(c, children)) {
1513 			sblksz = round_blksz(
1514 			    sndbuf_xbytes(sndbuf_getsize(b) >> 1, b, bs),
1515 			    sndbuf_getbps(bs));
1516 			sblkcnt = 2;
1517 			limit = 0;
1518 		} else if (limit != 0)
1519 			limit = sndbuf_xbytes(sndbuf_getsize(b), b, bs);
1520 
1521 		/*
1522 		 * Interrupt timeout
1523 		 */
1524 		c->timeout = ((u_int64_t)hz * sndbuf_getsize(b)) /
1525 		    ((u_int64_t)sndbuf_getspd(b) * sndbuf_getbps(b));
1526 		if (c->timeout < 1)
1527 			c->timeout = 1;
1528 	}
1529 
1530 	if (limit > CHN_2NDBUFMAXSIZE)
1531 		limit = CHN_2NDBUFMAXSIZE;
1532 
1533 #if 0
1534 	while (limit > 0 && (sblksz * sblkcnt) > limit) {
1535 		if (sblkcnt < 4)
1536 			break;
1537 		sblkcnt >>= 1;
1538 	}
1539 #endif
1540 
1541 	while ((sblksz * sblkcnt) < limit)
1542 		sblkcnt <<= 1;
1543 
1544 	while ((sblksz * sblkcnt) > CHN_2NDBUFMAXSIZE) {
1545 		if (sblkcnt < 4)
1546 			sblksz >>= 1;
1547 		else
1548 			sblkcnt >>= 1;
1549 	}
1550 
1551 	sblksz -= sblksz % sndbuf_getbps(bs);
1552 
1553 	if (sndbuf_getblkcnt(bs) != sblkcnt || sndbuf_getblksz(bs) != sblksz ||
1554 	    sndbuf_getsize(bs) != (sblkcnt * sblksz)) {
1555 		ret = sndbuf_remalloc(bs, sblkcnt, sblksz);
1556 		if (ret != 0) {
1557 			printf("%s: Failed: %d %d\n", __func__,
1558 			    sblkcnt, sblksz);
1559 			return ret;
1560 		}
1561 	}
1562 
1563 	/*
1564 	 * OSSv4 docs: "By default OSS will set the low water level equal
1565 	 * to the fragment size which is optimal in most cases."
1566 	 */
1567 	c->lw = sndbuf_getblksz(bs);
1568 	chn_resetbuf(c);
1569 
1570 	if (snd_verbose > 3)
1571 		printf("%s: %s (%s) timeout=%u "
1572 		    "b[%d/%d/%d] bs[%d/%d/%d] limit=%d\n",
1573 		    __func__, CHN_DIRSTR(c),
1574 		    (c->flags & CHN_F_VIRTUAL) ? "virtual" : "hardware",
1575 		    c->timeout,
1576 		    sndbuf_getsize(b), sndbuf_getblksz(b),
1577 		    sndbuf_getblkcnt(b),
1578 		    sndbuf_getsize(bs), sndbuf_getblksz(bs),
1579 		    sndbuf_getblkcnt(bs), limit);
1580 
1581 	return 0;
1582 }
1583 
1584 int
1585 chn_setlatency(struct pcm_channel *c, int latency)
1586 {
1587 	CHN_LOCKASSERT(c);
1588 	/* Destroy blksz/blkcnt, enforce latency profile. */
1589 	return chn_resizebuf(c, latency, -1, 0);
1590 }
1591 
1592 int
1593 chn_setblocksize(struct pcm_channel *c, int blkcnt, int blksz)
1594 {
1595 	CHN_LOCKASSERT(c);
1596 	/* Destroy latency profile, enforce blksz/blkcnt */
1597 	return chn_resizebuf(c, -1, blkcnt, blksz);
1598 }
1599 
1600 static int
1601 chn_tryspeed(struct pcm_channel *c, int speed)
1602 {
1603 	struct pcm_feeder *f;
1604     	struct snd_dbuf *b = c->bufhard;
1605     	struct snd_dbuf *bs = c->bufsoft;
1606     	struct snd_dbuf *x;
1607 	int r, delta;
1608 
1609 	CHN_LOCKASSERT(c);
1610 	DEB(printf("setspeed, channel %s\n", c->name));
1611 	DEB(printf("want speed %d, ", speed));
1612 	if (speed <= 0)
1613 		return EINVAL;
1614 	if (CHN_STOPPED(c)) {
1615 		r = 0;
1616 		c->speed = speed;
1617 		sndbuf_setspd(bs, speed);
1618 		RANGE(speed, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
1619 		DEB(printf("try speed %d, ", speed));
1620 		sndbuf_setspd(b, CHANNEL_SETSPEED(c->methods, c->devinfo, speed));
1621 		DEB(printf("got speed %d\n", sndbuf_getspd(b)));
1622 
1623 		delta = sndbuf_getspd(b) - sndbuf_getspd(bs);
1624 		if (delta < 0)
1625 			delta = -delta;
1626 
1627 		c->feederflags &= ~(1 << FEEDER_RATE);
1628 		/*
1629 		 * Used to be 500. It was too big!
1630 		 */
1631 		if (delta > feeder_rate_round)
1632 			c->feederflags |= 1 << FEEDER_RATE;
1633 		else
1634 			sndbuf_setspd(bs, sndbuf_getspd(b));
1635 
1636 		r = chn_buildfeeder(c);
1637 		DEB(printf("r = %d\n", r));
1638 		if (r)
1639 			goto out;
1640 
1641 		if (!(c->feederflags & (1 << FEEDER_RATE)))
1642 			goto out;
1643 
1644 		r = EINVAL;
1645 		f = chn_findfeeder(c, FEEDER_RATE);
1646 		DEB(printf("feedrate = %p\n", f));
1647 		if (f == NULL)
1648 			goto out;
1649 
1650 		x = (c->direction == PCMDIR_REC)? b : bs;
1651 		r = FEEDER_SET(f, FEEDRATE_SRC, sndbuf_getspd(x));
1652 		DEB(printf("feeder_set(FEEDRATE_SRC, %d) = %d\n", sndbuf_getspd(x), r));
1653 		if (r)
1654 			goto out;
1655 
1656 		x = (c->direction == PCMDIR_REC)? bs : b;
1657 		r = FEEDER_SET(f, FEEDRATE_DST, sndbuf_getspd(x));
1658 		DEB(printf("feeder_set(FEEDRATE_DST, %d) = %d\n", sndbuf_getspd(x), r));
1659 out:
1660 		if (!r)
1661 			r = CHANNEL_SETFORMAT(c->methods, c->devinfo,
1662 							sndbuf_getfmt(b));
1663 		if (!r)
1664 			sndbuf_setfmt(bs, c->format);
1665 		if (!r)
1666 			r = chn_resizebuf(c, -2, 0, 0);
1667 		DEB(printf("setspeed done, r = %d\n", r));
1668 		return r;
1669 	} else
1670 		return EINVAL;
1671 }
1672 
1673 int
1674 chn_setspeed(struct pcm_channel *c, int speed)
1675 {
1676 	int r, oldspeed = c->speed;
1677 
1678 	r = chn_tryspeed(c, speed);
1679 	if (r) {
1680 		if (snd_verbose > 3)
1681 			printf("Failed to set speed %d falling back to %d\n",
1682 			    speed, oldspeed);
1683 		r = chn_tryspeed(c, oldspeed);
1684 	}
1685 	return r;
1686 }
1687 
1688 static int
1689 chn_tryformat(struct pcm_channel *c, u_int32_t fmt)
1690 {
1691 	struct snd_dbuf *b = c->bufhard;
1692 	struct snd_dbuf *bs = c->bufsoft;
1693 	int r;
1694 
1695 	CHN_LOCKASSERT(c);
1696 	if (CHN_STOPPED(c)) {
1697 		DEB(printf("want format %d\n", fmt));
1698 		c->format = fmt;
1699 		r = chn_buildfeeder(c);
1700 		if (r == 0) {
1701 			sndbuf_setfmt(bs, c->format);
1702 			chn_resetbuf(c);
1703 			r = CHANNEL_SETFORMAT(c->methods, c->devinfo, sndbuf_getfmt(b));
1704 			if (r == 0)
1705 				r = chn_tryspeed(c, c->speed);
1706 		}
1707 		return r;
1708 	} else
1709 		return EINVAL;
1710 }
1711 
1712 int
1713 chn_setformat(struct pcm_channel *c, u_int32_t fmt)
1714 {
1715 	u_int32_t oldfmt = c->format;
1716 	int r;
1717 
1718 	r = chn_tryformat(c, fmt);
1719 	if (r) {
1720 		if (snd_verbose > 3)
1721 			printf("Format change 0x%08x failed, reverting to 0x%08x\n",
1722 			    fmt, oldfmt);
1723 		chn_tryformat(c, oldfmt);
1724 	}
1725 	return r;
1726 }
1727 
1728 int
1729 chn_trigger(struct pcm_channel *c, int go)
1730 {
1731 #ifdef DEV_ISA
1732     	struct snd_dbuf *b = c->bufhard;
1733 #endif
1734 	struct snddev_info *d = c->parentsnddev;
1735 	int ret;
1736 
1737 	CHN_LOCKASSERT(c);
1738 #ifdef DEV_ISA
1739 	if (SND_DMA(b) && (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD))
1740 		sndbuf_dmabounce(b);
1741 #endif
1742 	if (!PCMTRIG_COMMON(go))
1743 		return (CHANNEL_TRIGGER(c->methods, c->devinfo, go));
1744 
1745 	if (go == c->trigger)
1746 		return (0);
1747 
1748 	ret = CHANNEL_TRIGGER(c->methods, c->devinfo, go);
1749 	if (ret != 0)
1750 		return (ret);
1751 
1752 	switch (go) {
1753 	case PCMTRIG_START:
1754 		if (snd_verbose > 3)
1755 			device_printf(c->dev,
1756 			    "%s() %s: calling go=0x%08x , "
1757 			    "prev=0x%08x\n", __func__, c->name, go,
1758 			    c->trigger);
1759 		if (c->trigger != PCMTRIG_START) {
1760 			c->trigger = go;
1761 			CHN_UNLOCK(c);
1762 			pcm_lock(d);
1763 			CHN_INSERT_HEAD(d, c, channels.pcm.busy);
1764 			pcm_unlock(d);
1765 			CHN_LOCK(c);
1766 		}
1767 		break;
1768 	case PCMTRIG_STOP:
1769 	case PCMTRIG_ABORT:
1770 		if (snd_verbose > 3)
1771 			device_printf(c->dev,
1772 			    "%s() %s: calling go=0x%08x , "
1773 			    "prev=0x%08x\n", __func__, c->name, go,
1774 			    c->trigger);
1775 		if (c->trigger == PCMTRIG_START) {
1776 			c->trigger = go;
1777 			CHN_UNLOCK(c);
1778 			pcm_lock(d);
1779 			CHN_REMOVE(d, c, channels.pcm.busy);
1780 			pcm_unlock(d);
1781 			CHN_LOCK(c);
1782 		}
1783 		break;
1784 	default:
1785 		break;
1786 	}
1787 
1788 	return (0);
1789 }
1790 
1791 /**
1792  * @brief Queries sound driver for sample-aligned hardware buffer pointer index
1793  *
1794  * This function obtains the hardware pointer location, then aligns it to
1795  * the current bytes-per-sample value before returning.  (E.g., a channel
1796  * running in 16 bit stereo mode would require 4 bytes per sample, so a
1797  * hwptr value ranging from 32-35 would be returned as 32.)
1798  *
1799  * @param c	PCM channel context
1800  * @returns 	sample-aligned hardware buffer pointer index
1801  */
1802 int
1803 chn_getptr(struct pcm_channel *c)
1804 {
1805 	int hwptr;
1806 
1807 	CHN_LOCKASSERT(c);
1808 	hwptr = (CHN_STARTED(c)) ? CHANNEL_GETPTR(c->methods, c->devinfo) : 0;
1809 	return (hwptr - (hwptr % sndbuf_getbps(c->bufhard)));
1810 }
1811 
1812 struct pcmchan_caps *
1813 chn_getcaps(struct pcm_channel *c)
1814 {
1815 	CHN_LOCKASSERT(c);
1816 	return CHANNEL_GETCAPS(c->methods, c->devinfo);
1817 }
1818 
1819 u_int32_t
1820 chn_getformats(struct pcm_channel *c)
1821 {
1822 	u_int32_t *fmtlist, fmts;
1823 	int i;
1824 
1825 	fmtlist = chn_getcaps(c)->fmtlist;
1826 	fmts = 0;
1827 	for (i = 0; fmtlist[i]; i++)
1828 		fmts |= fmtlist[i];
1829 
1830 	/* report software-supported formats */
1831 	if (report_soft_formats)
1832 		fmts |= AFMT_MU_LAW|AFMT_A_LAW|AFMT_U32_LE|AFMT_U32_BE|
1833 		    AFMT_S32_LE|AFMT_S32_BE|AFMT_U24_LE|AFMT_U24_BE|
1834 		    AFMT_S24_LE|AFMT_S24_BE|AFMT_U16_LE|AFMT_U16_BE|
1835 		    AFMT_S16_LE|AFMT_S16_BE|AFMT_U8|AFMT_S8;
1836 
1837 	return fmts;
1838 }
1839 
1840 static int
1841 chn_buildfeeder(struct pcm_channel *c)
1842 {
1843 	struct feeder_class *fc;
1844 	struct pcm_feederdesc desc;
1845 	struct snd_mixer *m;
1846 	u_int32_t tmp[2], type, flags, hwfmt, *fmtlist;
1847 	int err;
1848 	char fmtstr[AFMTSTR_MAXSZ];
1849 
1850 	CHN_LOCKASSERT(c);
1851 	while (chn_removefeeder(c) == 0)
1852 		;
1853 	KASSERT((c->feeder == NULL), ("feeder chain not empty"));
1854 
1855 	c->align = sndbuf_getalign(c->bufsoft);
1856 
1857 	if (CHN_EMPTY(c, children) || c->direction == PCMDIR_REC) {
1858 		/*
1859 		 * Virtual rec need this.
1860 		 */
1861 		fc = feeder_getclass(NULL);
1862 		KASSERT(fc != NULL, ("can't find root feeder"));
1863 
1864 		err = chn_addfeeder(c, fc, NULL);
1865 		if (err) {
1866 			DEB(printf("can't add root feeder, err %d\n", err));
1867 
1868 			return err;
1869 		}
1870 		c->feeder->desc->out = c->format;
1871 	} else if (c->direction == PCMDIR_PLAY) {
1872 		if (c->flags & CHN_F_HAS_VCHAN) {
1873 			desc.type = FEEDER_MIXER;
1874 			desc.in = c->format;
1875 		} else {
1876 			DEB(printf("can't decide which feeder type to use!\n"));
1877 			return EOPNOTSUPP;
1878 		}
1879 		desc.out = c->format;
1880 		desc.flags = 0;
1881 		fc = feeder_getclass(&desc);
1882 		if (fc == NULL) {
1883 			DEB(printf("can't find vchan feeder\n"));
1884 
1885 			return EOPNOTSUPP;
1886 		}
1887 
1888 		err = chn_addfeeder(c, fc, &desc);
1889 		if (err) {
1890 			DEB(printf("can't add vchan feeder, err %d\n", err));
1891 
1892 			return err;
1893 		}
1894 	} else
1895 		return EOPNOTSUPP;
1896 
1897 	/* XXX These are too much.. */
1898 	if (c->parentsnddev != NULL && c->parentsnddev->mixer_dev != NULL &&
1899 	    c->parentsnddev->mixer_dev->si_drv1 != NULL)
1900 		m = c->parentsnddev->mixer_dev->si_drv1;
1901 	else
1902 		m = NULL;
1903 
1904 	c->feederflags &= ~(1 << FEEDER_VOLUME);
1905 	if (c->direction == PCMDIR_PLAY && !(c->flags & CHN_F_VIRTUAL) && m &&
1906 	    (c->parentsnddev->flags & SD_F_SOFTPCMVOL))
1907 		c->feederflags |= 1 << FEEDER_VOLUME;
1908 
1909 	if (!(c->flags & CHN_F_VIRTUAL) && c->parentsnddev &&
1910 	    ((c->direction == PCMDIR_PLAY &&
1911 	    (c->parentsnddev->flags & SD_F_PSWAPLR)) ||
1912 	    (c->direction == PCMDIR_REC &&
1913 	    (c->parentsnddev->flags & SD_F_RSWAPLR))))
1914 		c->feederflags |= 1 << FEEDER_SWAPLR;
1915 
1916 	flags = c->feederflags;
1917 	fmtlist = chn_getcaps(c)->fmtlist;
1918 
1919 	DEB(printf("feederflags %x\n", flags));
1920 
1921 	for (type = FEEDER_RATE; type < FEEDER_LAST; type++) {
1922 		if (flags & (1 << type)) {
1923 			desc.type = type;
1924 			desc.in = 0;
1925 			desc.out = 0;
1926 			desc.flags = 0;
1927 			DEB(printf("find feeder type %d, ", type));
1928 			if (type == FEEDER_VOLUME || type == FEEDER_RATE) {
1929 				if (c->feeder->desc->out & AFMT_32BIT)
1930 					strlcpy(fmtstr,"s32le", sizeof(fmtstr));
1931 				else if (c->feeder->desc->out & AFMT_24BIT)
1932 					strlcpy(fmtstr, "s24le", sizeof(fmtstr));
1933 				else {
1934 					/*
1935 					 * 8bit doesn't provide enough headroom
1936 					 * for proper processing without
1937 					 * creating too much noises. Force to
1938 					 * 16bit instead.
1939 					 */
1940 					strlcpy(fmtstr, "s16le", sizeof(fmtstr));
1941 				}
1942 				if (!(c->feeder->desc->out & AFMT_8BIT) &&
1943 					    c->feeder->desc->out & AFMT_BIGENDIAN)
1944 					afmtstr_swap_endian(fmtstr);
1945 				if (!(c->feeder->desc->out & (AFMT_A_LAW | AFMT_MU_LAW)) &&
1946 					    !(c->feeder->desc->out & AFMT_SIGNED))
1947 					afmtstr_swap_sign(fmtstr);
1948 				desc.in = afmtstr2afmt(NULL, fmtstr, AFMTSTR_MONO_RETURN);
1949 				if (desc.in == 0)
1950 					desc.in = AFMT_S16_LE;
1951 				/* feeder_volume need stereo processing */
1952 				if (type == FEEDER_VOLUME ||
1953 					    c->feeder->desc->out & AFMT_STEREO)
1954 					desc.in |= AFMT_STEREO;
1955 				desc.out = desc.in;
1956 			} else if (type == FEEDER_SWAPLR) {
1957 				desc.in = c->feeder->desc->out;
1958 				desc.in |= AFMT_STEREO;
1959 				desc.out = desc.in;
1960 			}
1961 
1962 			fc = feeder_getclass(&desc);
1963 			DEB(printf("got %p\n", fc));
1964 			if (fc == NULL) {
1965 				DEB(printf("can't find required feeder type %d\n", type));
1966 
1967 				return EOPNOTSUPP;
1968 			}
1969 
1970 			if (desc.in == 0 || desc.out == 0)
1971 				desc = *fc->desc;
1972 
1973  			DEB(printf("build fmtchain from 0x%08x to 0x%08x: ", c->feeder->desc->out, fc->desc->in));
1974 			tmp[0] = desc.in;
1975 			tmp[1] = 0;
1976 			if (chn_fmtchain(c, tmp) == 0) {
1977 				DEB(printf("failed\n"));
1978 
1979 				return ENODEV;
1980 			}
1981  			DEB(printf("ok\n"));
1982 
1983 			err = chn_addfeeder(c, fc, &desc);
1984 			if (err) {
1985 				DEB(printf("can't add feeder %p, output 0x%x, err %d\n", fc, fc->desc->out, err));
1986 
1987 				return err;
1988 			}
1989 			DEB(printf("added feeder %p, output 0x%x\n", fc, c->feeder->desc->out));
1990 		}
1991 	}
1992 
1993  	if (c->direction == PCMDIR_REC) {
1994 	 	tmp[0] = c->format;
1995  		tmp[1] = 0;
1996  		hwfmt = chn_fmtchain(c, tmp);
1997  	} else
1998  		hwfmt = chn_fmtchain(c, fmtlist);
1999 
2000 	if (hwfmt == 0 || !fmtvalid(hwfmt, fmtlist)) {
2001 		DEB(printf("Invalid hardware format: 0x%08x\n", hwfmt));
2002 		return ENODEV;
2003 	} else if (c->direction == PCMDIR_REC && !CHN_EMPTY(c, children)) {
2004 		/*
2005 		 * Kind of awkward. This whole "MIXER" concept need a
2006 		 * rethinking, I guess :) . Recording is the inverse
2007 		 * of Playback, which is why we push mixer vchan down here.
2008 		 */
2009 		if (c->flags & CHN_F_HAS_VCHAN) {
2010 			desc.type = FEEDER_MIXER;
2011 			desc.in = c->format;
2012 		} else
2013 			return EOPNOTSUPP;
2014 		desc.out = c->format;
2015 		desc.flags = 0;
2016 		fc = feeder_getclass(&desc);
2017 		if (fc == NULL)
2018 			return EOPNOTSUPP;
2019 
2020 		err = chn_addfeeder(c, fc, &desc);
2021 		if (err != 0)
2022 			return err;
2023 	}
2024 
2025 	sndbuf_setfmt(c->bufhard, hwfmt);
2026 
2027 	if ((flags & (1 << FEEDER_VOLUME))) {
2028 		u_int32_t parent;
2029 		int vol, left, right;
2030 
2031 		CHN_UNLOCK(c);
2032 		vol = mix_get(m, SOUND_MIXER_PCM);
2033 		if (vol == -1) {
2034 			device_printf(c->dev,
2035 			    "Soft PCM Volume: Failed to read default value\n");
2036 			vol = 100 | (100 << 8);
2037 		}
2038 		left = vol & 0x7f;
2039 		right = (vol >> 8) & 0x7f;
2040 		parent = mix_getparent(m, SOUND_MIXER_PCM);
2041 		if (parent != SOUND_MIXER_NONE) {
2042 			vol = mix_get(m, parent);
2043 			if (vol == -1) {
2044 				device_printf(c->dev,
2045 				    "Soft Volume: Failed to read parent "
2046 				    "default value\n");
2047 				vol = 100 | (100 << 8);
2048 			}
2049 			left = (left * (vol & 0x7f)) / 100;
2050 			right = (right * ((vol >> 8) & 0x7f)) / 100;
2051 		}
2052 		CHN_LOCK(c);
2053 		chn_setvolume(c, left, right);
2054 	}
2055 
2056 	return 0;
2057 }
2058 
2059 int
2060 chn_notify(struct pcm_channel *c, u_int32_t flags)
2061 {
2062 	int err, run, nrun;
2063 
2064 	CHN_LOCKASSERT(c);
2065 
2066 	if (CHN_EMPTY(c, children))
2067 		return (ENODEV);
2068 
2069 	err = 0;
2070 
2071 	/*
2072 	 * If the hwchan is running, we can't change its rate, format or
2073 	 * blocksize
2074 	 */
2075 	run = (CHN_STARTED(c)) ? 1 : 0;
2076 	if (run)
2077 		flags &= CHN_N_VOLUME | CHN_N_TRIGGER;
2078 
2079 	if (flags & CHN_N_RATE) {
2080 		/* XXX I'll make good use of this someday. */
2081 	}
2082 	if (flags & CHN_N_FORMAT) {
2083 		/* XXX I'll make good use of this someday. */
2084 	}
2085 	if (flags & CHN_N_VOLUME) {
2086 		/* XXX I'll make good use of this someday. */
2087 	}
2088 	if (flags & CHN_N_BLOCKSIZE) {
2089 		/*
2090 		 * Set to default latency profile
2091 		 */
2092 		chn_setlatency(c, chn_latency);
2093 	}
2094 	if (flags & CHN_N_TRIGGER) {
2095 		nrun = CHN_EMPTY(c, children.busy) ? 0 : 1;
2096 		if (nrun && !run)
2097 			err = chn_start(c, 1);
2098 		if (!nrun && run)
2099 			chn_abort(c);
2100 	}
2101 
2102 	return (err);
2103 }
2104 
2105 /**
2106  * @brief Fetch array of supported discrete sample rates
2107  *
2108  * Wrapper for CHANNEL_GETRATES.  Please see channel_if.m:getrates() for
2109  * detailed information.
2110  *
2111  * @note If the operation isn't supported, this function will just return 0
2112  *       (no rates in the array), and *rates will be set to NULL.  Callers
2113  *       should examine rates @b only if this function returns non-zero.
2114  *
2115  * @param c	pcm channel to examine
2116  * @param rates	pointer to array of integers; rate table will be recorded here
2117  *
2118  * @return number of rates in the array pointed to be @c rates
2119  */
2120 int
2121 chn_getrates(struct pcm_channel *c, int **rates)
2122 {
2123 	KASSERT(rates != NULL, ("rates is null"));
2124 	CHN_LOCKASSERT(c);
2125 	return CHANNEL_GETRATES(c->methods, c->devinfo, rates);
2126 }
2127 
2128 /**
2129  * @brief Remove channel from a sync group, if there is one.
2130  *
2131  * This function is initially intended for the following conditions:
2132  *   - Starting a syncgroup (@c SNDCTL_DSP_SYNCSTART ioctl)
2133  *   - Closing a device.  (A channel can't be destroyed if it's still in use.)
2134  *
2135  * @note Before calling this function, the syncgroup list mutex must be
2136  * held.  (Consider pcm_channel::sm protected by the SG list mutex
2137  * whether @c c is locked or not.)
2138  *
2139  * @param c	channel device to be started or closed
2140  * @returns	If this channel was the only member of a group, the group ID
2141  * 		is returned to the caller so that the caller can release it
2142  * 		via free_unr() after giving up the syncgroup lock.  Else it
2143  * 		returns 0.
2144  */
2145 int
2146 chn_syncdestroy(struct pcm_channel *c)
2147 {
2148 	struct pcmchan_syncmember *sm;
2149 	struct pcmchan_syncgroup *sg;
2150 	int sg_id;
2151 
2152 	sg_id = 0;
2153 
2154 	PCM_SG_LOCKASSERT(MA_OWNED);
2155 
2156 	if (c->sm != NULL) {
2157 		sm = c->sm;
2158 		sg = sm->parent;
2159 		c->sm = NULL;
2160 
2161 		KASSERT(sg != NULL, ("syncmember has null parent"));
2162 
2163 		SLIST_REMOVE(&sg->members, sm, pcmchan_syncmember, link);
2164 		free(sm, M_DEVBUF);
2165 
2166 		if (SLIST_EMPTY(&sg->members)) {
2167 			SLIST_REMOVE(&snd_pcm_syncgroups, sg, pcmchan_syncgroup, link);
2168 			sg_id = sg->id;
2169 			free(sg, M_DEVBUF);
2170 		}
2171 	}
2172 
2173 	return sg_id;
2174 }
2175 
2176 void
2177 chn_lock(struct pcm_channel *c)
2178 {
2179 	CHN_LOCK(c);
2180 }
2181 
2182 void
2183 chn_unlock(struct pcm_channel *c)
2184 {
2185 	CHN_UNLOCK(c);
2186 }
2187 
2188 #ifdef OSSV4_EXPERIMENT
2189 int
2190 chn_getpeaks(struct pcm_channel *c, int *lpeak, int *rpeak)
2191 {
2192 	CHN_LOCKASSERT(c);
2193 	return CHANNEL_GETPEAKS(c->methods, c->devinfo, lpeak, rpeak);
2194 }
2195 #endif
2196