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