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