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