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