1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2005-2009 Ariff Abdullah <ariff@FreeBSD.org> 5 * Portions Copyright (c) Ryan Beasley <ryan.beasley@gmail.com> - GSoC 2006 6 * Copyright (c) 1999 Cameron Grant <cg@FreeBSD.org> 7 * All rights reserved. 8 * Copyright (c) 2025 The FreeBSD Foundation 9 * 10 * Portions of this software were developed by Christos Margiolis 11 * <christos@FreeBSD.org> under sponsorship from the FreeBSD Foundation. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #ifdef HAVE_KERNEL_OPTION_HEADERS 36 #include "opt_snd.h" 37 #endif 38 39 #include <sys/refcount.h> 40 #include <dev/sound/pcm/sound.h> 41 42 #include "feeder_if.h" 43 44 #define SND_USE_FXDIV 45 #define SND_DECLARE_FXDIV 46 #include "snd_fxdiv_gen.h" 47 48 struct snd_dbuf * 49 sndbuf_create(struct pcm_channel *channel, uint32_t fmt, uint32_t spd, 50 const char *desc) 51 { 52 struct snd_dbuf *b; 53 54 b = malloc(sizeof(*b), M_DEVBUF, M_WAITOK | M_ZERO); 55 refcount_init(&b->refcount, 1); 56 snprintf(b->name, SNDBUF_NAMELEN, "%s:%s", channel->name, desc); 57 b->channel = channel; 58 sndbuf_setfmt(b, fmt); 59 sndbuf_setspd(b, spd); 60 61 return b; 62 } 63 64 void 65 sndbuf_destroy(struct snd_dbuf *b) 66 { 67 b->flags |= SNDBUF_F_DETACHED; 68 sndbuf_rele(b); 69 } 70 71 void 72 sndbuf_ref(struct snd_dbuf *b) 73 { 74 unsigned int count __diagused; 75 76 CHN_LOCK(b->channel); 77 count = refcount_acquire(&b->refcount); 78 KASSERT(count > 0, ("sndbuf %p refcount 0", b)); 79 CHN_UNLOCK(b->channel); 80 } 81 82 void 83 sndbuf_rele(struct snd_dbuf *b) 84 { 85 if (refcount_release(&b->refcount)) { 86 sndbuf_free(b); 87 KASSERT(refcount_load(&b->refcount) == 0, 88 ("sndbuf %p still referenced", b)); 89 free(b, M_DEVBUF); 90 } 91 } 92 93 static bool 94 sndbuf_busy(struct snd_dbuf *b) 95 { 96 CHN_LOCKASSERT(b->channel); 97 98 return (refcount_load(&b->refcount) > 1 || 99 (b->flags & SNDBUF_F_DETACHED) != 0 || 100 /* 101 * XXX-MJ CHN_F_MMAP is not reliable, but for software buffers the 102 * refcount accurately reflects whether the buffer is mapped. 103 * Ensure that there is no in-flight DMA transfer by checking 104 * CHN_F_TRIGGERED. This should really be checked at a higher 105 * layer, but this is tricky since chn_resizebuf() and 106 * sndbuf_resize() drop and reacquire the channel lock. 107 */ 108 (b->channel->flags & (CHN_F_MMAP | CHN_F_TRIGGERED)) != 0); 109 } 110 111 static void 112 sndbuf_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) 113 { 114 struct snd_dbuf *b = (struct snd_dbuf *)arg; 115 116 if (snd_verbose > 3) { 117 printf("sndbuf_setmap %lx, %lx; ", 118 (unsigned long)segs[0].ds_addr, 119 (unsigned long)segs[0].ds_len); 120 printf("%p -> %lx\n", b->buf, (unsigned long)segs[0].ds_addr); 121 } 122 if (error == 0) 123 b->buf_addr = segs[0].ds_addr; 124 else 125 b->buf_addr = 0; 126 } 127 128 /* 129 * Allocate memory for DMA buffer. If the device does not use DMA transfers, 130 * the driver can call malloc(9) and sndbuf_setup() itself. 131 */ 132 133 int 134 sndbuf_alloc(struct snd_dbuf *b, bus_dma_tag_t dmatag, int dmaflags, 135 unsigned int size) 136 { 137 int ret; 138 139 b->dmatag = dmatag; 140 b->dmaflags = dmaflags | BUS_DMA_NOWAIT | BUS_DMA_COHERENT; 141 b->maxsize = size; 142 b->bufsize = b->maxsize; 143 b->buf_addr = 0; 144 b->flags |= SNDBUF_F_MANAGED; 145 if (bus_dmamem_alloc(b->dmatag, (void **)&b->buf, b->dmaflags, 146 &b->dmamap)) { 147 sndbuf_free(b); 148 return (ENOMEM); 149 } 150 if (bus_dmamap_load(b->dmatag, b->dmamap, b->buf, b->maxsize, 151 sndbuf_setmap, b, BUS_DMA_NOWAIT) != 0 || b->buf_addr == 0) { 152 sndbuf_free(b); 153 return (ENOMEM); 154 } 155 156 ret = sndbuf_resize(b, 2, b->maxsize / 2); 157 if (ret != 0) 158 sndbuf_free(b); 159 160 return (ret); 161 } 162 163 int 164 sndbuf_setup(struct snd_dbuf *b, void *buf, unsigned int size) 165 { 166 b->flags &= ~SNDBUF_F_MANAGED; 167 if (buf) 168 b->flags |= SNDBUF_F_MANAGED; 169 b->buf = buf; 170 b->maxsize = size; 171 b->bufsize = b->maxsize; 172 return sndbuf_resize(b, 2, b->maxsize / 2); 173 } 174 175 void 176 sndbuf_free(struct snd_dbuf *b) 177 { 178 free(b->tmpbuf, M_DEVBUF); 179 free(b->shadbuf, M_DEVBUF); 180 181 if (b->buf) { 182 if (b->flags & SNDBUF_F_MANAGED) { 183 if (b->buf_addr) 184 bus_dmamap_unload(b->dmatag, b->dmamap); 185 if (b->dmatag) 186 bus_dmamem_free(b->dmatag, b->buf, b->dmamap); 187 } else 188 free(b->buf, M_DEVBUF); 189 } 190 seldrain(&b->sel); 191 192 b->tmpbuf = NULL; 193 b->shadbuf = NULL; 194 b->buf = NULL; 195 b->sl = 0; 196 b->dmatag = NULL; 197 b->dmamap = NULL; 198 } 199 200 #define SNDBUF_CACHE_SHIFT 5 201 202 int 203 sndbuf_resize(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz) 204 { 205 unsigned int bufsize, allocsize; 206 uint8_t *tmpbuf; 207 208 CHN_LOCK(b->channel); 209 if (b->maxsize == 0) 210 goto out; 211 if (blkcnt == 0) 212 blkcnt = b->blkcnt; 213 if (blksz == 0) 214 blksz = b->blksz; 215 if (blkcnt < 2 || blksz < 16 || (blkcnt * blksz) > b->maxsize) { 216 CHN_UNLOCK(b->channel); 217 return EINVAL; 218 } 219 if (blkcnt == b->blkcnt && blksz == b->blksz) 220 goto out; 221 222 bufsize = blkcnt * blksz; 223 224 if (bufsize > b->allocsize || 225 bufsize < (b->allocsize >> SNDBUF_CACHE_SHIFT)) { 226 if (sndbuf_busy(b)) { 227 CHN_UNLOCK(b->channel); 228 return (EBUSY); 229 } 230 allocsize = round_page(bufsize); 231 CHN_UNLOCK(b->channel); 232 tmpbuf = malloc(allocsize, M_DEVBUF, M_WAITOK); 233 CHN_LOCK(b->channel); 234 if (sndbuf_busy(b)) { 235 CHN_UNLOCK(b->channel); 236 free(tmpbuf, M_DEVBUF); 237 return (EBUSY); 238 } 239 if (snd_verbose > 3) 240 printf("%s(): b=%p %p -> %p [%d -> %d : %d]\n", 241 __func__, b, b->tmpbuf, tmpbuf, 242 b->allocsize, allocsize, bufsize); 243 free(b->tmpbuf, M_DEVBUF); 244 b->tmpbuf = tmpbuf; 245 b->allocsize = allocsize; 246 } else if (snd_verbose > 3) 247 printf("%s(): b=%p %d [%d] NOCHANGE\n", 248 __func__, b, b->allocsize, b->bufsize); 249 250 b->blkcnt = blkcnt; 251 b->blksz = blksz; 252 b->bufsize = bufsize; 253 254 sndbuf_reset(b); 255 out: 256 CHN_UNLOCK(b->channel); 257 return 0; 258 } 259 260 int 261 sndbuf_remalloc(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz) 262 { 263 unsigned int bufsize, allocsize; 264 uint8_t *buf, *tmpbuf, *shadbuf; 265 266 if (blkcnt < 2 || blksz < 16) 267 return EINVAL; 268 269 CHN_LOCKASSERT(b->channel); 270 271 bufsize = blksz * blkcnt; 272 273 if (bufsize > b->allocsize || 274 bufsize < (b->allocsize >> SNDBUF_CACHE_SHIFT)) { 275 if (sndbuf_busy(b)) 276 return (EBUSY); 277 allocsize = round_page(bufsize); 278 CHN_UNLOCK(b->channel); 279 buf = malloc(allocsize, M_DEVBUF, M_WAITOK); 280 tmpbuf = malloc(allocsize, M_DEVBUF, M_WAITOK); 281 shadbuf = malloc(allocsize, M_DEVBUF, M_WAITOK); 282 CHN_LOCK(b->channel); 283 if (sndbuf_busy(b)) { 284 free(buf, M_DEVBUF); 285 free(tmpbuf, M_DEVBUF); 286 free(shadbuf, M_DEVBUF); 287 return (EBUSY); 288 } 289 free(b->buf, M_DEVBUF); 290 b->buf = buf; 291 free(b->tmpbuf, M_DEVBUF); 292 b->tmpbuf = tmpbuf; 293 free(b->shadbuf, M_DEVBUF); 294 b->shadbuf = shadbuf; 295 if (snd_verbose > 3) 296 printf("%s(): b=%p %d -> %d [%d]\n", 297 __func__, b, b->allocsize, allocsize, bufsize); 298 b->allocsize = allocsize; 299 } else if (snd_verbose > 3) 300 printf("%s(): b=%p %d [%d] NOCHANGE\n", 301 __func__, b, b->allocsize, b->bufsize); 302 303 b->blkcnt = blkcnt; 304 b->blksz = blksz; 305 b->bufsize = bufsize; 306 b->maxsize = bufsize; 307 b->sl = bufsize; 308 309 sndbuf_reset(b); 310 311 return 0; 312 } 313 314 /** 315 * @brief Zero out space in buffer free area 316 * 317 * This function clears a chunk of @c length bytes in the buffer free area 318 * (i.e., where the next write will be placed). 319 * 320 * @param b buffer context 321 * @param length number of bytes to blank 322 */ 323 void 324 sndbuf_clear(struct snd_dbuf *b, unsigned int length) 325 { 326 int i; 327 uint8_t data, *p; 328 329 if (length == 0) 330 return; 331 if (length > b->bufsize) 332 length = b->bufsize; 333 334 data = sndbuf_zerodata(b->fmt); 335 i = sndbuf_getfreeptr(b); 336 p = b->buf; 337 for (; length > 0; length--, i++) 338 p[i % b->bufsize] = data; 339 } 340 341 /** 342 * @brief Zap buffer contents, resetting "ready area" fields 343 * 344 * @param b buffer context 345 */ 346 void 347 sndbuf_fillsilence(struct snd_dbuf *b) 348 { 349 if (b->bufsize > 0) 350 memset(b->buf, sndbuf_zerodata(b->fmt), b->bufsize); 351 b->rp = 0; 352 b->rl = b->bufsize; 353 } 354 355 void 356 sndbuf_fillsilence_rl(struct snd_dbuf *b, unsigned int rl) 357 { 358 if (b->bufsize > 0) 359 memset(b->buf, sndbuf_zerodata(b->fmt), b->bufsize); 360 b->rp = 0; 361 b->rl = min(b->bufsize, rl); 362 } 363 364 /** 365 * @brief Reset buffer w/o flushing statistics 366 * 367 * This function just zeroes out buffer contents and sets the "ready length" 368 * to zero. This was originally to facilitate minimal playback interruption 369 * (i.e., dropped samples) in SNDCTL_DSP_SILENCE/SKIP ioctls. 370 * 371 * @param b buffer context 372 */ 373 void 374 sndbuf_softreset(struct snd_dbuf *b) 375 { 376 b->rl = 0; 377 if (b->buf && b->bufsize > 0) 378 sndbuf_clear(b, b->bufsize); 379 } 380 381 void 382 sndbuf_reset(struct snd_dbuf *b) 383 { 384 b->hp = 0; 385 b->rp = 0; 386 b->rl = 0; 387 b->dl = 0; 388 b->prev_total = 0; 389 b->total = 0; 390 b->xrun = 0; 391 if (b->buf && b->bufsize > 0) 392 sndbuf_clear(b, b->bufsize); 393 sndbuf_clearshadow(b); 394 } 395 396 int 397 sndbuf_setfmt(struct snd_dbuf *b, uint32_t fmt) 398 { 399 b->fmt = fmt; 400 b->bps = AFMT_BPS(b->fmt); 401 b->align = AFMT_ALIGN(b->fmt); 402 return 0; 403 } 404 405 void 406 sndbuf_setspd(struct snd_dbuf *b, unsigned int spd) 407 { 408 b->spd = spd; 409 } 410 411 void * 412 sndbuf_getbufofs(struct snd_dbuf *b, unsigned int ofs) 413 { 414 KASSERT(ofs < b->bufsize, ("%s: ofs invalid %d", __func__, ofs)); 415 416 return b->buf + ofs; 417 } 418 419 unsigned int 420 sndbuf_runsz(struct snd_dbuf *b) 421 { 422 return b->dl; 423 } 424 425 void 426 sndbuf_setrun(struct snd_dbuf *b, int go) 427 { 428 b->dl = go? b->blksz : 0; 429 } 430 431 void 432 sndbuf_setxrun(struct snd_dbuf *b, unsigned int xrun) 433 { 434 b->xrun = xrun; 435 } 436 437 unsigned int 438 sndbuf_getready(struct snd_dbuf *b) 439 { 440 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl)); 441 442 return b->rl; 443 } 444 445 unsigned int 446 sndbuf_getreadyptr(struct snd_dbuf *b) 447 { 448 KASSERT((b->rp >= 0) && (b->rp <= b->bufsize), ("%s: b->rp invalid %d", __func__, b->rp)); 449 450 return b->rp; 451 } 452 453 unsigned int 454 sndbuf_getfree(struct snd_dbuf *b) 455 { 456 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl)); 457 458 return b->bufsize - b->rl; 459 } 460 461 unsigned int 462 sndbuf_getfreeptr(struct snd_dbuf *b) 463 { 464 KASSERT((b->rp >= 0) && (b->rp <= b->bufsize), ("%s: b->rp invalid %d", __func__, b->rp)); 465 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl)); 466 467 return (b->rp + b->rl) % b->bufsize; 468 } 469 470 uint64_t 471 sndbuf_getblocks(struct snd_dbuf *b) 472 { 473 return b->total / b->blksz; 474 } 475 476 unsigned int 477 sndbuf_xbytes(unsigned int v, struct snd_dbuf *from, struct snd_dbuf *to) 478 { 479 if (from == NULL || to == NULL || v == 0) 480 return 0; 481 482 return snd_xbytes(v, from->align * from->spd, to->align * to->spd); 483 } 484 485 uint8_t 486 sndbuf_zerodata(uint32_t fmt) 487 { 488 if (fmt & (AFMT_SIGNED | AFMT_PASSTHROUGH)) 489 return (0x00); 490 else if (fmt & AFMT_MU_LAW) 491 return (0x7f); 492 else if (fmt & AFMT_A_LAW) 493 return (0x55); 494 return (0x80); 495 } 496 497 /************************************************************/ 498 499 /** 500 * @brief Acquire buffer space to extend ready area 501 * 502 * This function extends the ready area length by @c count bytes, and may 503 * optionally copy samples from another location stored in @c from. The 504 * counter @c snd_dbuf::total is also incremented by @c count bytes. 505 * 506 * @param b audio buffer 507 * @param from sample source (optional) 508 * @param count number of bytes to acquire 509 * 510 * @retval 0 Unconditional 511 */ 512 int 513 sndbuf_acquire(struct snd_dbuf *b, uint8_t *from, unsigned int count) 514 { 515 int l; 516 517 KASSERT(count <= sndbuf_getfree(b), ("%s: count %d > free %d", __func__, count, sndbuf_getfree(b))); 518 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl)); 519 b->total += count; 520 if (from != NULL) { 521 while (count > 0) { 522 l = min(count, b->bufsize - sndbuf_getfreeptr(b)); 523 bcopy(from, sndbuf_getbufofs(b, sndbuf_getfreeptr(b)), l); 524 from += l; 525 b->rl += l; 526 count -= l; 527 } 528 } else 529 b->rl += count; 530 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d, count %d", __func__, b->rl, count)); 531 532 return 0; 533 } 534 535 /** 536 * @brief Dispose samples from channel buffer, increasing size of ready area 537 * 538 * This function discards samples from the supplied buffer by advancing the 539 * ready area start pointer and decrementing the ready area length. If 540 * @c to is not NULL, then the discard samples will be copied to the location 541 * it points to. 542 * 543 * @param b PCM channel sound buffer 544 * @param to destination buffer (optional) 545 * @param count number of bytes to discard 546 * 547 * @returns 0 unconditionally 548 */ 549 int 550 sndbuf_dispose(struct snd_dbuf *b, uint8_t *to, unsigned int count) 551 { 552 int l; 553 554 KASSERT(count <= sndbuf_getready(b), ("%s: count %d > ready %d", __func__, count, sndbuf_getready(b))); 555 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl)); 556 if (to != NULL) { 557 while (count > 0) { 558 l = min(count, b->bufsize - sndbuf_getreadyptr(b)); 559 bcopy(sndbuf_getbufofs(b, sndbuf_getreadyptr(b)), to, l); 560 to += l; 561 b->rl -= l; 562 b->rp = (b->rp + l) % b->bufsize; 563 count -= l; 564 } 565 } else { 566 b->rl -= count; 567 b->rp = (b->rp + count) % b->bufsize; 568 } 569 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d, count %d", __func__, b->rl, count)); 570 571 return 0; 572 } 573 574 /* count is number of bytes we want added to destination buffer */ 575 int 576 sndbuf_feed(struct snd_dbuf *from, struct snd_dbuf *to, struct pcm_channel *channel, struct pcm_feeder *feeder, unsigned int count) 577 { 578 unsigned int cnt, maxfeed; 579 580 KASSERT(count > 0, ("can't feed 0 bytes")); 581 582 if (sndbuf_getfree(to) < count) 583 return (EINVAL); 584 585 maxfeed = SND_FXROUND(SND_FXDIV_MAX, to->align); 586 587 do { 588 cnt = FEEDER_FEED(feeder, channel, to->tmpbuf, 589 min(count, maxfeed), from); 590 if (cnt == 0) 591 break; 592 sndbuf_acquire(to, to->tmpbuf, cnt); 593 count -= cnt; 594 } while (count != 0); 595 596 return (0); 597 } 598 599 /** 600 * @brief Clear the shadow buffer by filling with samples equal to zero. 601 * 602 * @param b buffer to clear 603 */ 604 void 605 sndbuf_clearshadow(struct snd_dbuf *b) 606 { 607 KASSERT(b != NULL, ("b is a null pointer")); 608 KASSERT(b->sl >= 0, ("illegal shadow length")); 609 610 if ((b->shadbuf != NULL) && (b->sl > 0)) 611 memset(b->shadbuf, sndbuf_zerodata(b->fmt), b->sl); 612 } 613 614 #ifdef OSSV4_EXPERIMENT 615 /** 616 * @brief Return peak value from samples in buffer ready area. 617 * 618 * Peak ranges from 0-32767. If channel is monaural, most significant 16 619 * bits will be zero. For now, only expects to work with 1-2 channel 620 * buffers. 621 * 622 * @note Currently only operates with linear PCM formats. 623 * 624 * @param b buffer to analyze 625 * @param lpeak pointer to store left peak value 626 * @param rpeak pointer to store right peak value 627 */ 628 void 629 sndbuf_getpeaks(struct snd_dbuf *b, int *lp, int *rp) 630 { 631 uint32_t lpeak, rpeak; 632 633 lpeak = 0; 634 rpeak = 0; 635 636 /** 637 * @todo fill this in later 638 */ 639 } 640 #endif 641