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
Cache object: b8d16e001bbc5ffec49ac1196800c171
|