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