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