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