Lines Matching +full:- +full:c
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
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 * Portions Copyright (c) Luigi Rizzo <luigi@FreeBSD.org> - 1997-99
43 &report_soft_formats, 0, "report software-emulated formats");
47 &report_soft_matrix, 0, "report software-emulated channel matrixing");
58 if (err != 0 || req->newptr == NULL) in sysctl_hw_snd_latency()
81 if (err != 0 || req->newptr == NULL) in sysctl_hw_snd_latency_profile()
104 if (err != 0 || req->newptr == NULL) in sysctl_hw_snd_timeout()
116 "interrupt timeout (1 - 10) seconds");
128 struct pcm_channel *c; in chn_vpc_proc() local
139 CHN_FOREACH(c, d, channels.pcm) { in chn_vpc_proc()
140 CHN_LOCK(c); in chn_vpc_proc()
141 CHN_SETVOLUME(c, SND_VOL_C_PCM, SND_CHN_T_VOL_0DB, db); in chn_vpc_proc()
143 chn_vpc_reset(c, SND_VOL_C_PCM, 1); in chn_vpc_proc()
144 CHN_UNLOCK(c); in chn_vpc_proc()
158 if (err != 0 || req->newptr == NULL) in sysctl_hw_snd_vpc_0db()
180 if (err != 0 || req->newptr == NULL || val == 0) in sysctl_hw_snd_vpc_reset()
194 static int chn_syncdelay = -1;
200 "append (0-1000) millisecond trailing buffer delay on each sync");
221 chn_lockinit(struct pcm_channel *c, int dir) in chn_lockinit() argument
225 c->lock = snd_mtxcreate(c->name, "pcm play channel"); in chn_lockinit()
226 cv_init(&c->intr_cv, "pcmwr"); in chn_lockinit()
229 c->lock = snd_mtxcreate(c->name, "pcm virtual play channel"); in chn_lockinit()
230 cv_init(&c->intr_cv, "pcmwrv"); in chn_lockinit()
233 c->lock = snd_mtxcreate(c->name, "pcm record channel"); in chn_lockinit()
234 cv_init(&c->intr_cv, "pcmrd"); in chn_lockinit()
237 c->lock = snd_mtxcreate(c->name, "pcm virtual record channel"); in chn_lockinit()
238 cv_init(&c->intr_cv, "pcmrdv"); in chn_lockinit()
245 cv_init(&c->cv, "pcmchn"); in chn_lockinit()
249 chn_lockdestroy(struct pcm_channel *c) in chn_lockdestroy() argument
251 CHN_LOCKASSERT(c); in chn_lockdestroy()
253 CHN_BROADCAST(&c->cv); in chn_lockdestroy()
254 CHN_BROADCAST(&c->intr_cv); in chn_lockdestroy()
256 cv_destroy(&c->cv); in chn_lockdestroy()
257 cv_destroy(&c->intr_cv); in chn_lockdestroy()
259 snd_mtxfree(c->lock); in chn_lockdestroy()
269 chn_polltrigger(struct pcm_channel *c) in chn_polltrigger() argument
271 struct snd_dbuf *bs = c->bufsoft; in chn_polltrigger()
274 CHN_LOCKASSERT(c); in chn_polltrigger()
276 if (c->flags & CHN_F_MMAP) { in chn_polltrigger()
277 if (sndbuf_getprevtotal(bs) < c->lw) in chn_polltrigger()
278 delta = c->lw; in chn_polltrigger()
280 delta = sndbuf_gettotal(bs) - sndbuf_getprevtotal(bs); in chn_polltrigger()
282 if (c->direction == PCMDIR_PLAY) in chn_polltrigger()
288 return ((delta < c->lw) ? 0 : 1); in chn_polltrigger()
292 chn_pollreset(struct pcm_channel *c) in chn_pollreset() argument
295 CHN_LOCKASSERT(c); in chn_pollreset()
296 sndbuf_updateprevtotal(c->bufsoft); in chn_pollreset()
300 chn_wakeup(struct pcm_channel *c) in chn_wakeup() argument
305 CHN_LOCKASSERT(c); in chn_wakeup()
307 bs = c->bufsoft; in chn_wakeup()
309 if (CHN_EMPTY(c, children.busy)) { in chn_wakeup()
310 if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c)) in chn_wakeup()
312 CHN_BROADCAST(&c->intr_cv); in chn_wakeup()
314 CHN_FOREACH(ch, c, children.busy) { in chn_wakeup()
323 chn_sleep(struct pcm_channel *c, int timeout) in chn_sleep() argument
327 CHN_LOCKASSERT(c); in chn_sleep()
329 if (c->flags & CHN_F_DEAD) in chn_sleep()
332 ret = cv_timedwait_sig(&c->intr_cv, c->lock, timeout); in chn_sleep()
334 return ((c->flags & CHN_F_DEAD) ? EINVAL : ret); in chn_sleep()
343 chn_dmaupdate(struct pcm_channel *c) in chn_dmaupdate() argument
345 struct snd_dbuf *b = c->bufhard; in chn_dmaupdate()
349 CHN_LOCKASSERT(c); in chn_dmaupdate()
352 hwptr = chn_getptr(c); in chn_dmaupdate()
353 delta = (sndbuf_getsize(b) + hwptr - old) % sndbuf_getsize(b); in chn_dmaupdate()
356 if (c->direction == PCMDIR_PLAY) { in chn_dmaupdate()
358 amt -= amt % sndbuf_getalign(b); in chn_dmaupdate()
363 amt -= amt % sndbuf_getalign(b); in chn_dmaupdate()
367 if (snd_verbose > 3 && CHN_STARTED(c) && delta == 0) { in chn_dmaupdate()
368 device_printf(c->dev, "WARNING: %s DMA completion " in chn_dmaupdate()
371 CHN_DIRSTR(c), hwptr, old, delta, amt, in chn_dmaupdate()
379 chn_wrfeed(struct pcm_channel *c) in chn_wrfeed() argument
381 struct snd_dbuf *b = c->bufhard; in chn_wrfeed()
382 struct snd_dbuf *bs = c->bufsoft; in chn_wrfeed()
385 CHN_LOCKASSERT(c); in chn_wrfeed()
387 if ((c->flags & CHN_F_MMAP) && !(c->flags & CHN_F_CLOSING)) in chn_wrfeed()
392 imax(0, sndbuf_xbytes(sndbuf_getsize(bs), bs, b) - in chn_wrfeed()
396 sndbuf_feed(bs, b, c, c->feeder, amt); in chn_wrfeed()
402 c->xruns++; in chn_wrfeed()
405 chn_wakeup(c); in chn_wrfeed()
410 chn_wrupdate(struct pcm_channel *c)
413 CHN_LOCKASSERT(c);
414 KASSERT(c->direction == PCMDIR_PLAY, ("%s(): bad channel", __func__));
416 if ((c->flags & (CHN_F_MMAP | CHN_F_VIRTUAL)) || CHN_STOPPED(c))
418 chn_dmaupdate(c);
419 chn_wrfeed(c);
421 chn_trigger(c, PCMTRIG_EMLDMAWR);
426 chn_wrintr(struct pcm_channel *c) in chn_wrintr() argument
429 CHN_LOCKASSERT(c); in chn_wrintr()
431 chn_dmaupdate(c); in chn_wrintr()
433 chn_wrfeed(c); in chn_wrintr()
435 chn_trigger(c, PCMTRIG_EMLDMAWR); in chn_wrintr()
439 * user write routine - uiomove data into secondary buffer, trigger if necessary
446 chn_write(struct pcm_channel *c, struct uio *buf) in chn_write() argument
448 struct snd_dbuf *bs = c->bufsoft; in chn_write()
452 CHN_LOCKASSERT(c); in chn_write()
457 while (ret == 0 && buf->uio_resid > 0) { in chn_write()
458 sz = min(buf->uio_resid, sndbuf_getfree(bs)); in chn_write()
463 * unlock-uiomove-lock sequence. in chn_write()
467 t = min(sz, sndbuf_getsize(bs) - p); in chn_write()
469 CHN_UNLOCK(c); in chn_write()
471 CHN_LOCK(c); in chn_write()
472 sz -= t; in chn_write()
476 if (CHN_STOPPED(c) && !(c->flags & CHN_F_NOTRIGGER)) { in chn_write()
477 ret = chn_start(c, 0); in chn_write()
479 c->flags |= CHN_F_DEAD; in chn_write()
481 } else if (c->flags & (CHN_F_NBIO | CHN_F_NOTRIGGER)) { in chn_write()
494 ret = chn_sleep(c, timeout); in chn_write()
497 c->flags |= CHN_F_DEAD; in chn_write()
498 device_printf(c->dev, "%s(): %s: " in chn_write()
500 __func__, c->name); in chn_write()
502 c->flags |= CHN_F_ABORTING; in chn_write()
513 chn_rdfeed(struct pcm_channel *c) in chn_rdfeed() argument
515 struct snd_dbuf *b = c->bufhard; in chn_rdfeed()
516 struct snd_dbuf *bs = c->bufsoft; in chn_rdfeed()
519 CHN_LOCKASSERT(c); in chn_rdfeed()
521 if (c->flags & CHN_F_MMAP) in chn_rdfeed()
526 sndbuf_feed(b, bs, c, c->feeder, amt); in chn_rdfeed()
530 c->xruns++; in chn_rdfeed()
535 chn_wakeup(c); in chn_rdfeed()
540 chn_rdupdate(struct pcm_channel *c)
543 CHN_LOCKASSERT(c);
544 KASSERT(c->direction == PCMDIR_REC, ("chn_rdupdate on bad channel"));
546 if ((c->flags & (CHN_F_MMAP | CHN_F_VIRTUAL)) || CHN_STOPPED(c))
548 chn_trigger(c, PCMTRIG_EMLDMARD);
549 chn_dmaupdate(c);
550 chn_rdfeed(c);
556 chn_rdintr(struct pcm_channel *c) in chn_rdintr() argument
559 CHN_LOCKASSERT(c); in chn_rdintr()
560 /* tell the driver to update the primary buffer if non-dma */ in chn_rdintr()
561 chn_trigger(c, PCMTRIG_EMLDMARD); in chn_rdintr()
563 chn_dmaupdate(c); in chn_rdintr()
565 chn_rdfeed(c); in chn_rdintr()
569 * user read routine - trigger if necessary, uiomove data from secondary buffer
576 chn_read(struct pcm_channel *c, struct uio *buf) in chn_read() argument
578 struct snd_dbuf *bs = c->bufsoft; in chn_read()
582 CHN_LOCKASSERT(c); in chn_read()
584 if (CHN_STOPPED(c) && !(c->flags & CHN_F_NOTRIGGER)) { in chn_read()
585 ret = chn_start(c, 0); in chn_read()
587 c->flags |= CHN_F_DEAD; in chn_read()
595 while (ret == 0 && buf->uio_resid > 0) { in chn_read()
596 sz = min(buf->uio_resid, sndbuf_getready(bs)); in chn_read()
601 * unlock-uiomove-lock sequence. in chn_read()
605 t = min(sz, sndbuf_getsize(bs) - p); in chn_read()
607 CHN_UNLOCK(c); in chn_read()
609 CHN_LOCK(c); in chn_read()
610 sz -= t; in chn_read()
614 } else if (c->flags & (CHN_F_NBIO | CHN_F_NOTRIGGER)) in chn_read()
617 ret = chn_sleep(c, timeout); in chn_read()
620 c->flags |= CHN_F_DEAD; in chn_read()
621 device_printf(c->dev, "%s(): %s: " in chn_read()
623 __func__, c->name); in chn_read()
625 c->flags |= CHN_F_ABORTING; in chn_read()
633 chn_intr_locked(struct pcm_channel *c) in chn_intr_locked() argument
636 CHN_LOCKASSERT(c); in chn_intr_locked()
638 c->interrupts++; in chn_intr_locked()
640 if (c->direction == PCMDIR_PLAY) in chn_intr_locked()
641 chn_wrintr(c); in chn_intr_locked()
643 chn_rdintr(c); in chn_intr_locked()
647 chn_intr(struct pcm_channel *c) in chn_intr() argument
650 if (CHN_LOCKOWNED(c)) { in chn_intr()
651 chn_intr_locked(c); in chn_intr()
655 CHN_LOCK(c); in chn_intr()
656 chn_intr_locked(c); in chn_intr()
657 CHN_UNLOCK(c); in chn_intr()
661 chn_start(struct pcm_channel *c, int force) in chn_start() argument
664 struct snd_dbuf *b = c->bufhard; in chn_start()
665 struct snd_dbuf *bs = c->bufsoft; in chn_start()
668 CHN_LOCKASSERT(c); in chn_start()
670 if (CHN_STARTED(c) || ((c->flags & CHN_F_NOTRIGGER) && !force)) in chn_start()
679 if (c->direction == PCMDIR_REC) { in chn_start()
689 pb = CHN_BUF_PARENT(c, b); in chn_start()
694 if (snd_verbose > 3 && CHN_EMPTY(c, children)) in chn_start()
695 device_printf(c->dev, "%s(): %s (%s) threshold " in chn_start()
696 "i=%d j=%d\n", __func__, CHN_DIRSTR(c), in chn_start()
697 (c->flags & CHN_F_VIRTUAL) ? "virtual" : in chn_start()
702 c->flags |= CHN_F_TRIGGERED; in chn_start()
704 if (c->flags & CHN_F_CLOSING) in chn_start()
705 c->feedcount = 2; in chn_start()
707 c->feedcount = 0; in chn_start()
708 c->interrupts = 0; in chn_start()
709 c->xruns = 0; in chn_start()
711 if (c->parentchannel == NULL) { in chn_start()
712 if (c->direction == PCMDIR_PLAY) in chn_start()
716 device_printf(c->dev, in chn_start()
721 (c->flags & CHN_F_HAS_VCHAN) ? in chn_start()
722 "VCHAN PARENT" : "HW", CHN_DIRSTR(c), in chn_start()
723 (c->flags & CHN_F_CLOSING) ? "closing" : in chn_start()
726 force, i, j, c->timeout, in chn_start()
730 err = chn_trigger(c, PCMTRIG_START); in chn_start()
737 chn_resetbuf(struct pcm_channel *c) in chn_resetbuf() argument
739 struct snd_dbuf *b = c->bufhard; in chn_resetbuf()
740 struct snd_dbuf *bs = c->bufsoft; in chn_resetbuf()
742 c->blocks = 0; in chn_resetbuf()
753 chn_sync(struct pcm_channel *c, int threshold) in chn_sync() argument
759 CHN_LOCKASSERT(c); in chn_sync()
761 if (c->direction != PCMDIR_PLAY) in chn_sync()
764 bs = c->bufsoft; in chn_sync()
766 if ((c->flags & (CHN_F_DEAD | CHN_F_ABORTING)) || in chn_sync()
771 if (CHN_STOPPED(c)) { in chn_sync()
773 ret = chn_start(c, 1); in chn_sync()
780 b = CHN_BUF_PARENT(c, c->bufhard); in chn_sync()
790 * Append (0-1000) millisecond trailing buffer (if needed) in chn_sync()
798 minflush -= minflush % sndbuf_getalign(bs); in chn_sync()
804 minflush -= threshold; in chn_sync()
811 device_printf(c->dev, in chn_sync()
825 device_printf(c->dev, "%s(): [begin] timeout=%d count=%d " in chn_sync()
826 "minflush=%d resid=%d\n", __func__, c->timeout, count, in chn_sync()
829 cflag = c->flags & CHN_F_CLOSING; in chn_sync()
830 c->flags |= CHN_F_CLOSING; in chn_sync()
832 ret = chn_sleep(c, c->timeout); in chn_sync()
834 c->flags |= CHN_F_ABORTING; in chn_sync()
839 --count; in chn_sync()
841 device_printf(c->dev, in chn_sync()
845 __func__, c->timeout, count, in chn_sync()
850 device_printf(c->dev, in chn_sync()
854 __func__, c->timeout, count, in chn_sync()
863 minflush -= threshold; in chn_sync()
869 c->flags &= ~CHN_F_CLOSING; in chn_sync()
870 c->flags |= cflag; in chn_sync()
873 device_printf(c->dev, in chn_sync()
876 __func__, c->timeout, count, hcount, resid, residp, in chn_sync()
884 chn_poll(struct pcm_channel *c, int ev, struct thread *td) in chn_poll() argument
886 struct snd_dbuf *bs = c->bufsoft; in chn_poll()
889 CHN_LOCKASSERT(c); in chn_poll()
891 if (!(c->flags & (CHN_F_MMAP | CHN_F_TRIGGERED))) { in chn_poll()
892 ret = chn_start(c, 1); in chn_poll()
898 if (chn_polltrigger(c)) { in chn_poll()
899 chn_pollreset(c); in chn_poll()
914 chn_abort(struct pcm_channel *c) in chn_abort() argument
917 struct snd_dbuf *b = c->bufhard; in chn_abort()
918 struct snd_dbuf *bs = c->bufsoft; in chn_abort()
920 CHN_LOCKASSERT(c); in chn_abort()
921 if (CHN_STOPPED(c)) in chn_abort()
923 c->flags |= CHN_F_ABORTING; in chn_abort()
925 c->flags &= ~CHN_F_TRIGGERED; in chn_abort()
927 chn_trigger(c, PCMTRIG_ABORT); in chn_abort()
929 if (!(c->flags & CHN_F_VIRTUAL)) in chn_abort()
930 chn_dmaupdate(c); in chn_abort()
933 c->flags &= ~CHN_F_ABORTING; in chn_abort()
949 chn_flush(struct pcm_channel *c) in chn_flush() argument
951 struct snd_dbuf *b = c->bufhard; in chn_flush()
953 CHN_LOCKASSERT(c); in chn_flush()
954 KASSERT(c->direction == PCMDIR_PLAY, ("chn_flush on bad channel")); in chn_flush()
955 DEB(printf("chn_flush: c->flags 0x%08x\n", c->flags)); in chn_flush()
957 c->flags |= CHN_F_CLOSING; in chn_flush()
958 chn_sync(c, 0); in chn_flush()
959 c->flags &= ~CHN_F_TRIGGERED; in chn_flush()
961 chn_trigger(c, PCMTRIG_ABORT); in chn_flush()
964 c->flags &= ~CHN_F_CLOSING; in chn_flush()
1109 afmt_tab[i].name, ch - ext, ext); in snd_afmt2str()
1116 chn_reset(struct pcm_channel *c, uint32_t fmt, uint32_t spd) in chn_reset() argument
1120 CHN_LOCKASSERT(c); in chn_reset()
1121 c->feedcount = 0; in chn_reset()
1122 c->flags &= CHN_F_RESET; in chn_reset()
1123 c->interrupts = 0; in chn_reset()
1124 c->timeout = 1; in chn_reset()
1125 c->xruns = 0; in chn_reset()
1127 c->flags |= (pcm_getflags(c->dev) & SD_F_BITPERFECT) ? in chn_reset()
1130 r = CHANNEL_RESET(c->methods, c->devinfo); in chn_reset()
1132 r = chn_setparam(c, fmt, spd); in chn_reset()
1137 r = chn_setformat(c, fmt); in chn_reset()
1139 r = chn_setspeed(c, spd); in chn_reset()
1141 r = chn_setlatency(c, chn_latency); in chn_reset()
1143 chn_resetbuf(c); in chn_reset()
1144 r = CHANNEL_RESETDONE(c->methods, c->devinfo); in chn_reset()
1154 return (d->p_unr); in chn_getunr()
1156 return (d->vp_unr); in chn_getunr()
1158 return (d->r_unr); in chn_getunr()
1160 return (d->vr_unr); in chn_getunr()
1168 chn_mkname(char *buf, size_t len, struct pcm_channel *c) in chn_mkname() argument
1175 switch (c->type) { in chn_mkname()
1193 device_get_unit(c->dev), str, c->unit); in chn_mkname()
1202 struct pcm_channel *c; in chn_init() local
1221 device_printf(d->dev, in chn_init()
1231 c = malloc(sizeof(*c), M_DEVBUF, M_WAITOK | M_ZERO); in chn_init()
1232 c->methods = kobj_create(cls, M_DEVBUF, M_WAITOK | M_ZERO); in chn_init()
1233 chn_lockinit(c, dir); in chn_init()
1234 CHN_INIT(c, children); in chn_init()
1235 CHN_INIT(c, children.busy); in chn_init()
1236 c->direction = direction; in chn_init()
1237 c->type = dir; in chn_init()
1238 c->unit = alloc_unr(chn_getunr(d, c->type)); in chn_init()
1239 c->format = SND_FORMAT(AFMT_U8, 1, 0); in chn_init()
1240 c->speed = DSP_DEFAULT_SPEED; in chn_init()
1241 c->pid = -1; in chn_init()
1242 c->latency = -1; in chn_init()
1243 c->timeout = 1; in chn_init()
1244 strlcpy(c->comm, CHN_COMM_UNUSED, sizeof(c->comm)); in chn_init()
1245 c->parentsnddev = d; in chn_init()
1246 c->parentchannel = parent; in chn_init()
1247 c->dev = d->dev; in chn_init()
1248 c->trigger = PCMTRIG_STOP; in chn_init()
1249 strlcpy(c->name, chn_mkname(buf, sizeof(buf), c), sizeof(c->name)); in chn_init()
1251 c->matrix = *feeder_matrix_id_map(SND_CHN_MATRIX_1_0); in chn_init()
1252 c->matrix.id = SND_CHN_MATRIX_PCMCHANNEL; in chn_init()
1255 c->volume[SND_VOL_C_MASTER][i] = SND_VOL_0DB_MASTER; in chn_init()
1257 c->volume[SND_VOL_C_MASTER][SND_CHN_T_VOL_0DB] = SND_VOL_0DB_MASTER; in chn_init()
1258 c->volume[SND_VOL_C_PCM][SND_CHN_T_VOL_0DB] = chn_vol_0db_pcm; in chn_init()
1260 CHN_LOCK(c); in chn_init()
1261 chn_vpc_reset(c, SND_VOL_C_PCM, 1); in chn_init()
1262 CHN_UNLOCK(c); in chn_init()
1266 device_printf(d->dev, "%s(): failed to get feeder class\n", in chn_init()
1270 if (feeder_add(c, fc, NULL)) { in chn_init()
1271 device_printf(d->dev, "%s(): failed to add feeder\n", __func__); in chn_init()
1275 b = sndbuf_create(c->dev, c->name, "primary", c); in chn_init()
1276 bs = sndbuf_create(c->dev, c->name, "secondary", c); in chn_init()
1278 device_printf(d->dev, "%s(): failed to create %s buffer\n", in chn_init()
1282 c->bufhard = b; in chn_init()
1283 c->bufsoft = bs; in chn_init()
1285 c->devinfo = CHANNEL_INIT(c->methods, devinfo, b, c, direction); in chn_init()
1286 if (c->devinfo == NULL) { in chn_init()
1287 device_printf(d->dev, "%s(): CHANNEL_INIT() failed\n", __func__); in chn_init()
1291 if ((sndbuf_getsize(b) == 0) && ((c->flags & CHN_F_VIRTUAL) == 0)) { in chn_init()
1292 device_printf(d->dev, "%s(): hardware buffer's size is 0\n", in chn_init()
1297 sndbuf_setfmt(b, c->format); in chn_init()
1298 sndbuf_setspd(b, c->speed); in chn_init()
1299 sndbuf_setfmt(bs, c->format); in chn_init()
1300 sndbuf_setspd(bs, c->speed); in chn_init()
1308 if (c->direction == PCMDIR_PLAY) { in chn_init()
1309 bs->sl = sndbuf_getmaxsize(bs); in chn_init()
1310 bs->shadbuf = malloc(bs->sl, M_DEVBUF, M_WAITOK); in chn_init()
1314 CHN_INSERT_SORT_ASCEND(d, c, channels.pcm); in chn_init()
1316 switch (c->type) { in chn_init()
1318 d->playcount++; in chn_init()
1321 d->pvchancount++; in chn_init()
1324 d->reccount++; in chn_init()
1327 d->rvchancount++; in chn_init()
1333 return (c); in chn_init()
1336 free_unr(chn_getunr(d, c->type), c->unit); in chn_init()
1337 feeder_remove(c); in chn_init()
1338 if (c->devinfo && CHANNEL_FREE(c->methods, c->devinfo)) in chn_init()
1344 CHN_LOCK(c); in chn_init()
1345 chn_lockdestroy(c); in chn_init()
1347 kobj_delete(c->methods, M_DEVBUF); in chn_init()
1348 free(c, M_DEVBUF); in chn_init()
1356 chn_kill(struct pcm_channel *c) in chn_kill() argument
1358 struct snddev_info *d = c->parentsnddev; in chn_kill()
1359 struct snd_dbuf *b = c->bufhard; in chn_kill()
1360 struct snd_dbuf *bs = c->bufsoft; in chn_kill()
1362 PCM_BUSYASSERT(c->parentsnddev); in chn_kill()
1365 CHN_REMOVE(d, c, channels.pcm); in chn_kill()
1367 switch (c->type) { in chn_kill()
1369 d->playcount--; in chn_kill()
1372 d->pvchancount--; in chn_kill()
1375 d->reccount--; in chn_kill()
1378 d->rvchancount--; in chn_kill()
1385 if (CHN_STARTED(c)) { in chn_kill()
1386 CHN_LOCK(c); in chn_kill()
1387 chn_trigger(c, PCMTRIG_ABORT); in chn_kill()
1388 CHN_UNLOCK(c); in chn_kill()
1390 free_unr(chn_getunr(c->parentsnddev, c->type), c->unit); in chn_kill()
1391 feeder_remove(c); in chn_kill()
1392 if (CHANNEL_FREE(c->methods, c->devinfo)) in chn_kill()
1396 CHN_LOCK(c); in chn_kill()
1397 c->flags |= CHN_F_DEAD; in chn_kill()
1398 chn_lockdestroy(c); in chn_kill()
1399 kobj_delete(c->methods, M_DEVBUF); in chn_kill()
1400 free(c, M_DEVBUF); in chn_kill()
1404 chn_shutdown(struct pcm_channel *c) in chn_shutdown() argument
1406 CHN_LOCKASSERT(c); in chn_shutdown()
1408 chn_wakeup(c); in chn_shutdown()
1409 c->flags |= CHN_F_DEAD; in chn_shutdown()
1414 chn_release(struct pcm_channel *c) in chn_release() argument
1416 PCM_BUSYASSERT(c->parentsnddev); in chn_release()
1417 CHN_LOCKASSERT(c); in chn_release()
1419 c->flags &= ~CHN_F_BUSY; in chn_release()
1420 c->pid = -1; in chn_release()
1421 strlcpy(c->comm, CHN_COMM_UNUSED, sizeof(c->comm)); in chn_release()
1422 CHN_UNLOCK(c); in chn_release()
1428 chn_setvolume_multi(struct pcm_channel *c, int vc, int left, int right, in chn_setvolume_multi() argument
1437 ret |= chn_setvolume_matrix(c, vc, i, left); in chn_setvolume_multi()
1439 ret |= chn_setvolume_matrix(c, vc, i, right) << 8; in chn_setvolume_multi()
1441 ret |= chn_setvolume_matrix(c, vc, i, center) << 16; in chn_setvolume_multi()
1448 chn_setvolume_matrix(struct pcm_channel *c, int vc, int vt, int val) in chn_setvolume_matrix() argument
1452 KASSERT(c != NULL && vc >= SND_VOL_C_MASTER && vc < SND_VOL_C_MAX && in chn_setvolume_matrix()
1457 ("%s(): invalid volume matrix c=%p vc=%d vt=%d val=%d", in chn_setvolume_matrix()
1458 __func__, c, vc, vt, val)); in chn_setvolume_matrix()
1459 CHN_LOCKASSERT(c); in chn_setvolume_matrix()
1466 c->volume[vc][vt] = val; in chn_setvolume_matrix()
1475 c->volume[SND_VOL_C_VAL(vc)][vt] = in chn_setvolume_matrix()
1476 SND_VOL_CALC_VAL(c->volume, vc, vt); in chn_setvolume_matrix()
1481 c->volume[SND_VOL_C_VAL(vc)][i] = in chn_setvolume_matrix()
1482 SND_VOL_CALC_VAL(c->volume, vc, i); in chn_setvolume_matrix()
1485 c->volume[SND_VOL_C_VAL(vc)][vt] = in chn_setvolume_matrix()
1486 SND_VOL_CALC_VAL(c->volume, vc, vt); in chn_setvolume_matrix()
1493 chn_getvolume_matrix(struct pcm_channel *c, int vc, int vt) in chn_getvolume_matrix() argument
1495 KASSERT(c != NULL && vc >= SND_VOL_C_MASTER && vc < SND_VOL_C_MAX && in chn_getvolume_matrix()
1498 ("%s(): invalid volume matrix c=%p vc=%d vt=%d", in chn_getvolume_matrix()
1499 __func__, c, vc, vt)); in chn_getvolume_matrix()
1500 CHN_LOCKASSERT(c); in chn_getvolume_matrix()
1502 return (c->volume[vc][vt]); in chn_getvolume_matrix()
1506 chn_setmute_multi(struct pcm_channel *c, int vc, int mute) in chn_setmute_multi() argument
1514 ret |= chn_setmute_matrix(c, vc, i, mute); in chn_setmute_multi()
1516 ret |= chn_setmute_matrix(c, vc, i, mute) << 8; in chn_setmute_multi()
1518 ret |= chn_setmute_matrix(c, vc, i, mute) << 16; in chn_setmute_multi()
1524 chn_setmute_matrix(struct pcm_channel *c, int vc, int vt, int mute) in chn_setmute_matrix() argument
1528 KASSERT(c != NULL && vc >= SND_VOL_C_MASTER && vc < SND_VOL_C_MAX && in chn_setmute_matrix()
1531 ("%s(): invalid mute matrix c=%p vc=%d vt=%d mute=%d", in chn_setmute_matrix()
1532 __func__, c, vc, vt, mute)); in chn_setmute_matrix()
1534 CHN_LOCKASSERT(c); in chn_setmute_matrix()
1538 c->muted[vc][vt] = mute; in chn_setmute_matrix()
1547 c->muted[SND_VOL_C_VAL(vc)][vt] = mute; in chn_setmute_matrix()
1552 c->muted[SND_VOL_C_VAL(vc)][i] = mute; in chn_setmute_matrix()
1555 c->muted[SND_VOL_C_VAL(vc)][vt] = mute; in chn_setmute_matrix()
1562 chn_getmute_matrix(struct pcm_channel *c, int vc, int vt) in chn_getmute_matrix() argument
1564 KASSERT(c != NULL && vc >= SND_VOL_C_MASTER && vc < SND_VOL_C_MAX && in chn_getmute_matrix()
1567 ("%s(): invalid mute matrix c=%p vc=%d vt=%d", in chn_getmute_matrix()
1568 __func__, c, vc, vt)); in chn_getmute_matrix()
1569 CHN_LOCKASSERT(c); in chn_getmute_matrix()
1571 return (c->muted[vc][vt]); in chn_getmute_matrix()
1575 chn_getmatrix(struct pcm_channel *c) in chn_getmatrix() argument
1578 KASSERT(c != NULL, ("%s(): NULL channel", __func__)); in chn_getmatrix()
1579 CHN_LOCKASSERT(c); in chn_getmatrix()
1581 if (!(c->format & AFMT_CONVERTIBLE)) in chn_getmatrix()
1584 return (&c->matrix); in chn_getmatrix()
1588 chn_setmatrix(struct pcm_channel *c, struct pcmchan_matrix *m) in chn_setmatrix() argument
1591 KASSERT(c != NULL && m != NULL, in chn_setmatrix()
1593 CHN_LOCKASSERT(c); in chn_setmatrix()
1595 if (!(c->format & AFMT_CONVERTIBLE)) in chn_setmatrix()
1598 c->matrix = *m; in chn_setmatrix()
1599 c->matrix.id = SND_CHN_MATRIX_PCMCHANNEL; in chn_setmatrix()
1601 return (chn_setformat(c, SND_FORMAT(c->format, m->channels, m->ext))); in chn_setmatrix()
1608 chn_oss_getorder(struct pcm_channel *c, unsigned long long *map) in chn_oss_getorder() argument
1611 KASSERT(c != NULL && map != NULL, in chn_oss_getorder()
1613 CHN_LOCKASSERT(c); in chn_oss_getorder()
1615 if (!(c->format & AFMT_CONVERTIBLE)) in chn_oss_getorder()
1618 return (feeder_matrix_oss_get_channel_order(&c->matrix, map)); in chn_oss_getorder()
1622 chn_oss_setorder(struct pcm_channel *c, unsigned long long *map) in chn_oss_setorder() argument
1627 KASSERT(c != NULL && map != NULL, in chn_oss_setorder()
1629 CHN_LOCKASSERT(c); in chn_oss_setorder()
1631 if (!(c->format & AFMT_CONVERTIBLE)) in chn_oss_setorder()
1634 m = c->matrix; in chn_oss_setorder()
1639 return (chn_setmatrix(c, &m)); in chn_oss_setorder()
1648 chn_oss_getmask(struct pcm_channel *c, uint32_t *retmask) in chn_oss_getmask() argument
1654 KASSERT(c != NULL && retmask != NULL, in chn_oss_getmask()
1656 CHN_LOCKASSERT(c); in chn_oss_getmask()
1658 caps = chn_getcaps(c); in chn_oss_getmask()
1659 if (caps == NULL || caps->fmtlist == NULL) in chn_oss_getmask()
1662 for (i = 0; caps->fmtlist[i] != 0; i++) { in chn_oss_getmask()
1663 format = caps->fmtlist[i]; in chn_oss_getmask()
1668 m = CHANNEL_GETMATRIX(c->methods, c->devinfo, format); in chn_oss_getmask()
1671 if (m->mask & SND_CHN_OSS_FRONT) in chn_oss_getmask()
1673 if (m->mask & SND_CHN_OSS_SURR) in chn_oss_getmask()
1675 if (m->mask & SND_CHN_OSS_CENTER_LFE) in chn_oss_getmask()
1677 if (m->mask & SND_CHN_OSS_REAR) in chn_oss_getmask()
1681 /* report software-supported binding mask */ in chn_oss_getmask()
1682 if (!CHN_BITPERFECT(c) && report_soft_matrix) in chn_oss_getmask()
1690 chn_vpc_reset(struct pcm_channel *c, int vc, int force) in chn_vpc_reset() argument
1694 KASSERT(c != NULL && vc >= SND_VOL_C_BEGIN && vc <= SND_VOL_C_END, in chn_vpc_reset()
1695 ("%s(): invalid reset c=%p vc=%d", __func__, c, vc)); in chn_vpc_reset()
1696 CHN_LOCKASSERT(c); in chn_vpc_reset()
1702 CHN_SETVOLUME(c, vc, i, c->volume[vc][SND_CHN_T_VOL_0DB]); in chn_vpc_reset()
1715 ret = 1 << (ret - 1); in round_pow2()
1734 tmp = ret - (ret % round); in round_blksz()
1737 tmp = ret - (ret % round); in round_blksz()
1750 * +---------+------------+-----------+------------+
1752 * +---------+------------+-----------+------------+
1754 * +---------+------------+-----------+------------+
1756 * +---------+------------+-----------+------------+
1758 * +---------+------------+-----------+------------+
1760 * +---------+------------+-----------+------------+
1762 * +---------+------------+-----------+------------+
1764 * +---------+------------+-----------+------------+
1766 * +---------+------------+-----------+------------+
1768 * +---------+------------+-----------+------------+
1770 * +---------+------------+-----------+------------+
1772 * +---------+------------+-----------+------------+
1774 * +---------+------------+-----------+------------+
1781 * +---------+------------+-----------+------------+
1783 * +---------+------------+-----------+------------+
1785 * +---------+------------+-----------+------------+
1787 * +---------+------------+-----------+------------+
1789 * +---------+------------+-----------+------------+
1791 * +---------+------------+-----------+------------+
1793 * +---------+------------+-----------+------------+
1795 * +---------+------------+-----------+------------+
1797 * +---------+------------+-----------+------------+
1799 * +---------+------------+-----------+------------+
1801 * +---------+------------+-----------+------------+
1803 * +---------+------------+-----------+------------+
1805 * +---------+------------+-----------+------------+
1884 chn_resizebuf(struct pcm_channel *c, int latency, in chn_resizebuf() argument
1891 CHN_LOCKASSERT(c); in chn_resizebuf()
1893 if ((c->flags & (CHN_F_MMAP | CHN_F_TRIGGERED)) || in chn_resizebuf()
1894 !(c->direction == PCMDIR_PLAY || c->direction == PCMDIR_REC)) in chn_resizebuf()
1897 if (latency == -1) { in chn_resizebuf()
1898 c->latency = -1; in chn_resizebuf()
1900 } else if (latency == -2) { in chn_resizebuf()
1901 latency = c->latency; in chn_resizebuf()
1907 c->latency = latency; in chn_resizebuf()
1910 bs = c->bufsoft; in chn_resizebuf()
1911 b = c->bufhard; in chn_resizebuf()
1913 if (!(blksz == 0 || blkcnt == -1) && in chn_resizebuf()
1918 chn_calclatency(c->direction, latency, sndbuf_getalign(bs), in chn_resizebuf()
1922 if (blksz == 0 || blkcnt == -1) { in chn_resizebuf()
1923 if (blkcnt == -1) in chn_resizebuf()
1924 c->flags &= ~CHN_F_HAS_SIZE; in chn_resizebuf()
1925 if (c->flags & CHN_F_HAS_SIZE) { in chn_resizebuf()
1930 c->flags |= CHN_F_HAS_SIZE; in chn_resizebuf()
1932 if (c->flags & CHN_F_HAS_SIZE) { in chn_resizebuf()
1944 if (c->parentchannel != NULL) { in chn_resizebuf()
1945 pb = c->parentchannel->bufsoft; in chn_resizebuf()
1946 CHN_UNLOCK(c); in chn_resizebuf()
1947 CHN_LOCK(c->parentchannel); in chn_resizebuf()
1948 chn_notify(c->parentchannel, CHN_N_BLOCKSIZE); in chn_resizebuf()
1949 CHN_UNLOCK(c->parentchannel); in chn_resizebuf()
1950 CHN_LOCK(c); in chn_resizebuf()
1951 if (c->direction == PCMDIR_PLAY) { in chn_resizebuf()
1960 if (c->flags & CHN_F_HAS_SIZE) { in chn_resizebuf()
1965 chn_calclatency(c->direction, latency, in chn_resizebuf()
1981 hblksz -= hblksz % sndbuf_getalign(b); in chn_resizebuf()
1985 hblksz -= hblksz % sndbuf_getalign(b); in chn_resizebuf()
1989 CHN_UNLOCK(c); in chn_resizebuf()
1991 CHANNEL_SETFRAGMENTS(c->methods, c->devinfo, in chn_resizebuf()
1993 sndbuf_setblksz(b, CHANNEL_SETBLOCKSIZE(c->methods, in chn_resizebuf()
1994 c->devinfo, hblksz)); in chn_resizebuf()
1995 CHN_LOCK(c); in chn_resizebuf()
1997 if (!CHN_EMPTY(c, children)) { in chn_resizebuf()
2002 if (c->direction == PCMDIR_PLAY) { in chn_resizebuf()
2004 nsblkcnt--; in chn_resizebuf()
2037 sblksz -= sblksz % sndbuf_getalign(bs); in chn_resizebuf()
2043 device_printf(c->dev, "%s(): Failed: %d %d\n", in chn_resizebuf()
2052 c->timeout = ((u_int64_t)hz * sndbuf_getsize(bs)) / in chn_resizebuf()
2054 if (c->parentchannel != NULL) in chn_resizebuf()
2055 c->timeout = min(c->timeout, c->parentchannel->timeout); in chn_resizebuf()
2056 if (c->timeout < 1) in chn_resizebuf()
2057 c->timeout = 1; in chn_resizebuf()
2063 c->lw = sndbuf_getblksz(bs); in chn_resizebuf()
2064 chn_resetbuf(c); in chn_resizebuf()
2067 device_printf(c->dev, "%s(): %s (%s) timeout=%u " in chn_resizebuf()
2069 __func__, CHN_DIRSTR(c), in chn_resizebuf()
2070 (c->flags & CHN_F_VIRTUAL) ? "virtual" : "hardware", in chn_resizebuf()
2071 c->timeout, in chn_resizebuf()
2081 chn_setlatency(struct pcm_channel *c, int latency) in chn_setlatency() argument
2083 CHN_LOCKASSERT(c); in chn_setlatency()
2085 return chn_resizebuf(c, latency, -1, 0); in chn_setlatency()
2089 chn_setblocksize(struct pcm_channel *c, int blkcnt, int blksz) in chn_setblocksize() argument
2091 CHN_LOCKASSERT(c); in chn_setblocksize()
2093 return chn_resizebuf(c, -1, blkcnt, blksz); in chn_setblocksize()
2097 chn_setparam(struct pcm_channel *c, uint32_t format, uint32_t speed) in chn_setparam() argument
2103 CHN_LOCKASSERT(c); in chn_setparam()
2105 if (speed < 1 || format == 0 || CHN_STARTED(c)) in chn_setparam()
2108 c->format = format; in chn_setparam()
2109 c->speed = speed; in chn_setparam()
2111 caps = chn_getcaps(c); in chn_setparam()
2114 RANGE(hwspeed, caps->minspeed, caps->maxspeed); in chn_setparam()
2116 sndbuf_setspd(c->bufhard, CHANNEL_SETSPEED(c->methods, c->devinfo, in chn_setparam()
2118 hwspeed = sndbuf_getspd(c->bufhard); in chn_setparam()
2120 delta = (hwspeed > speed) ? (hwspeed - speed) : (speed - hwspeed); in chn_setparam()
2123 c->speed = hwspeed; in chn_setparam()
2125 ret = feeder_chain(c); in chn_setparam()
2128 ret = CHANNEL_SETFORMAT(c->methods, c->devinfo, in chn_setparam()
2129 sndbuf_getfmt(c->bufhard)); in chn_setparam()
2132 ret = chn_resizebuf(c, -2, 0, 0); in chn_setparam()
2138 chn_setspeed(struct pcm_channel *c, uint32_t speed) in chn_setspeed() argument
2145 if (c->format & AFMT_PASSTHROUGH) in chn_setspeed()
2149 oldformat = c->format; in chn_setspeed()
2150 oldspeed = c->speed; in chn_setspeed()
2153 ret = chn_setparam(c, format, speed); in chn_setspeed()
2156 device_printf(c->dev, in chn_setspeed()
2160 chn_setparam(c, c->format, oldspeed); in chn_setspeed()
2167 chn_setformat(struct pcm_channel *c, uint32_t format) in chn_setformat() argument
2178 oldformat = c->format; in chn_setformat()
2179 oldspeed = c->speed; in chn_setformat()
2182 ret = chn_setparam(c, format, speed); in chn_setformat()
2185 device_printf(c->dev, in chn_setformat()
2189 chn_setparam(c, oldformat, oldspeed); in chn_setformat()
2196 chn_syncstate(struct pcm_channel *c) in chn_syncstate() argument
2201 d = (c != NULL) ? c->parentsnddev : NULL; in chn_syncstate()
2202 m = (d != NULL && d->mixer_dev != NULL) ? d->mixer_dev->si_drv1 : in chn_syncstate()
2208 CHN_LOCKASSERT(c); in chn_syncstate()
2210 if (c->feederflags & (1 << FEEDER_VOLUME)) { in chn_syncstate()
2214 if (c->direction == PCMDIR_PLAY && in chn_syncstate()
2215 (d->flags & SD_F_SOFTPCMVOL)) { in chn_syncstate()
2216 /* CHN_UNLOCK(c); */ in chn_syncstate()
2223 /* CHN_LOCK(c); */ in chn_syncstate()
2229 if (vol == -1) { in chn_syncstate()
2230 device_printf(c->dev, in chn_syncstate()
2236 if (pvol == -1) { in chn_syncstate()
2237 device_printf(c->dev, in chn_syncstate()
2247 chn_setvolume_multi(c, SND_VOL_C_MASTER, left, right, center); in chn_syncstate()
2250 if (c->feederflags & (1 << FEEDER_EQ)) { in chn_syncstate()
2254 /* CHN_UNLOCK(c); */ in chn_syncstate()
2257 /* CHN_LOCK(c); */ in chn_syncstate()
2259 if (treble == -1) in chn_syncstate()
2265 if (bass == -1) in chn_syncstate()
2270 f = feeder_find(c, FEEDER_EQ); in chn_syncstate()
2273 device_printf(c->dev, in chn_syncstate()
2274 "EQ: Failed to set treble -- %d\n", in chn_syncstate()
2277 device_printf(c->dev, in chn_syncstate()
2278 "EQ: Failed to set bass -- %d\n", in chn_syncstate()
2280 if (FEEDER_SET(f, FEEDEQ_PREAMP, d->eqpreamp) != 0) in chn_syncstate()
2281 device_printf(c->dev, in chn_syncstate()
2282 "EQ: Failed to set preamp -- %d\n", in chn_syncstate()
2283 d->eqpreamp); in chn_syncstate()
2284 if (d->flags & SD_F_EQ_BYPASSED) in chn_syncstate()
2286 else if (d->flags & SD_F_EQ_ENABLED) in chn_syncstate()
2291 device_printf(c->dev, in chn_syncstate()
2292 "EQ: Failed to set state -- %d\n", state); in chn_syncstate()
2298 chn_trigger(struct pcm_channel *c, int go) in chn_trigger() argument
2300 struct snddev_info *d = c->parentsnddev; in chn_trigger()
2303 CHN_LOCKASSERT(c); in chn_trigger()
2305 return (CHANNEL_TRIGGER(c->methods, c->devinfo, go)); in chn_trigger()
2307 if (go == c->trigger) in chn_trigger()
2311 device_printf(c->dev, "%s() %s: calling go=0x%08x , " in chn_trigger()
2312 "prev=0x%08x\n", __func__, c->name, go, c->trigger); in chn_trigger()
2315 c->trigger = go; in chn_trigger()
2316 ret = CHANNEL_TRIGGER(c->methods, c->devinfo, go); in chn_trigger()
2320 CHN_UNLOCK(c); in chn_trigger()
2322 CHN_LOCK(c); in chn_trigger()
2328 if (go != c->trigger) { in chn_trigger()
2339 CHN_INSERT_HEAD_SAFE(d, c, channels.pcm.busy); in chn_trigger()
2341 chn_syncstate(c); in chn_trigger()
2345 CHN_REMOVE_SAFE(d, c, channels.pcm.busy); in chn_trigger()
2357 * @brief Queries sound driver for sample-aligned hardware buffer pointer index
2360 * the current bytes-per-sample value before returning. (E.g., a channel
2362 * hwptr value ranging from 32-35 would be returned as 32.)
2364 * @param c PCM channel context
2365 * @returns sample-aligned hardware buffer pointer index
2368 chn_getptr(struct pcm_channel *c) in chn_getptr() argument
2372 CHN_LOCKASSERT(c); in chn_getptr()
2373 hwptr = (CHN_STARTED(c)) ? CHANNEL_GETPTR(c->methods, c->devinfo) : 0; in chn_getptr()
2374 return (hwptr - (hwptr % sndbuf_getalign(c->bufhard))); in chn_getptr()
2378 chn_getcaps(struct pcm_channel *c) in chn_getcaps() argument
2380 CHN_LOCKASSERT(c); in chn_getcaps()
2381 return CHANNEL_GETCAPS(c->methods, c->devinfo); in chn_getcaps()
2385 chn_getformats(struct pcm_channel *c) in chn_getformats() argument
2390 fmtlist = chn_getcaps(c)->fmtlist; in chn_getformats()
2395 /* report software-supported formats */ in chn_getformats()
2396 if (!CHN_BITPERFECT(c) && report_soft_formats) in chn_getformats()
2403 chn_notify(struct pcm_channel *c, u_int32_t flags) in chn_notify() argument
2411 CHN_LOCKASSERT(c); in chn_notify()
2413 if (CHN_EMPTY(c, children)) in chn_notify()
2422 run = (CHN_STARTED(c)) ? 1 : 0; in chn_notify()
2454 chn_setlatency(c, chn_latency); in chn_notify()
2457 if ((flags & CHN_N_TRIGGER) && !(c->flags & CHN_F_VCHAN_DYNAMIC)) { in chn_notify()
2458 nrun = CHN_EMPTY(c, children.busy) ? 0 : 1; in chn_notify()
2460 err = chn_start(c, 1); in chn_notify()
2462 chn_abort(c); in chn_notify()
2467 if (c->direction == PCMDIR_PLAY) { in chn_notify()
2468 vchanformat = &c->parentsnddev->pvchanformat; in chn_notify()
2469 vchanrate = &c->parentsnddev->pvchanrate; in chn_notify()
2471 vchanformat = &c->parentsnddev->rvchanformat; in chn_notify()
2472 vchanrate = &c->parentsnddev->rvchanrate; in chn_notify()
2476 if (!(c->flags & CHN_F_VCHAN_ADAPTIVE)) { in chn_notify()
2486 caps = chn_getcaps(c); in chn_notify()
2490 CHN_FOREACH(ch, c, children.busy) { in chn_notify()
2492 if ((ch->format & AFMT_PASSTHROUGH) && in chn_notify()
2493 snd_fmtvalid(ch->format, caps->fmtlist)) { in chn_notify()
2494 bestformat = ch->format; in chn_notify()
2495 bestspeed = ch->speed; in chn_notify()
2501 if ((ch->flags & CHN_F_EXCLUSIVE) && vpflags == 0) { in chn_notify()
2502 if (c->flags & CHN_F_VCHAN_ADAPTIVE) { in chn_notify()
2503 bestspeed = ch->speed; in chn_notify()
2504 RANGE(bestspeed, caps->minspeed, in chn_notify()
2505 caps->maxspeed); in chn_notify()
2506 besthwformat = snd_fmtbest(ch->format, in chn_notify()
2507 caps->fmtlist); in chn_notify()
2516 if (!(c->flags & CHN_F_VCHAN_ADAPTIVE) || in chn_notify()
2522 if (ch->speed > bestspeed) { in chn_notify()
2523 bestspeed = ch->speed; in chn_notify()
2524 RANGE(bestspeed, caps->minspeed, in chn_notify()
2525 caps->maxspeed); in chn_notify()
2527 besthwformat = snd_fmtbest(ch->format, caps->fmtlist); in chn_notify()
2545 bestformat = c->format; in chn_notify()
2547 bestspeed = c->speed; in chn_notify()
2549 if (bestformat != c->format || bestspeed != c->speed) in chn_notify()
2552 c->flags &= ~(CHN_F_PASSTHROUGH | CHN_F_EXCLUSIVE); in chn_notify()
2553 c->flags |= vpflags; in chn_notify()
2557 bestspeed = CHANNEL_SETSPEED(c->methods, in chn_notify()
2558 c->devinfo, bestspeed); in chn_notify()
2559 err = chn_reset(c, bestformat, bestspeed); in chn_notify()
2562 CHN_FOREACH(ch, c, children.busy) { in chn_notify()
2571 c->flags |= CHN_F_DIRTY; in chn_notify()
2572 err = chn_start(c, 1); in chn_notify()
2577 chn_abort(c); in chn_notify()
2578 bestspeed = CHANNEL_SETSPEED(c->methods, c->devinfo, in chn_notify()
2580 err = chn_reset(c, bestformat, bestspeed); in chn_notify()
2582 CHN_FOREACH(ch, c, children.busy) { in chn_notify()
2590 c->flags |= CHN_F_DIRTY; in chn_notify()
2591 err = chn_start(c, 1); in chn_notify()
2602 c->flags &= ~(CHN_F_PASSTHROUGH | CHN_F_EXCLUSIVE); in chn_notify()
2605 chn_abort(c); in chn_notify()
2606 if (c->format != bestformat || c->speed != bestspeed) in chn_notify()
2607 chn_reset(c, bestformat, bestspeed); in chn_notify()
2622 * should examine rates @b only if this function returns non-zero.
2624 * @param c pcm channel to examine
2627 * @return number of rates in the array pointed to be @c rates
2630 chn_getrates(struct pcm_channel *c, int **rates) in chn_getrates() argument
2633 CHN_LOCKASSERT(c); in chn_getrates()
2634 return CHANNEL_GETRATES(c->methods, c->devinfo, rates); in chn_getrates()
2641 * - Starting a syncgroup (@c SNDCTL_DSP_SYNCSTART ioctl)
2642 * - Closing a device. (A channel can't be destroyed if it's still in use.)
2646 * whether @c c is locked or not.)
2648 * @param c channel device to be started or closed
2655 chn_syncdestroy(struct pcm_channel *c) in chn_syncdestroy() argument
2665 if (c->sm != NULL) { in chn_syncdestroy()
2666 sm = c->sm; in chn_syncdestroy()
2667 sg = sm->parent; in chn_syncdestroy()
2668 c->sm = NULL; in chn_syncdestroy()
2672 SLIST_REMOVE(&sg->members, sm, pcmchan_syncmember, link); in chn_syncdestroy()
2675 if (SLIST_EMPTY(&sg->members)) { in chn_syncdestroy()
2677 sg_id = sg->id; in chn_syncdestroy()
2687 chn_getpeaks(struct pcm_channel *c, int *lpeak, int *rpeak) in chn_getpeaks() argument
2689 CHN_LOCKASSERT(c); in chn_getpeaks()
2690 return CHANNEL_GETPEAKS(c->methods, c->devinfo, lpeak, rpeak); in chn_getpeaks()