1 /*- 2 * Copyright (c) 1999 Cameron Grant <cg@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <dev/sound/pcm/sound.h> 28 29 #include "feeder_if.h" 30 31 SND_DECLARE_FILE("$FreeBSD$"); 32 33 struct snd_dbuf * 34 sndbuf_create(device_t dev, char *drv, char *desc, struct pcm_channel *channel) 35 { 36 struct snd_dbuf *b; 37 38 b = malloc(sizeof(*b), M_DEVBUF, M_WAITOK | M_ZERO); 39 snprintf(b->name, SNDBUF_NAMELEN, "%s:%s", drv, desc); 40 b->dev = dev; 41 b->channel = channel; 42 43 return b; 44 } 45 46 void 47 sndbuf_destroy(struct snd_dbuf *b) 48 { 49 sndbuf_free(b); 50 free(b, M_DEVBUF); 51 } 52 53 bus_addr_t 54 sndbuf_getbufaddr(struct snd_dbuf *buf) 55 { 56 return (buf->buf_addr); 57 } 58 59 static void 60 sndbuf_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) 61 { 62 struct snd_dbuf *b = (struct snd_dbuf *)arg; 63 64 if (bootverbose) { 65 device_printf(b->dev, "sndbuf_setmap %lx, %lx; ", 66 (u_long)segs[0].ds_addr, (u_long)segs[0].ds_len); 67 printf("%p -> %lx\n", b->buf, (u_long)segs[0].ds_addr); 68 } 69 if (error == 0) 70 b->buf_addr = segs[0].ds_addr; 71 else 72 b->buf_addr = 0; 73 } 74 75 /* 76 * Allocate memory for DMA buffer. If the device does not use DMA transfers, 77 * the driver can call malloc(9) and sndbuf_setup() itself. 78 */ 79 80 int 81 sndbuf_alloc(struct snd_dbuf *b, bus_dma_tag_t dmatag, unsigned int size) 82 { 83 int ret; 84 85 b->dmatag = dmatag; 86 b->maxsize = size; 87 b->bufsize = b->maxsize; 88 b->buf_addr = 0; 89 b->flags |= SNDBUF_F_MANAGED; 90 if (bus_dmamem_alloc(b->dmatag, (void **)&b->buf, BUS_DMA_NOWAIT, 91 &b->dmamap)) { 92 sndbuf_free(b); 93 return (ENOMEM); 94 } 95 if (bus_dmamap_load(b->dmatag, b->dmamap, b->buf, b->maxsize, 96 sndbuf_setmap, b, 0) != 0 || b->buf_addr == 0) { 97 sndbuf_free(b); 98 return (ENOMEM); 99 } 100 101 ret = sndbuf_resize(b, 2, b->maxsize / 2); 102 if (ret != 0) 103 sndbuf_free(b); 104 105 return (ret); 106 } 107 108 int 109 sndbuf_setup(struct snd_dbuf *b, void *buf, unsigned int size) 110 { 111 b->flags &= ~SNDBUF_F_MANAGED; 112 if (buf) 113 b->flags |= SNDBUF_F_MANAGED; 114 b->buf = buf; 115 b->maxsize = size; 116 b->bufsize = b->maxsize; 117 return sndbuf_resize(b, 2, b->maxsize / 2); 118 } 119 120 void 121 sndbuf_free(struct snd_dbuf *b) 122 { 123 if (b->tmpbuf) 124 free(b->tmpbuf, M_DEVBUF); 125 126 if (b->shadbuf) 127 free(b->shadbuf, M_DEVBUF); 128 129 if (b->buf) { 130 if (b->flags & SNDBUF_F_MANAGED) { 131 if (b->dmamap) 132 bus_dmamap_unload(b->dmatag, b->dmamap); 133 if (b->dmatag) 134 bus_dmamem_free(b->dmatag, b->buf, b->dmamap); 135 } else 136 free(b->buf, M_DEVBUF); 137 } 138 139 b->tmpbuf = NULL; 140 b->shadbuf = NULL; 141 b->buf = NULL; 142 b->sl = 0; 143 b->dmatag = NULL; 144 b->dmamap = NULL; 145 } 146 147 int 148 sndbuf_resize(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz) 149 { 150 u_int8_t *tmpbuf, *f2; 151 152 chn_lock(b->channel); 153 if (b->maxsize == 0) 154 goto out; 155 if (blkcnt == 0) 156 blkcnt = b->blkcnt; 157 if (blksz == 0) 158 blksz = b->blksz; 159 if (blkcnt < 2 || blksz < 16 || (blkcnt * blksz > b->maxsize)) { 160 chn_unlock(b->channel); 161 return EINVAL; 162 } 163 if (blkcnt == b->blkcnt && blksz == b->blksz) 164 goto out; 165 166 chn_unlock(b->channel); 167 tmpbuf = malloc(blkcnt * blksz, M_DEVBUF, M_NOWAIT); 168 if (tmpbuf == NULL) 169 return ENOMEM; 170 chn_lock(b->channel); 171 b->blkcnt = blkcnt; 172 b->blksz = blksz; 173 b->bufsize = blkcnt * blksz; 174 f2 = b->tmpbuf; 175 b->tmpbuf = tmpbuf; 176 sndbuf_reset(b); 177 chn_unlock(b->channel); 178 free(f2, M_DEVBUF); 179 return 0; 180 out: 181 chn_unlock(b->channel); 182 return 0; 183 } 184 185 int 186 sndbuf_remalloc(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz) 187 { 188 u_int8_t *buf, *tmpbuf, *f1, *f2; 189 u_int8_t *shadbuf, *f3; 190 unsigned int bufsize; 191 int ret; 192 193 if (blkcnt < 2 || blksz < 16) 194 return EINVAL; 195 196 bufsize = blksz * blkcnt; 197 198 chn_unlock(b->channel); 199 buf = malloc(bufsize, M_DEVBUF, M_WAITOK); 200 tmpbuf = malloc(bufsize, M_DEVBUF, M_WAITOK); 201 shadbuf = malloc(bufsize, M_DEVBUF, M_WAITOK); 202 203 chn_lock(b->channel); 204 205 b->blkcnt = blkcnt; 206 b->blksz = blksz; 207 b->bufsize = bufsize; 208 b->maxsize = bufsize; 209 f1 = b->buf; 210 f2 = b->tmpbuf; 211 b->buf = buf; 212 b->tmpbuf = tmpbuf; 213 f3 = b->shadbuf; 214 b->shadbuf = shadbuf; 215 b->sl = bufsize; 216 217 sndbuf_reset(b); 218 219 chn_unlock(b->channel); 220 if (f1) 221 free(f1, M_DEVBUF); 222 if (f2) 223 free(f2, M_DEVBUF); 224 if (f3) 225 free(f3, M_DEVBUF); 226 227 ret = 0; 228 229 chn_lock(b->channel); 230 return ret; 231 } 232 233 /** 234 * @brief Zero out space in buffer free area 235 * 236 * This function clears a chunk of @c length bytes in the buffer free area 237 * (i.e., where the next write will be placed). 238 * 239 * @param b buffer context 240 * @param length number of bytes to blank 241 */ 242 void 243 sndbuf_clear(struct snd_dbuf *b, unsigned int length) 244 { 245 int i; 246 u_char data, *p; 247 248 if (length == 0) 249 return; 250 if (length > b->bufsize) 251 length = b->bufsize; 252 253 data = sndbuf_zerodata(b->fmt); 254 255 i = sndbuf_getfreeptr(b); 256 p = sndbuf_getbuf(b); 257 while (length > 0) { 258 p[i] = data; 259 length--; 260 i++; 261 if (i >= b->bufsize) 262 i = 0; 263 } 264 } 265 266 /** 267 * @brief Zap buffer contents, resetting "ready area" fields 268 * 269 * @param b buffer context 270 */ 271 void 272 sndbuf_fillsilence(struct snd_dbuf *b) 273 { 274 if (b->bufsize > 0) 275 memset(sndbuf_getbuf(b), sndbuf_zerodata(b->fmt), b->bufsize); 276 b->rp = 0; 277 b->rl = b->bufsize; 278 } 279 280 /** 281 * @brief Reset buffer w/o flushing statistics 282 * 283 * This function just zeroes out buffer contents and sets the "ready length" 284 * to zero. This was originally to facilitate minimal playback interruption 285 * (i.e., dropped samples) in SNDCTL_DSP_SILENCE/SKIP ioctls. 286 * 287 * @param b buffer context 288 */ 289 void 290 sndbuf_softreset(struct snd_dbuf *b) 291 { 292 b->rl = 0; 293 if (b->buf && b->bufsize > 0) 294 sndbuf_clear(b, b->bufsize); 295 } 296 297 void 298 sndbuf_reset(struct snd_dbuf *b) 299 { 300 b->hp = 0; 301 b->rp = 0; 302 b->rl = 0; 303 b->dl = 0; 304 b->prev_total = 0; 305 b->total = 0; 306 b->xrun = 0; 307 if (b->buf && b->bufsize > 0) 308 sndbuf_clear(b, b->bufsize); 309 sndbuf_clearshadow(b); 310 } 311 312 u_int32_t 313 sndbuf_getfmt(struct snd_dbuf *b) 314 { 315 return b->fmt; 316 } 317 318 int 319 sndbuf_setfmt(struct snd_dbuf *b, u_int32_t fmt) 320 { 321 b->fmt = fmt; 322 b->bps = 1; 323 b->bps <<= (b->fmt & AFMT_STEREO)? 1 : 0; 324 if (b->fmt & AFMT_16BIT) 325 b->bps <<= 1; 326 else if (b->fmt & AFMT_24BIT) 327 b->bps *= 3; 328 else if (b->fmt & AFMT_32BIT) 329 b->bps <<= 2; 330 return 0; 331 } 332 333 unsigned int 334 sndbuf_getspd(struct snd_dbuf *b) 335 { 336 return b->spd; 337 } 338 339 void 340 sndbuf_setspd(struct snd_dbuf *b, unsigned int spd) 341 { 342 b->spd = spd; 343 } 344 345 unsigned int 346 sndbuf_getalign(struct snd_dbuf *b) 347 { 348 static int align[] = {0, 1, 1, 2, 2, 2, 2, 3}; 349 350 return align[b->bps - 1]; 351 } 352 353 unsigned int 354 sndbuf_getblkcnt(struct snd_dbuf *b) 355 { 356 return b->blkcnt; 357 } 358 359 void 360 sndbuf_setblkcnt(struct snd_dbuf *b, unsigned int blkcnt) 361 { 362 b->blkcnt = blkcnt; 363 } 364 365 unsigned int 366 sndbuf_getblksz(struct snd_dbuf *b) 367 { 368 return b->blksz; 369 } 370 371 void 372 sndbuf_setblksz(struct snd_dbuf *b, unsigned int blksz) 373 { 374 b->blksz = blksz; 375 } 376 377 unsigned int 378 sndbuf_getbps(struct snd_dbuf *b) 379 { 380 return b->bps; 381 } 382 383 void * 384 sndbuf_getbuf(struct snd_dbuf *b) 385 { 386 return b->buf; 387 } 388 389 void * 390 sndbuf_getbufofs(struct snd_dbuf *b, unsigned int ofs) 391 { 392 KASSERT(ofs < b->bufsize, ("%s: ofs invalid %d", __func__, ofs)); 393 394 return b->buf + ofs; 395 } 396 397 unsigned int 398 sndbuf_getsize(struct snd_dbuf *b) 399 { 400 return b->bufsize; 401 } 402 403 unsigned int 404 sndbuf_getmaxsize(struct snd_dbuf *b) 405 { 406 return b->maxsize; 407 } 408 409 unsigned int 410 sndbuf_runsz(struct snd_dbuf *b) 411 { 412 return b->dl; 413 } 414 415 void 416 sndbuf_setrun(struct snd_dbuf *b, int go) 417 { 418 b->dl = go? b->blksz : 0; 419 } 420 421 struct selinfo * 422 sndbuf_getsel(struct snd_dbuf *b) 423 { 424 return &b->sel; 425 } 426 427 /************************************************************/ 428 unsigned int 429 sndbuf_getxrun(struct snd_dbuf *b) 430 { 431 SNDBUF_LOCKASSERT(b); 432 433 return b->xrun; 434 } 435 436 void 437 sndbuf_setxrun(struct snd_dbuf *b, unsigned int xrun) 438 { 439 SNDBUF_LOCKASSERT(b); 440 441 b->xrun = xrun; 442 } 443 444 unsigned int 445 sndbuf_gethwptr(struct snd_dbuf *b) 446 { 447 SNDBUF_LOCKASSERT(b); 448 449 return b->hp; 450 } 451 452 void 453 sndbuf_sethwptr(struct snd_dbuf *b, unsigned int ptr) 454 { 455 SNDBUF_LOCKASSERT(b); 456 457 b->hp = ptr; 458 } 459 460 unsigned int 461 sndbuf_getready(struct snd_dbuf *b) 462 { 463 SNDBUF_LOCKASSERT(b); 464 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl)); 465 466 return b->rl; 467 } 468 469 unsigned int 470 sndbuf_getreadyptr(struct snd_dbuf *b) 471 { 472 SNDBUF_LOCKASSERT(b); 473 KASSERT((b->rp >= 0) && (b->rp <= b->bufsize), ("%s: b->rp invalid %d", __func__, b->rp)); 474 475 return b->rp; 476 } 477 478 unsigned int 479 sndbuf_getfree(struct snd_dbuf *b) 480 { 481 SNDBUF_LOCKASSERT(b); 482 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl)); 483 484 return b->bufsize - b->rl; 485 } 486 487 unsigned int 488 sndbuf_getfreeptr(struct snd_dbuf *b) 489 { 490 SNDBUF_LOCKASSERT(b); 491 KASSERT((b->rp >= 0) && (b->rp <= b->bufsize), ("%s: b->rp invalid %d", __func__, b->rp)); 492 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl)); 493 494 return (b->rp + b->rl) % b->bufsize; 495 } 496 497 unsigned int 498 sndbuf_getblocks(struct snd_dbuf *b) 499 { 500 SNDBUF_LOCKASSERT(b); 501 502 return b->total / b->blksz; 503 } 504 505 unsigned int 506 sndbuf_getprevblocks(struct snd_dbuf *b) 507 { 508 SNDBUF_LOCKASSERT(b); 509 510 return b->prev_total / b->blksz; 511 } 512 513 unsigned int 514 sndbuf_gettotal(struct snd_dbuf *b) 515 { 516 SNDBUF_LOCKASSERT(b); 517 518 return b->total; 519 } 520 521 void 522 sndbuf_updateprevtotal(struct snd_dbuf *b) 523 { 524 SNDBUF_LOCKASSERT(b); 525 526 b->prev_total = b->total; 527 } 528 529 unsigned int 530 snd_xbytes(unsigned int v, unsigned int from, unsigned int to) 531 { 532 unsigned int w, x, y; 533 534 if (from == to) 535 return v; 536 537 if (from == 0 || to == 0 || v == 0) 538 return 0; 539 540 x = from; 541 y = to; 542 while (y != 0) { 543 w = x % y; 544 x = y; 545 y = w; 546 } 547 from /= x; 548 to /= x; 549 550 return (unsigned int)(((u_int64_t)v * to) / from); 551 } 552 553 unsigned int 554 sndbuf_xbytes(unsigned int v, struct snd_dbuf *from, struct snd_dbuf *to) 555 { 556 if (from == NULL || to == NULL || v == 0) 557 return 0; 558 559 return snd_xbytes(v, sndbuf_getbps(from) * sndbuf_getspd(from), 560 sndbuf_getbps(to) * sndbuf_getspd(to)); 561 } 562 563 u_int8_t 564 sndbuf_zerodata(u_int32_t fmt) 565 { 566 if (fmt & AFMT_SIGNED) 567 return (0x00); 568 else if (fmt & AFMT_MU_LAW) 569 return (0x7f); 570 else if (fmt & AFMT_A_LAW) 571 return (0x55); 572 return (0x80); 573 } 574 575 /************************************************************/ 576 577 /** 578 * @brief Acquire buffer space to extend ready area 579 * 580 * This function extends the ready area length by @c count bytes, and may 581 * optionally copy samples from another location stored in @c from. The 582 * counter @c snd_dbuf::total is also incremented by @c count bytes. 583 * 584 * @param b audio buffer 585 * @param from sample source (optional) 586 * @param count number of bytes to acquire 587 * 588 * @retval 0 Unconditional 589 */ 590 int 591 sndbuf_acquire(struct snd_dbuf *b, u_int8_t *from, unsigned int count) 592 { 593 int l; 594 595 KASSERT(count <= sndbuf_getfree(b), ("%s: count %d > free %d", __func__, count, sndbuf_getfree(b))); 596 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl)); 597 b->total += count; 598 if (from != NULL) { 599 while (count > 0) { 600 l = min(count, sndbuf_getsize(b) - sndbuf_getfreeptr(b)); 601 bcopy(from, sndbuf_getbufofs(b, sndbuf_getfreeptr(b)), l); 602 from += l; 603 b->rl += l; 604 count -= l; 605 } 606 } else 607 b->rl += count; 608 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d, count %d", __func__, b->rl, count)); 609 610 return 0; 611 } 612 613 /** 614 * @brief Dispose samples from channel buffer, increasing size of ready area 615 * 616 * This function discards samples from the supplied buffer by advancing the 617 * ready area start pointer and decrementing the ready area length. If 618 * @c to is not NULL, then the discard samples will be copied to the location 619 * it points to. 620 * 621 * @param b PCM channel sound buffer 622 * @param to destination buffer (optional) 623 * @param count number of bytes to discard 624 * 625 * @returns 0 unconditionally 626 */ 627 int 628 sndbuf_dispose(struct snd_dbuf *b, u_int8_t *to, unsigned int count) 629 { 630 int l; 631 632 KASSERT(count <= sndbuf_getready(b), ("%s: count %d > ready %d", __func__, count, sndbuf_getready(b))); 633 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl)); 634 if (to != NULL) { 635 while (count > 0) { 636 l = min(count, sndbuf_getsize(b) - sndbuf_getreadyptr(b)); 637 bcopy(sndbuf_getbufofs(b, sndbuf_getreadyptr(b)), to, l); 638 to += l; 639 b->rl -= l; 640 b->rp = (b->rp + l) % b->bufsize; 641 count -= l; 642 } 643 } else { 644 b->rl -= count; 645 b->rp = (b->rp + count) % b->bufsize; 646 } 647 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d, count %d", __func__, b->rl, count)); 648 649 return 0; 650 } 651 652 /* count is number of bytes we want added to destination buffer */ 653 int 654 sndbuf_feed(struct snd_dbuf *from, struct snd_dbuf *to, struct pcm_channel *channel, struct pcm_feeder *feeder, unsigned int count) 655 { 656 unsigned int cnt; 657 658 KASSERT(count > 0, ("can't feed 0 bytes")); 659 660 if (sndbuf_getfree(to) < count) 661 return EINVAL; 662 663 do { 664 cnt = FEEDER_FEED(feeder, channel, to->tmpbuf, count, from); 665 if (cnt) 666 sndbuf_acquire(to, to->tmpbuf, cnt); 667 /* the root feeder has called sndbuf_dispose(from, , bytes fetched) */ 668 count -= cnt; 669 } while (count && cnt); 670 671 return 0; 672 } 673 674 /************************************************************/ 675 676 void 677 sndbuf_dump(struct snd_dbuf *b, char *s, u_int32_t what) 678 { 679 printf("%s: [", s); 680 if (what & 0x01) 681 printf(" bufsize: %d, maxsize: %d", b->bufsize, b->maxsize); 682 if (what & 0x02) 683 printf(" dl: %d, rp: %d, rl: %d, hp: %d", b->dl, b->rp, b->rl, b->hp); 684 if (what & 0x04) 685 printf(" total: %d, prev_total: %d, xrun: %d", b->total, b->prev_total, b->xrun); 686 if (what & 0x08) 687 printf(" fmt: 0x%x, spd: %d", b->fmt, b->spd); 688 if (what & 0x10) 689 printf(" blksz: %d, blkcnt: %d, flags: 0x%x", b->blksz, b->blkcnt, b->flags); 690 printf(" ]\n"); 691 } 692 693 /************************************************************/ 694 u_int32_t 695 sndbuf_getflags(struct snd_dbuf *b) 696 { 697 return b->flags; 698 } 699 700 void 701 sndbuf_setflags(struct snd_dbuf *b, u_int32_t flags, int on) 702 { 703 b->flags &= ~flags; 704 if (on) 705 b->flags |= flags; 706 } 707 708 /** 709 * @brief Clear the shadow buffer by filling with samples equal to zero. 710 * 711 * @param b buffer to clear 712 */ 713 void 714 sndbuf_clearshadow(struct snd_dbuf *b) 715 { 716 KASSERT(b != NULL, ("b is a null pointer")); 717 KASSERT(b->sl >= 0, ("illegal shadow length")); 718 719 if ((b->shadbuf != NULL) && (b->sl > 0)) 720 memset(b->shadbuf, sndbuf_zerodata(b->fmt), b->sl); 721 } 722 723 #ifdef OSSV4_EXPERIMENT 724 /** 725 * @brief Return peak value from samples in buffer ready area. 726 * 727 * Peak ranges from 0-32767. If channel is monaural, most significant 16 728 * bits will be zero. For now, only expects to work with 1-2 channel 729 * buffers. 730 * 731 * @note Currently only operates with linear PCM formats. 732 * 733 * @param b buffer to analyze 734 * @param lpeak pointer to store left peak value 735 * @param rpeak pointer to store right peak value 736 */ 737 void 738 sndbuf_getpeaks(struct snd_dbuf *b, int *lp, int *rp) 739 { 740 u_int32_t lpeak, rpeak; 741 742 lpeak = 0; 743 rpeak = 0; 744 745 /** 746 * @todo fill this in later 747 */ 748 } 749 #endif 750