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 * $FreeBSD: src/sys/dev/sound/pcm/channel.c,v 1.99.2.4 2006/04/04 17:37:51 ariff Exp $ 28 * $DragonFly: src/sys/dev/sound/pcm/channel.c,v 1.11 2007/01/04 21:47:03 corecode Exp $ 29 */ 30 31 #include "use_isa.h" 32 33 #include <dev/sound/pcm/sound.h> 34 #include <sys/vnode.h> /* IO_NDELAY */ 35 36 #include "feeder_if.h" 37 38 SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pcm/channel.c,v 1.11 2007/01/04 21:47:03 corecode Exp $"); 39 40 #define MIN_CHUNK_SIZE 256 /* for uiomove etc. */ 41 #if 0 42 #define DMA_ALIGN_THRESHOLD 4 43 #define DMA_ALIGN_MASK (~(DMA_ALIGN_THRESHOLD - 1)) 44 #endif 45 46 #define CANCHANGE(c) (!(c->flags & CHN_F_TRIGGERED)) 47 48 /* 49 #define DEB(x) x 50 */ 51 52 static int chn_targetirqrate = 32; 53 TUNABLE_INT("hw.snd.targetirqrate", &chn_targetirqrate); 54 55 static int 56 sysctl_hw_snd_targetirqrate(SYSCTL_HANDLER_ARGS) 57 { 58 int err, val; 59 60 val = chn_targetirqrate; 61 err = sysctl_handle_int(oidp, &val, sizeof(val), req); 62 if (val < 16 || val > 512) 63 err = EINVAL; 64 else 65 chn_targetirqrate = val; 66 67 return err; 68 } 69 SYSCTL_PROC(_hw_snd, OID_AUTO, targetirqrate, CTLTYPE_INT | CTLFLAG_RW, 70 0, sizeof(int), sysctl_hw_snd_targetirqrate, "I", ""); 71 static int report_soft_formats = 1; 72 SYSCTL_INT(_hw_snd, OID_AUTO, report_soft_formats, CTLFLAG_RW, 73 &report_soft_formats, 1, "report software-emulated formats"); 74 75 static int chn_buildfeeder(struct pcm_channel *c); 76 77 static void 78 chn_lockinit(struct pcm_channel *c, int dir) 79 { 80 switch(dir) { 81 case PCMDIR_PLAY: 82 c->lock = snd_mtxcreate(c->name, "pcm play channel"); 83 break; 84 case PCMDIR_REC: 85 c->lock = snd_mtxcreate(c->name, "pcm record channel"); 86 break; 87 case PCMDIR_VIRTUAL: 88 c->lock = snd_mtxcreate(c->name, "pcm virtual play channel"); 89 break; 90 case 0: 91 c->lock = snd_mtxcreate(c->name, "pcm fake channel"); 92 break; 93 } 94 } 95 96 static void 97 chn_lockdestroy(struct pcm_channel *c) 98 { 99 snd_mtxfree(c->lock); 100 } 101 102 static int 103 chn_polltrigger(struct pcm_channel *c) 104 { 105 struct snd_dbuf *bs = c->bufsoft; 106 unsigned amt, lim; 107 108 CHN_LOCKASSERT(c); 109 if (c->flags & CHN_F_MAPPED) { 110 if (sndbuf_getprevblocks(bs) == 0) 111 return 1; 112 else 113 return (sndbuf_getblocks(bs) > sndbuf_getprevblocks(bs))? 1 : 0; 114 } else { 115 amt = (c->direction == PCMDIR_PLAY)? sndbuf_getfree(bs) : sndbuf_getready(bs); 116 #if 0 117 lim = (c->flags & CHN_F_HAS_SIZE)? sndbuf_getblksz(bs) : 1; 118 #endif 119 lim = 1; 120 return (amt >= lim)? 1 : 0; 121 } 122 return 0; 123 } 124 125 static int 126 chn_pollreset(struct pcm_channel *c) 127 { 128 struct snd_dbuf *bs = c->bufsoft; 129 130 CHN_LOCKASSERT(c); 131 sndbuf_updateprevtotal(bs); 132 return 1; 133 } 134 135 static void 136 chn_wakeup(struct pcm_channel *c) 137 { 138 struct snd_dbuf *bs = c->bufsoft; 139 struct pcmchan_children *pce; 140 141 CHN_LOCKASSERT(c); 142 if (SLIST_EMPTY(&c->children)) { 143 /*if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c))*/ 144 if (sndbuf_getsel(bs)->si_pid && chn_polltrigger(c)) 145 selwakeup(sndbuf_getsel(bs)); 146 } else { 147 SLIST_FOREACH(pce, &c->children, link) { 148 CHN_LOCK(pce->channel); 149 chn_wakeup(pce->channel); 150 CHN_UNLOCK(pce->channel); 151 } 152 } 153 154 wakeup(bs); 155 } 156 157 static int 158 chn_sleep(struct pcm_channel *c, char *str, int timeout) 159 { 160 struct snd_dbuf *bs = c->bufsoft; 161 int ret; 162 163 CHN_LOCKASSERT(c); 164 #ifdef USING_MUTEX 165 ret = msleep(bs, c->lock, PCATCH, str, timeout); 166 #else 167 ret = tsleep(bs, PRIBIO | PCATCH, str, timeout); 168 #endif 169 170 return ret; 171 } 172 173 /* 174 * chn_dmaupdate() tracks the status of a dma transfer, 175 * updating pointers. 176 */ 177 178 static unsigned int 179 chn_dmaupdate(struct pcm_channel *c) 180 { 181 struct snd_dbuf *b = c->bufhard; 182 unsigned int delta, old, hwptr, amt; 183 184 KASSERT(sndbuf_getsize(b) > 0, ("bufsize == 0")); 185 CHN_LOCKASSERT(c); 186 187 old = sndbuf_gethwptr(b); 188 hwptr = chn_getptr(c); 189 delta = (sndbuf_getsize(b) + hwptr - old) % sndbuf_getsize(b); 190 sndbuf_sethwptr(b, hwptr); 191 192 DEB( 193 if (delta >= ((sndbuf_getsize(b) * 15) / 16)) { 194 if (!(c->flags & (CHN_F_CLOSING | CHN_F_ABORTING))) 195 device_printf(c->dev, "hwptr went backwards %d -> %d\n", old, hwptr); 196 } 197 ); 198 199 if (c->direction == PCMDIR_PLAY) { 200 amt = MIN(delta, sndbuf_getready(b)); 201 if (amt > 0) 202 sndbuf_dispose(b, NULL, amt); 203 } else { 204 amt = MIN(delta, sndbuf_getfree(b)); 205 if (amt > 0) 206 sndbuf_acquire(b, NULL, amt); 207 } 208 209 return delta; 210 } 211 212 void 213 chn_wrupdate(struct pcm_channel *c) 214 { 215 int ret; 216 217 CHN_LOCKASSERT(c); 218 KASSERT(c->direction == PCMDIR_PLAY, ("chn_wrupdate on bad channel")); 219 220 if ((c->flags & (CHN_F_MAPPED | CHN_F_VIRTUAL)) || !(c->flags & CHN_F_TRIGGERED)) 221 return; 222 chn_dmaupdate(c); 223 ret = chn_wrfeed(c); 224 /* tell the driver we've updated the primary buffer */ 225 chn_trigger(c, PCMTRIG_EMLDMAWR); 226 DEB(if (ret) 227 kprintf("chn_wrupdate: chn_wrfeed returned %d\n", ret);) 228 229 } 230 231 int 232 chn_wrfeed(struct pcm_channel *c) 233 { 234 struct snd_dbuf *b = c->bufhard; 235 struct snd_dbuf *bs = c->bufsoft; 236 unsigned int ret, amt; 237 238 CHN_LOCKASSERT(c); 239 #if 0 240 DEB( 241 if (c->flags & CHN_F_CLOSING) { 242 sndbuf_dump(b, "b", 0x02); 243 sndbuf_dump(bs, "bs", 0x02); 244 }) 245 #endif 246 247 if (c->flags & CHN_F_MAPPED) 248 sndbuf_acquire(bs, NULL, sndbuf_getfree(bs)); 249 250 amt = sndbuf_getfree(b); 251 KASSERT(amt <= sndbuf_getsize(bs), 252 ("%s(%s): amt %d > source size %d, flags 0x%x", __func__, c->name, 253 amt, sndbuf_getsize(bs), c->flags)); 254 255 ret = (amt > 0) ? sndbuf_feed(bs, b, c, c->feeder, amt) : ENOSPC; 256 /* 257 * Possible xruns. There should be no empty space left in buffer. 258 */ 259 if (sndbuf_getfree(b) > 0) 260 c->xruns++; 261 262 if (ret == 0 && sndbuf_getfree(b) < amt) 263 chn_wakeup(c); 264 265 return ret; 266 } 267 268 static void 269 chn_wrintr(struct pcm_channel *c) 270 { 271 int ret; 272 273 CHN_LOCKASSERT(c); 274 /* update pointers in primary buffer */ 275 chn_dmaupdate(c); 276 /* ...and feed from secondary to primary */ 277 ret = chn_wrfeed(c); 278 /* tell the driver we've updated the primary buffer */ 279 chn_trigger(c, PCMTRIG_EMLDMAWR); 280 DEB(if (ret) 281 kprintf("chn_wrintr: chn_wrfeed returned %d\n", ret);) 282 } 283 284 /* 285 * user write routine - uiomove data into secondary buffer, trigger if necessary 286 * if blocking, sleep, rinse and repeat. 287 * 288 * called externally, so must handle locking 289 */ 290 291 int 292 chn_write(struct pcm_channel *c, struct uio *buf, int ioflags) 293 { 294 int ret, timeout, newsize, count, sz; 295 int nbio; 296 struct snd_dbuf *bs = c->bufsoft; 297 void *off; 298 int t, x,togo,p; 299 300 CHN_LOCKASSERT(c); 301 /* 302 * XXX Certain applications attempt to write larger size 303 * of pcm data than c->blocksize2nd without blocking, 304 * resulting partial write. Expand the block size so that 305 * the write operation avoids blocking. 306 */ 307 nbio = (c->flags & CHN_F_NBIO) || (ioflags & IO_NDELAY); 308 if (nbio && buf->uio_resid > sndbuf_getblksz(bs)) { 309 DEB(device_printf(c->dev, "broken app, nbio and tried to write %d bytes with fragsz %d\n", 310 buf->uio_resid, sndbuf_getblksz(bs))); 311 newsize = 16; 312 while (newsize < min(buf->uio_resid, CHN_2NDBUFMAXSIZE / 2)) 313 newsize <<= 1; 314 chn_setblocksize(c, sndbuf_getblkcnt(bs), newsize); 315 DEB(device_printf(c->dev, "frags reset to %d x %d\n", sndbuf_getblkcnt(bs), sndbuf_getblksz(bs))); 316 } 317 318 ret = 0; 319 count = hz; 320 while (!ret && (buf->uio_resid > 0) && (count > 0)) { 321 sz = sndbuf_getfree(bs); 322 if (sz == 0) { 323 if (nbio) 324 ret = EWOULDBLOCK; 325 else { 326 timeout = (hz * sndbuf_getblksz(bs)) / (sndbuf_getspd(bs) * sndbuf_getbps(bs)); 327 if (timeout < 1) 328 timeout = 1; 329 timeout = 1; 330 ret = chn_sleep(c, "pcmwr", timeout); 331 if (ret == EWOULDBLOCK) { 332 count -= timeout; 333 ret = 0; 334 } else if (ret == 0) 335 count = hz; 336 } 337 } else { 338 sz = MIN(sz, buf->uio_resid); 339 KASSERT(sz > 0, ("confusion in chn_write")); 340 /* kprintf("sz: %d\n", sz); */ 341 342 /* 343 * The following assumes that the free space in 344 * the buffer can never be less around the 345 * unlock-uiomove-lock sequence. 346 */ 347 togo = sz; 348 while (ret == 0 && togo> 0) { 349 p = sndbuf_getfreeptr(bs); 350 t = MIN(togo, sndbuf_getsize(bs) - p); 351 off = sndbuf_getbufofs(bs, p); 352 CHN_UNLOCK(c); 353 ret = uiomove(off, t, buf); 354 CHN_LOCK(c); 355 togo -= t; 356 x = sndbuf_acquire(bs, NULL, t); 357 } 358 ret = 0; 359 if (ret == 0 && !(c->flags & CHN_F_TRIGGERED)) 360 chn_start(c, 0); 361 } 362 } 363 /* kprintf("ret: %d left: %d\n", ret, buf->uio_resid); */ 364 365 if (count <= 0) { 366 c->flags |= CHN_F_DEAD; 367 kprintf("%s: play interrupt timeout, channel dead\n", c->name); 368 } 369 370 return ret; 371 } 372 373 #if 0 374 static int 375 chn_rddump(struct pcm_channel *c, unsigned int cnt) 376 { 377 struct snd_dbuf *b = c->bufhard; 378 379 CHN_LOCKASSERT(c); 380 #if 0 381 static uint32_t kk = 0; 382 printf("%u: dumping %d bytes\n", ++kk, cnt); 383 #endif 384 c->xruns++; 385 sndbuf_setxrun(b, sndbuf_getxrun(b) + cnt); 386 return sndbuf_dispose(b, NULL, cnt); 387 } 388 #endif 389 390 /* 391 * Feed new data from the read buffer. Can be called in the bottom half. 392 */ 393 int 394 chn_rdfeed(struct pcm_channel *c) 395 { 396 struct snd_dbuf *b = c->bufhard; 397 struct snd_dbuf *bs = c->bufsoft; 398 unsigned int ret, amt; 399 400 CHN_LOCKASSERT(c); 401 DEB( 402 if (c->flags & CHN_F_CLOSING) { 403 sndbuf_dump(b, "b", 0x02); 404 sndbuf_dump(bs, "bs", 0x02); 405 }) 406 407 #if 0 408 amt = sndbuf_getready(b); 409 if (sndbuf_getfree(bs) < amt) { 410 c->xruns++; 411 amt = sndbuf_getfree(bs); 412 } 413 #endif 414 amt = sndbuf_getfree(bs); 415 ret = (amt > 0)? sndbuf_feed(b, bs, c, c->feeder, amt) : 0; 416 417 amt = sndbuf_getready(b); 418 if (amt > 0) { 419 c->xruns++; 420 sndbuf_dispose(b, NULL, amt); 421 } 422 423 chn_wakeup(c); 424 425 return ret; 426 } 427 428 void 429 chn_rdupdate(struct pcm_channel *c) 430 { 431 int ret; 432 433 CHN_LOCKASSERT(c); 434 KASSERT(c->direction == PCMDIR_REC, ("chn_rdupdate on bad channel")); 435 436 if ((c->flags & CHN_F_MAPPED) || !(c->flags & CHN_F_TRIGGERED)) 437 return; 438 chn_trigger(c, PCMTRIG_EMLDMARD); 439 chn_dmaupdate(c); 440 ret = chn_rdfeed(c); 441 DEB(if (ret) 442 kprintf("chn_rdfeed: %d\n", ret);) 443 } 444 445 /* read interrupt routine. Must be called with interrupts blocked. */ 446 static void 447 chn_rdintr(struct pcm_channel *c) 448 { 449 int ret; 450 451 CHN_LOCKASSERT(c); 452 /* tell the driver to update the primary buffer if non-dma */ 453 chn_trigger(c, PCMTRIG_EMLDMARD); 454 /* update pointers in primary buffer */ 455 chn_dmaupdate(c); 456 /* ...and feed from primary to secondary */ 457 ret = chn_rdfeed(c); 458 } 459 460 /* 461 * user read routine - trigger if necessary, uiomove data from secondary buffer 462 * if blocking, sleep, rinse and repeat. 463 * 464 * called externally, so must handle locking 465 */ 466 467 int 468 chn_read(struct pcm_channel *c, struct uio *buf, int ioflags) 469 { 470 int ret, timeout, sz, count; 471 int nbio; 472 struct snd_dbuf *bs = c->bufsoft; 473 void *off; 474 int t, x,togo,p; 475 476 CHN_LOCKASSERT(c); 477 nbio = (c->flags & CHN_F_NBIO) || (ioflags & IO_NDELAY); 478 if (!(c->flags & CHN_F_TRIGGERED)) 479 chn_start(c, 0); 480 481 ret = 0; 482 count = hz; 483 while (!ret && (buf->uio_resid > 0) && (count > 0)) { 484 sz = MIN(buf->uio_resid, sndbuf_getready(bs)); 485 486 if (sz > 0) { 487 /* 488 * The following assumes that the free space in 489 * the buffer can never be less around the 490 * unlock-uiomove-lock sequence. 491 */ 492 togo = sz; 493 while (ret == 0 && togo> 0) { 494 p = sndbuf_getreadyptr(bs); 495 t = MIN(togo, sndbuf_getsize(bs) - p); 496 off = sndbuf_getbufofs(bs, p); 497 CHN_UNLOCK(c); 498 ret = uiomove(off, t, buf); 499 CHN_LOCK(c); 500 togo -= t; 501 x = sndbuf_dispose(bs, NULL, t); 502 } 503 ret = 0; 504 } else { 505 if (nbio) { 506 ret = EWOULDBLOCK; 507 } else { 508 timeout = (hz * sndbuf_getblksz(bs)) / (sndbuf_getspd(bs) * sndbuf_getbps(bs)); 509 if (timeout < 1) 510 timeout = 1; 511 ret = chn_sleep(c, "pcmrd", timeout); 512 if (ret == EWOULDBLOCK) { 513 count -= timeout; 514 ret = 0; 515 } else { 516 count = hz; 517 } 518 519 } 520 } 521 } 522 523 if (count <= 0) { 524 c->flags |= CHN_F_DEAD; 525 kprintf("%s: record interrupt timeout, channel dead\n", c->name); 526 } 527 528 return ret; 529 } 530 531 void 532 chn_intr(struct pcm_channel *c) 533 { 534 CHN_LOCK(c); 535 c->interrupts++; 536 if (c->direction == PCMDIR_PLAY) 537 chn_wrintr(c); 538 else 539 chn_rdintr(c); 540 CHN_UNLOCK(c); 541 } 542 543 u_int32_t 544 chn_start(struct pcm_channel *c, int force) 545 { 546 u_int32_t i, j; 547 struct snd_dbuf *b = c->bufhard; 548 struct snd_dbuf *bs = c->bufsoft; 549 550 CHN_LOCKASSERT(c); 551 /* if we're running, or if we're prevented from triggering, bail */ 552 if ((c->flags & CHN_F_TRIGGERED) || ((c->flags & CHN_F_NOTRIGGER) && !force)) 553 return EINVAL; 554 555 i = (c->direction == PCMDIR_PLAY)? sndbuf_getready(bs) : sndbuf_getfree(bs); 556 j = (c->direction == PCMDIR_PLAY)? sndbuf_getfree(b) : sndbuf_getready(b); 557 if (force || (i >= j)) { 558 c->flags |= CHN_F_TRIGGERED; 559 /* 560 * if we're starting because a vchan started, don't feed any data 561 * or it becomes impossible to start vchans synchronised with the 562 * first one. the hardbuf should be empty so we top it up with 563 * silence to give it something to chew. the real data will be 564 * fed at the first irq. 565 */ 566 if (c->direction == PCMDIR_PLAY) { 567 /* 568 * Reduce pops during playback startup. 569 */ 570 sndbuf_fillsilence(b); 571 if (SLIST_EMPTY(&c->children)) 572 chn_wrfeed(c); 573 } 574 sndbuf_setrun(b, 1); 575 c->xruns = 0; 576 chn_trigger(c, PCMTRIG_START); 577 return 0; 578 } 579 580 return 0; 581 } 582 583 void 584 chn_resetbuf(struct pcm_channel *c) 585 { 586 struct snd_dbuf *b = c->bufhard; 587 struct snd_dbuf *bs = c->bufsoft; 588 589 c->blocks = 0; 590 sndbuf_reset(b); 591 sndbuf_reset(bs); 592 } 593 594 /* 595 * chn_sync waits until the space in the given channel goes above 596 * a threshold. The threshold is checked against fl or rl respectively. 597 * Assume that the condition can become true, do not check here... 598 */ 599 int 600 chn_sync(struct pcm_channel *c, int threshold) 601 { 602 u_long rdy; 603 int ret; 604 struct snd_dbuf *bs = c->bufsoft; 605 606 CHN_LOCKASSERT(c); 607 608 /* if we haven't yet started and nothing is buffered, else start*/ 609 if (!(c->flags & CHN_F_TRIGGERED)) { 610 if (sndbuf_getready(bs) > 0) { 611 ret = chn_start(c, 1); 612 if (ret) 613 return ret; 614 } else { 615 return 0; 616 } 617 } 618 619 for (;;) { 620 rdy = (c->direction == PCMDIR_PLAY)? sndbuf_getfree(bs) : sndbuf_getready(bs); 621 if (rdy <= threshold) { 622 ret = chn_sleep(c, "pcmsyn", 1); 623 if (ret == ERESTART || ret == EINTR) { 624 DEB(kprintf("chn_sync: tsleep returns %d\n", ret)); 625 return -1; 626 } 627 } else 628 break; 629 } 630 return 0; 631 } 632 633 /* called externally, handle locking */ 634 int 635 chn_poll(struct pcm_channel *c, int ev, struct thread *td) 636 { 637 struct snd_dbuf *bs = c->bufsoft; 638 int ret; 639 640 CHN_LOCKASSERT(c); 641 if (!(c->flags & CHN_F_MAPPED) && !(c->flags & CHN_F_TRIGGERED)) 642 chn_start(c, 1); 643 ret = 0; 644 if (chn_polltrigger(c) && chn_pollreset(c)) 645 ret = ev; 646 else 647 selrecord(td, sndbuf_getsel(bs)); 648 return ret; 649 } 650 651 /* 652 * chn_abort terminates a running dma transfer. it may sleep up to 200ms. 653 * it returns the number of bytes that have not been transferred. 654 * 655 * called from: dsp_close, dsp_ioctl, with channel locked 656 */ 657 int 658 chn_abort(struct pcm_channel *c) 659 { 660 int missing = 0; 661 struct snd_dbuf *b = c->bufhard; 662 struct snd_dbuf *bs = c->bufsoft; 663 664 CHN_LOCKASSERT(c); 665 if (!(c->flags & CHN_F_TRIGGERED)) 666 return 0; 667 c->flags |= CHN_F_ABORTING; 668 669 c->flags &= ~CHN_F_TRIGGERED; 670 /* kill the channel */ 671 chn_trigger(c, PCMTRIG_ABORT); 672 sndbuf_setrun(b, 0); 673 if (!(c->flags & CHN_F_VIRTUAL)) 674 chn_dmaupdate(c); 675 missing = sndbuf_getready(bs) + sndbuf_getready(b); 676 677 c->flags &= ~CHN_F_ABORTING; 678 return missing; 679 } 680 681 /* 682 * this routine tries to flush the dma transfer. It is called 683 * on a close of a playback channel. 684 * first, if there is data in the buffer, but the dma has not yet 685 * begun, we need to start it. 686 * next, we wait for the play buffer to drain 687 * finally, we stop the dma. 688 * 689 * called from: dsp_close, not valid for record channels. 690 */ 691 692 int 693 chn_flush(struct pcm_channel *c) 694 { 695 int ret, count, resid, resid_p; 696 struct snd_dbuf *b = c->bufhard; 697 struct snd_dbuf *bs = c->bufsoft; 698 699 CHN_LOCKASSERT(c); 700 KASSERT(c->direction == PCMDIR_PLAY, ("chn_flush on bad channel")); 701 DEB(kprintf("chn_flush: c->flags 0x%08x\n", c->flags)); 702 703 /* if we haven't yet started and nothing is buffered, else start*/ 704 if (!(c->flags & CHN_F_TRIGGERED)) { 705 if (sndbuf_getready(bs) > 0) { 706 ret = chn_start(c, 1); 707 if (ret) 708 return ret; 709 } else { 710 return 0; 711 } 712 } 713 714 c->flags |= CHN_F_CLOSING; 715 resid = sndbuf_getready(bs) + sndbuf_getready(b); 716 resid_p = resid; 717 count = 10; 718 ret = 0; 719 while ((count > 0) && (resid > sndbuf_getsize(b)) && (ret == 0)) { 720 /* still pending output data. */ 721 ret = chn_sleep(c, "pcmflu", hz / 10); 722 if (ret == EWOULDBLOCK) 723 ret = 0; 724 if (ret == 0) { 725 resid = sndbuf_getready(bs) + sndbuf_getready(b); 726 if (resid == resid_p) 727 count--; 728 if (resid > resid_p) 729 DEB(printf("chn_flush: buffer length increasind %d -> %d\n", resid_p, resid)); 730 resid_p = resid; 731 } 732 } 733 if (count == 0) 734 DEB(kprintf("chn_flush: timeout, hw %d, sw %d\n", 735 sndbuf_getready(b), sndbuf_getready(bs))); 736 737 c->flags &= ~CHN_F_TRIGGERED; 738 /* kill the channel */ 739 chn_trigger(c, PCMTRIG_ABORT); 740 sndbuf_setrun(b, 0); 741 742 c->flags &= ~CHN_F_CLOSING; 743 return 0; 744 } 745 746 int 747 fmtvalid(u_int32_t fmt, u_int32_t *fmtlist) 748 { 749 int i; 750 751 for (i = 0; fmtlist[i]; i++) 752 if (fmt == fmtlist[i]) 753 return 1; 754 return 0; 755 } 756 757 int 758 chn_reset(struct pcm_channel *c, u_int32_t fmt) 759 { 760 int hwspd, r; 761 762 CHN_LOCKASSERT(c); 763 c->flags &= CHN_F_RESET; 764 c->interrupts = 0; 765 c->xruns = 0; 766 767 r = CHANNEL_RESET(c->methods, c->devinfo); 768 if (fmt != 0) { 769 #if 0 770 hwspd = DSP_DEFAULT_SPEED; 771 /* only do this on a record channel until feederbuilder works */ 772 if (c->direction == PCMDIR_REC) 773 RANGE(hwspd, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed); 774 c->speed = hwspd; 775 #endif 776 hwspd = chn_getcaps(c)->minspeed; 777 c->speed = hwspd; 778 779 if (r == 0) 780 r = chn_setformat(c, fmt); 781 if (r == 0) 782 r = chn_setspeed(c, hwspd); 783 #if 0 784 if (r == 0) 785 r = chn_setvolume(c, 100, 100); 786 #endif 787 } 788 if (r == 0) 789 r = chn_setblocksize(c, 0, 0); 790 if (r == 0) { 791 chn_resetbuf(c); 792 r = CHANNEL_RESETDONE(c->methods, c->devinfo); 793 } 794 return r; 795 } 796 797 int 798 chn_init(struct pcm_channel *c, void *devinfo, int dir, int direction) 799 { 800 struct feeder_class *fc; 801 struct snd_dbuf *b, *bs; 802 int ret; 803 804 chn_lockinit(c, dir); 805 806 b = NULL; 807 bs = NULL; 808 c->devinfo = NULL; 809 c->feeder = NULL; 810 811 ret = ENOMEM; 812 b = sndbuf_create(c->dev, c->name, "primary", c); 813 if (b == NULL) 814 goto out; 815 bs = sndbuf_create(c->dev, c->name, "secondary", c); 816 if (bs == NULL) 817 goto out; 818 819 CHN_LOCK(c); 820 821 ret = EINVAL; 822 fc = feeder_getclass(NULL); 823 if (fc == NULL) 824 goto out; 825 if (chn_addfeeder(c, fc, NULL)) 826 goto out; 827 828 /* 829 * XXX - sndbuf_setup() & sndbuf_resize() expect to be called 830 * with the channel unlocked because they are also called 831 * from driver methods that don't know about locking 832 */ 833 CHN_UNLOCK(c); 834 sndbuf_setup(bs, NULL, 0); 835 CHN_LOCK(c); 836 c->bufhard = b; 837 c->bufsoft = bs; 838 c->flags = 0; 839 c->feederflags = 0; 840 841 ret = ENODEV; 842 CHN_UNLOCK(c); /* XXX - Unlock for CHANNEL_INIT() kmalloc() call */ 843 c->devinfo = CHANNEL_INIT(c->methods, devinfo, b, c, direction); 844 CHN_LOCK(c); 845 if (c->devinfo == NULL) 846 goto out; 847 848 ret = ENOMEM; 849 if ((sndbuf_getsize(b) == 0) && ((c->flags & CHN_F_VIRTUAL) == 0)) 850 goto out; 851 852 ret = chn_setdir(c, direction); 853 if (ret) 854 goto out; 855 856 ret = sndbuf_setfmt(b, AFMT_U8); 857 if (ret) 858 goto out; 859 860 ret = sndbuf_setfmt(bs, AFMT_U8); 861 if (ret) 862 goto out; 863 864 865 out: 866 CHN_UNLOCK(c); 867 if (ret) { 868 if (c->devinfo) { 869 if (CHANNEL_FREE(c->methods, c->devinfo)) 870 sndbuf_free(b); 871 } 872 if (bs) 873 sndbuf_destroy(bs); 874 if (b) 875 sndbuf_destroy(b); 876 c->flags |= CHN_F_DEAD; 877 chn_lockdestroy(c); 878 879 return ret; 880 } 881 882 return 0; 883 } 884 885 int 886 chn_kill(struct pcm_channel *c) 887 { 888 struct snd_dbuf *b = c->bufhard; 889 struct snd_dbuf *bs = c->bufsoft; 890 891 if (c->flags & CHN_F_TRIGGERED) 892 chn_trigger(c, PCMTRIG_ABORT); 893 while (chn_removefeeder(c) == 0); 894 if (CHANNEL_FREE(c->methods, c->devinfo)) 895 sndbuf_free(b); 896 c->flags |= CHN_F_DEAD; 897 sndbuf_destroy(bs); 898 sndbuf_destroy(b); 899 chn_lockdestroy(c); 900 return 0; 901 } 902 903 int 904 chn_setdir(struct pcm_channel *c, int dir) 905 { 906 #if NISA > 0 907 struct snd_dbuf *b = c->bufhard; 908 #endif 909 int r; 910 911 CHN_LOCKASSERT(c); 912 c->direction = dir; 913 r = CHANNEL_SETDIR(c->methods, c->devinfo, c->direction); 914 #if NISA > 0 915 if (!r && SND_DMA(b)) 916 sndbuf_dmasetdir(b, c->direction); 917 #endif 918 return r; 919 } 920 921 int 922 chn_setvolume(struct pcm_channel *c, int left, int right) 923 { 924 CHN_LOCKASSERT(c); 925 /* should add a feeder for volume changing if channel returns -1 */ 926 if (left > 100) 927 left = 100; 928 if (left < 0) 929 left = 0; 930 if (right > 100) 931 right = 100; 932 if (right < 0) 933 right = 0; 934 c->volume = left | (right << 8); 935 return 0; 936 } 937 938 static int 939 chn_tryspeed(struct pcm_channel *c, int speed) 940 { 941 struct pcm_feeder *f; 942 struct snd_dbuf *b = c->bufhard; 943 struct snd_dbuf *bs = c->bufsoft; 944 struct snd_dbuf *x; 945 int r, delta; 946 947 CHN_LOCKASSERT(c); 948 DEB(kprintf("setspeed, channel %s\n", c->name)); 949 DEB(kprintf("want speed %d, ", speed)); 950 if (speed <= 0) 951 return EINVAL; 952 if (CANCHANGE(c)) { 953 r = 0; 954 c->speed = speed; 955 sndbuf_setspd(bs, speed); 956 RANGE(speed, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed); 957 DEB(kprintf("try speed %d, ", speed)); 958 sndbuf_setspd(b, CHANNEL_SETSPEED(c->methods, c->devinfo, speed)); 959 DEB(kprintf("got speed %d\n", sndbuf_getspd(b))); 960 961 delta = sndbuf_getspd(b) - sndbuf_getspd(bs); 962 if (delta < 0) 963 delta = -delta; 964 965 c->feederflags &= ~(1 << FEEDER_RATE); 966 /* 967 * Used to be 500. It was too big! 968 */ 969 if (delta > 25) 970 c->feederflags |= 1 << FEEDER_RATE; 971 else 972 sndbuf_setspd(bs, sndbuf_getspd(b)); 973 974 r = chn_buildfeeder(c); 975 DEB(kprintf("r = %d\n", r)); 976 if (r) 977 goto out; 978 979 r = chn_setblocksize(c, 0, 0); 980 if (r) 981 goto out; 982 983 if (!(c->feederflags & (1 << FEEDER_RATE))) 984 goto out; 985 986 r = EINVAL; 987 f = chn_findfeeder(c, FEEDER_RATE); 988 DEB(kprintf("feedrate = %p\n", f)); 989 if (f == NULL) 990 goto out; 991 992 x = (c->direction == PCMDIR_REC)? b : bs; 993 r = FEEDER_SET(f, FEEDRATE_SRC, sndbuf_getspd(x)); 994 DEB(kprintf("feeder_set(FEEDRATE_SRC, %d) = %d\n", sndbuf_getspd(x), r)); 995 if (r) 996 goto out; 997 998 x = (c->direction == PCMDIR_REC)? bs : b; 999 r = FEEDER_SET(f, FEEDRATE_DST, sndbuf_getspd(x)); 1000 DEB(kprintf("feeder_set(FEEDRATE_DST, %d) = %d\n", sndbuf_getspd(x), r)); 1001 out: 1002 if (!r) 1003 r = CHANNEL_SETFORMAT(c->methods, c->devinfo, 1004 sndbuf_getfmt(b)); 1005 if (!r) 1006 sndbuf_setfmt(bs, c->format); 1007 DEB(kprintf("setspeed done, r = %d\n", r)); 1008 return r; 1009 } else 1010 return EINVAL; 1011 } 1012 1013 int 1014 chn_setspeed(struct pcm_channel *c, int speed) 1015 { 1016 int r, oldspeed = c->speed; 1017 1018 r = chn_tryspeed(c, speed); 1019 if (r) { 1020 DEB(kprintf("Failed to set speed %d falling back to %d\n", speed, oldspeed)); 1021 r = chn_tryspeed(c, oldspeed); 1022 } 1023 return r; 1024 } 1025 1026 static int 1027 chn_tryformat(struct pcm_channel *c, u_int32_t fmt) 1028 { 1029 struct snd_dbuf *b = c->bufhard; 1030 struct snd_dbuf *bs = c->bufsoft; 1031 int r; 1032 1033 CHN_LOCKASSERT(c); 1034 if (CANCHANGE(c)) { 1035 DEB(kprintf("want format %d\n", fmt)); 1036 c->format = fmt; 1037 r = chn_buildfeeder(c); 1038 if (r == 0) { 1039 sndbuf_setfmt(bs, c->format); 1040 chn_resetbuf(c); 1041 r = CHANNEL_SETFORMAT(c->methods, c->devinfo, sndbuf_getfmt(b)); 1042 if (r == 0) 1043 r = chn_tryspeed(c, c->speed); 1044 } 1045 return r; 1046 } else 1047 return EINVAL; 1048 } 1049 1050 int 1051 chn_setformat(struct pcm_channel *c, u_int32_t fmt) 1052 { 1053 u_int32_t oldfmt = c->format; 1054 int r; 1055 1056 r = chn_tryformat(c, fmt); 1057 if (r) { 1058 DEB(kprintf("Format change %d failed, reverting to %d\n", fmt, oldfmt)); 1059 chn_tryformat(c, oldfmt); 1060 } 1061 return r; 1062 } 1063 1064 /* 1065 * given a bufsz value, round it to a power of 2 in the min-max range 1066 * XXX only works if min and max are powers of 2 1067 */ 1068 static int 1069 round_bufsz(int bufsz, int min, int max) 1070 { 1071 int tmp = min * 2; 1072 1073 KASSERT((min & (min-1)) == 0, ("min %d must be power of 2\n", min)); 1074 KASSERT((max & (max-1)) == 0, ("max %d must be power of 2\n", max)); 1075 while (tmp <= bufsz) 1076 tmp <<= 1; 1077 tmp >>= 1; 1078 if (tmp > max) 1079 tmp = max; 1080 return tmp; 1081 } 1082 1083 /* 1084 * set the channel's blocksize both for soft and hard buffers. 1085 * 1086 * blksz should be a power of 2 between 2**4 and 2**16 -- it is useful 1087 * that it has the same value for both bufsoft and bufhard. 1088 * blksz == -1 computes values according to a target irq rate. 1089 * blksz == 0 reuses previous values if available, otherwise 1090 * behaves as for -1 1091 * 1092 * blkcnt is set by the user, between 2 and (2**17)/blksz for bufsoft, 1093 * but should be a power of 2 for bufhard to simplify life to low 1094 * level drivers. 1095 * Note, for the rec channel a large blkcnt is ok, 1096 * but for the play channel we want blksz as small as possible to keep 1097 * the delay small, because routines in the write path always try to 1098 * keep bufhard full. 1099 * 1100 * Unless we have good reason to, use the values suggested by the caller. 1101 */ 1102 int 1103 chn_setblocksize(struct pcm_channel *c, int blkcnt, int blksz) 1104 { 1105 struct snd_dbuf *b = c->bufhard; 1106 struct snd_dbuf *bs = c->bufsoft; 1107 int irqhz, ret, maxsz, maxsize, reqblksz; 1108 1109 CHN_LOCKASSERT(c); 1110 if (!CANCHANGE(c) || (c->flags & CHN_F_MAPPED)) { 1111 KASSERT(sndbuf_getsize(bs) == 0 || 1112 sndbuf_getsize(bs) >= sndbuf_getsize(b), 1113 ("%s(%s): bufsoft size %d < bufhard size %d", __func__, 1114 c->name, sndbuf_getsize(bs), sndbuf_getsize(b))); 1115 return EINVAL; 1116 } 1117 c->flags |= CHN_F_SETBLOCKSIZE; 1118 1119 ret = 0; 1120 DEB(kprintf("%s(%d, %d)\n", __func__, blkcnt, blksz)); 1121 if (blksz == 0 || blksz == -1) { /* let the driver choose values */ 1122 if (blksz == -1) /* delete previous values */ 1123 c->flags &= ~CHN_F_HAS_SIZE; 1124 if (!(c->flags & CHN_F_HAS_SIZE)) { /* no previous value */ 1125 /* 1126 * compute a base blksz according to the target irq 1127 * rate, then round to a suitable power of 2 1128 * in the range 16.. 2^17/2. 1129 * Finally compute a suitable blkcnt. 1130 */ 1131 blksz = round_bufsz( (sndbuf_getbps(bs) * 1132 sndbuf_getspd(bs)) / chn_targetirqrate, 1133 16, CHN_2NDBUFMAXSIZE / 2); 1134 blkcnt = CHN_2NDBUFMAXSIZE / blksz; 1135 } else { /* use previously defined value */ 1136 blkcnt = sndbuf_getblkcnt(bs); 1137 blksz = sndbuf_getblksz(bs); 1138 } 1139 } else { 1140 /* 1141 * use supplied values if reasonable. Note that here we 1142 * might have blksz which is not a power of 2 if the 1143 * ioctl() to compute it allows such values. 1144 */ 1145 ret = EINVAL; 1146 if ((blksz < 16) || (blkcnt < 2) || (blkcnt * blksz > CHN_2NDBUFMAXSIZE)) 1147 goto out; 1148 ret = 0; 1149 c->flags |= CHN_F_HAS_SIZE; 1150 } 1151 1152 reqblksz = blksz; 1153 if (reqblksz < sndbuf_getbps(bs)) 1154 reqblksz = sndbuf_getbps(bs); 1155 if (reqblksz % sndbuf_getbps(bs)) 1156 reqblksz -= reqblksz % sndbuf_getbps(bs); 1157 1158 /* adjust for different hw format/speed */ 1159 /* 1160 * Now compute the approx irq rate for the given (soft) blksz, 1161 * reduce to the acceptable range and compute a corresponding blksz 1162 * for the hard buffer. Then set the channel's blocksize and 1163 * corresponding hardbuf value. The number of blocks used should 1164 * be set by the device-specific routine. In fact, even the 1165 * call to sndbuf_setblksz() should not be here! XXX 1166 */ 1167 1168 irqhz = (sndbuf_getbps(bs) * sndbuf_getspd(bs)) / blksz; 1169 RANGE(irqhz, 16, 512); 1170 1171 maxsz = sndbuf_getmaxsize(b); 1172 if (maxsz == 0) /* virtual channels don't appear to allocate bufhard */ 1173 maxsz = CHN_2NDBUFMAXSIZE; 1174 blksz = round_bufsz( (sndbuf_getbps(b) * sndbuf_getspd(b)) / irqhz, 1175 16, maxsz / 2); 1176 1177 /* Increase the size of bufsoft if before increasing bufhard. */ 1178 maxsize = sndbuf_getsize(b); 1179 if (sndbuf_getsize(bs) > maxsize) 1180 maxsize = sndbuf_getsize(bs); 1181 if (reqblksz * blkcnt > maxsize) 1182 maxsize = reqblksz * blkcnt; 1183 if (sndbuf_getsize(bs) != maxsize || sndbuf_getblksz(bs) != reqblksz) { 1184 ret = sndbuf_remalloc(bs, maxsize/reqblksz, reqblksz); 1185 if (ret) 1186 goto out1; 1187 } 1188 1189 CHN_UNLOCK(c); 1190 sndbuf_setblksz(b, CHANNEL_SETBLOCKSIZE(c->methods, c->devinfo, blksz)); 1191 CHN_LOCK(c); 1192 1193 /* Decrease the size of bufsoft after decreasing bufhard. */ 1194 maxsize = sndbuf_getsize(b); 1195 if (reqblksz * blkcnt > maxsize) 1196 maxsize = reqblksz * blkcnt; 1197 if (maxsize > sndbuf_getsize(bs)) 1198 kprintf("Danger! %s bufsoft size increasing from %d to %d after CHANNEL_SETBLOCKSIZE()\n", 1199 c->name, sndbuf_getsize(bs), maxsize); 1200 if (sndbuf_getsize(bs) != maxsize || sndbuf_getblksz(bs) != reqblksz) { 1201 ret = sndbuf_remalloc(bs, maxsize/reqblksz, reqblksz); 1202 if (ret) 1203 goto out1; 1204 } 1205 1206 chn_resetbuf(c); 1207 out1: 1208 KASSERT(sndbuf_getsize(bs) == 0 || 1209 sndbuf_getsize(bs) >= sndbuf_getsize(b), 1210 ("%s(%s): bufsoft size %d < bufhard size %d, reqblksz=%d blksz=%d maxsize=%d blkcnt=%d", 1211 __func__, c->name, sndbuf_getsize(bs), sndbuf_getsize(b), reqblksz, 1212 blksz, maxsize, blkcnt)); 1213 out: 1214 c->flags &= ~CHN_F_SETBLOCKSIZE; 1215 #if 0 1216 if (1) { 1217 static uint32_t kk = 0; 1218 printf("%u: b %d/%d/%d : (%d)%d/0x%0x | bs %d/%d/%d : (%d)%d/0x%0x\n", ++kk, 1219 sndbuf_getsize(b), sndbuf_getblksz(b), sndbuf_getblkcnt(b), 1220 sndbuf_getbps(b), 1221 sndbuf_getspd(b), sndbuf_getfmt(b), 1222 sndbuf_getsize(bs), sndbuf_getblksz(bs), sndbuf_getblkcnt(bs), 1223 sndbuf_getbps(bs), 1224 sndbuf_getspd(bs), sndbuf_getfmt(bs)); 1225 if (sndbuf_getsize(b) % sndbuf_getbps(b) || 1226 sndbuf_getblksz(b) % sndbuf_getbps(b) || 1227 sndbuf_getsize(bs) % sndbuf_getbps(bs) || 1228 sndbuf_getblksz(b) % sndbuf_getbps(b)) { 1229 printf("%u: bps/blksz alignment screwed!\n", kk); 1230 } 1231 } 1232 #endif 1233 return ret; 1234 } 1235 1236 int 1237 chn_trigger(struct pcm_channel *c, int go) 1238 { 1239 #if NISA > 0 1240 struct snd_dbuf *b = c->bufhard; 1241 #endif 1242 int ret; 1243 1244 CHN_LOCKASSERT(c); 1245 #if NISA > 0 1246 if (SND_DMA(b) && (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)) 1247 sndbuf_dmabounce(b); 1248 #endif 1249 ret = CHANNEL_TRIGGER(c->methods, c->devinfo, go); 1250 1251 return ret; 1252 } 1253 1254 int 1255 chn_getptr(struct pcm_channel *c) 1256 { 1257 #if 0 1258 int hwptr; 1259 int a = (1 << c->align) - 1; 1260 1261 CHN_LOCKASSERT(c); 1262 hwptr = (c->flags & CHN_F_TRIGGERED)? CHANNEL_GETPTR(c->methods, c->devinfo) : 0; 1263 /* don't allow unaligned values in the hwa ptr */ 1264 #if 1 1265 hwptr &= ~a ; /* Apply channel align mask */ 1266 #endif 1267 hwptr &= DMA_ALIGN_MASK; /* Apply DMA align mask */ 1268 return hwptr; 1269 #endif 1270 int hwptr; 1271 1272 CHN_LOCKASSERT(c); 1273 hwptr = (c->flags & CHN_F_TRIGGERED)? CHANNEL_GETPTR(c->methods, c->devinfo) : 0; 1274 return (hwptr - (hwptr % sndbuf_getbps(c->bufhard))); 1275 } 1276 1277 struct pcmchan_caps * 1278 chn_getcaps(struct pcm_channel *c) 1279 { 1280 CHN_LOCKASSERT(c); 1281 return CHANNEL_GETCAPS(c->methods, c->devinfo); 1282 } 1283 1284 u_int32_t 1285 chn_getformats(struct pcm_channel *c) 1286 { 1287 u_int32_t *fmtlist, fmts; 1288 int i; 1289 1290 fmtlist = chn_getcaps(c)->fmtlist; 1291 fmts = 0; 1292 for (i = 0; fmtlist[i]; i++) 1293 fmts |= fmtlist[i]; 1294 1295 /* report software-supported formats */ 1296 if (report_soft_formats) 1297 fmts |= AFMT_MU_LAW|AFMT_A_LAW|AFMT_U32_LE|AFMT_U32_BE| 1298 AFMT_S32_LE|AFMT_S32_BE|AFMT_U24_LE|AFMT_U24_BE| 1299 AFMT_S24_LE|AFMT_S24_BE|AFMT_U16_LE|AFMT_U16_BE| 1300 AFMT_S16_LE|AFMT_S16_BE|AFMT_U8|AFMT_S8; 1301 1302 return fmts; 1303 } 1304 1305 static int 1306 chn_buildfeeder(struct pcm_channel *c) 1307 { 1308 struct feeder_class *fc; 1309 struct pcm_feederdesc desc; 1310 u_int32_t tmp[2], type, flags, hwfmt, *fmtlist; 1311 int err; 1312 1313 CHN_LOCKASSERT(c); 1314 while (chn_removefeeder(c) == 0); 1315 KASSERT((c->feeder == NULL), ("feeder chain not empty")); 1316 1317 c->align = sndbuf_getalign(c->bufsoft); 1318 1319 if (SLIST_EMPTY(&c->children)) { 1320 fc = feeder_getclass(NULL); 1321 KASSERT(fc != NULL, ("can't find root feeder")); 1322 1323 err = chn_addfeeder(c, fc, NULL); 1324 if (err) { 1325 DEB(kprintf("can't add root feeder, err %d\n", err)); 1326 1327 return err; 1328 } 1329 c->feeder->desc->out = c->format; 1330 } else { 1331 if (c->flags & CHN_F_HAS_VCHAN) { 1332 desc.type = FEEDER_MIXER; 1333 desc.in = 0; 1334 } else { 1335 DEB(printf("can't decide which feeder type to use!\n")); 1336 return EOPNOTSUPP; 1337 } 1338 desc.out = c->format; 1339 desc.flags = 0; 1340 fc = feeder_getclass(&desc); 1341 if (fc == NULL) { 1342 DEB(kprintf("can't find vchan feeder\n")); 1343 1344 return EOPNOTSUPP; 1345 } 1346 1347 err = chn_addfeeder(c, fc, &desc); 1348 if (err) { 1349 DEB(kprintf("can't add vchan feeder, err %d\n", err)); 1350 1351 return err; 1352 } 1353 } 1354 c->feederflags &= ~(1 << FEEDER_VOLUME); 1355 if (c->direction == PCMDIR_PLAY && 1356 !(c->flags & CHN_F_VIRTUAL) && 1357 c->parentsnddev && (c->parentsnddev->flags & SD_F_SOFTVOL) && 1358 c->parentsnddev->mixer_dev) 1359 c->feederflags |= 1 << FEEDER_VOLUME; 1360 flags = c->feederflags; 1361 fmtlist = chn_getcaps(c)->fmtlist; 1362 1363 DEB(kprintf("feederflags %x\n", flags)); 1364 1365 for (type = FEEDER_RATE; type <= FEEDER_LAST; type++) { 1366 if (flags & (1 << type)) { 1367 desc.type = type; 1368 desc.in = 0; 1369 desc.out = 0; 1370 desc.flags = 0; 1371 DEB(kprintf("find feeder type %d, ", type)); 1372 fc = feeder_getclass(&desc); 1373 DEB(kprintf("got %p\n", fc)); 1374 if (fc == NULL) { 1375 DEB(kprintf("can't find required feeder type %d\n", type)); 1376 1377 return EOPNOTSUPP; 1378 } 1379 1380 DEB(kprintf("build fmtchain from 0x%08x to 0x%08x: ", c->feeder->desc->out, fc->desc->in)); 1381 tmp[0] = fc->desc->in; 1382 tmp[1] = 0; 1383 if (chn_fmtchain(c, tmp) == 0) { 1384 DEB(printf("failed\n")); 1385 1386 return ENODEV; 1387 } 1388 DEB(printf("ok\n")); 1389 1390 err = chn_addfeeder(c, fc, fc->desc); 1391 if (err) { 1392 DEB(kprintf("can't add feeder %p, output 0x%x, err %d\n", fc, fc->desc->out, err)); 1393 1394 return err; 1395 } 1396 DEB(kprintf("added feeder %p, output 0x%x\n", fc, c->feeder->desc->out)); 1397 } 1398 } 1399 1400 if (c->direction == PCMDIR_REC) { 1401 tmp[0] = c->format; 1402 tmp[1] = 0; 1403 hwfmt = chn_fmtchain(c, tmp); 1404 } else 1405 hwfmt = chn_fmtchain(c, fmtlist); 1406 1407 if (hwfmt == 0 || !fmtvalid(hwfmt, fmtlist)) { 1408 DEB(printf("Invalid hardware format: 0x%08x\n", hwfmt)); 1409 return ENODEV; 1410 } 1411 1412 sndbuf_setfmt(c->bufhard, hwfmt); 1413 1414 if ((flags & (1 << FEEDER_VOLUME))) { 1415 struct dev_ioctl_args map; 1416 int vol = 100 | (100 << 8); 1417 1418 CHN_UNLOCK(c); 1419 /* 1420 * XXX This is ugly! The way mixer subs being so secretive 1421 * about its own internals force us to use this silly 1422 * monkey trick. 1423 */ 1424 map.a_head.a_dev = c->parentsnddev->mixer_dev; 1425 map.a_cmd = MIXER_READ(SOUND_MIXER_PCM); 1426 map.a_data = (caddr_t)&vol; 1427 map.a_fflag = -1; 1428 map.a_cred = NULL; 1429 if (mixer_ioctl(&map) != 0) 1430 device_printf(c->dev, "Soft Volume: Failed to read default value\n"); 1431 CHN_LOCK(c); 1432 chn_setvolume(c, vol & 0x7f, (vol >> 8) & 0x7f); 1433 } 1434 1435 return 0; 1436 } 1437 1438 int 1439 chn_notify(struct pcm_channel *c, u_int32_t flags) 1440 { 1441 struct pcmchan_children *pce; 1442 struct pcm_channel *child; 1443 int run; 1444 1445 CHN_LOCK(c); 1446 1447 if (SLIST_EMPTY(&c->children)) { 1448 CHN_UNLOCK(c); 1449 return ENODEV; 1450 } 1451 1452 run = (c->flags & CHN_F_TRIGGERED)? 1 : 0; 1453 /* 1454 * if the hwchan is running, we can't change its rate, format or 1455 * blocksize 1456 */ 1457 if (run) 1458 flags &= CHN_N_VOLUME | CHN_N_TRIGGER; 1459 1460 if (flags & CHN_N_RATE) { 1461 /* 1462 * we could do something here, like scan children and decide on 1463 * the most appropriate rate to mix at, but we don't for now 1464 */ 1465 } 1466 if (flags & CHN_N_FORMAT) { 1467 /* 1468 * we could do something here, like scan children and decide on 1469 * the most appropriate mixer feeder to use, but we don't for now 1470 */ 1471 } 1472 if (flags & CHN_N_VOLUME) { 1473 /* 1474 * we could do something here but we don't for now 1475 */ 1476 } 1477 if (flags & CHN_N_BLOCKSIZE) { 1478 int blksz; 1479 /* 1480 * scan the children, find the lowest blocksize and use that 1481 * for the hard blocksize 1482 */ 1483 blksz = sndbuf_getmaxsize(c->bufhard) / 2; 1484 SLIST_FOREACH(pce, &c->children, link) { 1485 child = pce->channel; 1486 CHN_LOCK(child); 1487 if (sndbuf_getblksz(child->bufhard) < blksz) 1488 blksz = sndbuf_getblksz(child->bufhard); 1489 CHN_UNLOCK(child); 1490 } 1491 chn_setblocksize(c, 2, blksz); 1492 } 1493 if (flags & CHN_N_TRIGGER) { 1494 int nrun; 1495 /* 1496 * scan the children, and figure out if any are running 1497 * if so, we need to be running, otherwise we need to be stopped 1498 * if we aren't in our target sstate, move to it 1499 */ 1500 nrun = 0; 1501 SLIST_FOREACH(pce, &c->children, link) { 1502 child = pce->channel; 1503 CHN_LOCK(child); 1504 if (child->flags & CHN_F_TRIGGERED) 1505 nrun = 1; 1506 CHN_UNLOCK(child); 1507 } 1508 if (nrun && !run) 1509 chn_start(c, 1); 1510 if (!nrun && run) 1511 chn_abort(c); 1512 } 1513 CHN_UNLOCK(c); 1514 return 0; 1515 } 1516 1517 void 1518 chn_lock(struct pcm_channel *c) 1519 { 1520 CHN_LOCK(c); 1521 } 1522 1523 void 1524 chn_unlock(struct pcm_channel *c) 1525 { 1526 CHN_UNLOCK(c); 1527 } 1528