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