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