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