Lines Matching defs:c
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
128 struct pcm_channel *c;
139 CHN_FOREACH(c, d, channels.pcm) {
140 CHN_LOCK(c);
141 CHN_SETVOLUME(c, SND_VOL_C_PCM, SND_CHN_T_VOL_0DB, db);
143 chn_vpc_reset(c, SND_VOL_C_PCM, 1);
144 CHN_UNLOCK(c);
221 chn_lockinit(struct pcm_channel *c, int dir)
225 c->lock = snd_mtxcreate(c->name, "pcm play channel");
226 cv_init(&c->intr_cv, "pcmwr");
229 c->lock = snd_mtxcreate(c->name, "pcm virtual play channel");
230 cv_init(&c->intr_cv, "pcmwrv");
233 c->lock = snd_mtxcreate(c->name, "pcm record channel");
234 cv_init(&c->intr_cv, "pcmrd");
237 c->lock = snd_mtxcreate(c->name, "pcm virtual record channel");
238 cv_init(&c->intr_cv, "pcmrdv");
245 cv_init(&c->cv, "pcmchn");
249 chn_lockdestroy(struct pcm_channel *c)
251 CHN_LOCKASSERT(c);
253 CHN_BROADCAST(&c->cv);
254 CHN_BROADCAST(&c->intr_cv);
256 cv_destroy(&c->cv);
257 cv_destroy(&c->intr_cv);
259 snd_mtxfree(c->lock);
269 chn_polltrigger(struct pcm_channel *c)
271 struct snd_dbuf *bs = c->bufsoft;
274 CHN_LOCKASSERT(c);
276 if (c->flags & CHN_F_MMAP) {
277 if (sndbuf_getprevtotal(bs) < c->lw)
278 delta = c->lw;
282 if (c->direction == PCMDIR_PLAY)
288 return ((delta < c->lw) ? 0 : 1);
292 chn_pollreset(struct pcm_channel *c)
295 CHN_LOCKASSERT(c);
296 sndbuf_updateprevtotal(c->bufsoft);
300 chn_wakeup(struct pcm_channel *c)
305 CHN_LOCKASSERT(c);
307 bs = c->bufsoft;
309 if (CHN_EMPTY(c, children.busy)) {
310 if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c))
312 CHN_BROADCAST(&c->intr_cv);
314 CHN_FOREACH(ch, c, children.busy) {
323 chn_sleep(struct pcm_channel *c, int timeout)
327 CHN_LOCKASSERT(c);
329 if (c->flags & CHN_F_DEAD)
332 c->sleeping++;
333 ret = cv_timedwait_sig(&c->intr_cv, c->lock, timeout);
334 c->sleeping--;
336 return ((c->flags & CHN_F_DEAD) ? EINVAL : ret);
345 chn_dmaupdate(struct pcm_channel *c)
347 struct snd_dbuf *b = c->bufhard;
351 CHN_LOCKASSERT(c);
354 hwptr = chn_getptr(c);
358 if (c->direction == PCMDIR_PLAY) {
369 if (snd_verbose > 3 && CHN_STARTED(c) && delta == 0) {
370 device_printf(c->dev, "WARNING: %s DMA completion "
373 CHN_DIRSTR(c), hwptr, old, delta, amt,
381 chn_wrfeed(struct pcm_channel *c)
383 struct snd_dbuf *b = c->bufhard;
384 struct snd_dbuf *bs = c->bufsoft;
387 CHN_LOCKASSERT(c);
389 if ((c->flags & CHN_F_MMAP) && !(c->flags & CHN_F_CLOSING))
398 sndbuf_feed(bs, b, c, c->feeder, amt);
404 c->xruns++;
407 chn_wakeup(c);
411 chn_wrintr(struct pcm_channel *c)
414 CHN_LOCKASSERT(c);
416 chn_dmaupdate(c);
418 chn_wrfeed(c);
420 chn_trigger(c, PCMTRIG_EMLDMAWR);
431 chn_write(struct pcm_channel *c, struct uio *buf)
433 struct snd_dbuf *bs = c->bufsoft;
437 CHN_LOCKASSERT(c);
454 CHN_UNLOCK(c);
456 CHN_LOCK(c);
461 if (CHN_STOPPED(c) && !(c->flags & CHN_F_NOTRIGGER)) {
462 ret = chn_start(c, 0);
464 c->flags |= CHN_F_DEAD;
466 } else if (c->flags & (CHN_F_NBIO | CHN_F_NOTRIGGER)) {
479 ret = chn_sleep(c, timeout);
482 c->flags |= CHN_F_DEAD;
483 device_printf(c->dev, "%s(): %s: "
485 __func__, c->name);
487 c->flags |= CHN_F_ABORTING;
498 chn_rdfeed(struct pcm_channel *c)
500 struct snd_dbuf *b = c->bufhard;
501 struct snd_dbuf *bs = c->bufsoft;
504 CHN_LOCKASSERT(c);
506 if (c->flags & CHN_F_MMAP)
511 sndbuf_feed(b, bs, c, c->feeder, amt);
515 c->xruns++;
520 chn_wakeup(c);
525 chn_rdintr(struct pcm_channel *c)
528 CHN_LOCKASSERT(c);
530 chn_trigger(c, PCMTRIG_EMLDMARD);
532 chn_dmaupdate(c);
534 chn_rdfeed(c);
545 chn_read(struct pcm_channel *c, struct uio *buf)
547 struct snd_dbuf *bs = c->bufsoft;
551 CHN_LOCKASSERT(c);
553 if (CHN_STOPPED(c) && !(c->flags & CHN_F_NOTRIGGER)) {
554 ret = chn_start(c, 0);
556 c->flags |= CHN_F_DEAD;
576 CHN_UNLOCK(c);
578 CHN_LOCK(c);
583 } else if (c->flags & (CHN_F_NBIO | CHN_F_NOTRIGGER))
586 ret = chn_sleep(c, timeout);
589 c->flags |= CHN_F_DEAD;
590 device_printf(c->dev, "%s(): %s: "
592 __func__, c->name);
594 c->flags |= CHN_F_ABORTING;
602 chn_intr_locked(struct pcm_channel *c)
605 CHN_LOCKASSERT(c);
607 c->interrupts++;
609 if (c->direction == PCMDIR_PLAY)
610 chn_wrintr(c);
612 chn_rdintr(c);
616 chn_intr(struct pcm_channel *c)
619 if (CHN_LOCKOWNED(c)) {
620 chn_intr_locked(c);
624 CHN_LOCK(c);
625 chn_intr_locked(c);
626 CHN_UNLOCK(c);
630 chn_start(struct pcm_channel *c, int force)
633 struct snd_dbuf *b = c->bufhard;
634 struct snd_dbuf *bs = c->bufsoft;
637 CHN_LOCKASSERT(c);
639 if (CHN_STARTED(c) || ((c->flags & CHN_F_NOTRIGGER) && !force))
648 if (c->direction == PCMDIR_REC) {
658 pb = CHN_BUF_PARENT(c, b);
663 if (snd_verbose > 3 && CHN_EMPTY(c, children))
664 device_printf(c->dev, "%s(): %s (%s) threshold "
665 "i=%d j=%d\n", __func__, CHN_DIRSTR(c),
666 (c->flags & CHN_F_VIRTUAL) ? "virtual" :
671 c->flags |= CHN_F_TRIGGERED;
673 if (c->flags & CHN_F_CLOSING)
674 c->feedcount = 2;
676 c->feedcount = 0;
677 c->interrupts = 0;
678 c->xruns = 0;
680 if (c->parentchannel == NULL) {
681 if (c->direction == PCMDIR_PLAY)
685 device_printf(c->dev,
690 (c->flags & CHN_F_HAS_VCHAN) ?
691 "VCHAN PARENT" : "HW", CHN_DIRSTR(c),
692 (c->flags & CHN_F_CLOSING) ? "closing" :
695 force, i, j, c->timeout,
699 err = chn_trigger(c, PCMTRIG_START);
706 chn_resetbuf(struct pcm_channel *c)
708 struct snd_dbuf *b = c->bufhard;
709 struct snd_dbuf *bs = c->bufsoft;
711 c->blocks = 0;
722 chn_sync(struct pcm_channel *c, int threshold)
728 CHN_LOCKASSERT(c);
730 if (c->direction != PCMDIR_PLAY)
733 bs = c->bufsoft;
735 if ((c->flags & (CHN_F_DEAD | CHN_F_ABORTING)) ||
740 if (CHN_STOPPED(c)) {
742 ret = chn_start(c, 1);
749 b = CHN_BUF_PARENT(c, c->bufhard);
780 device_printf(c->dev,
794 device_printf(c->dev, "%s(): [begin] timeout=%d count=%d "
795 "minflush=%d resid=%d\n", __func__, c->timeout, count,
798 cflag = c->flags & CHN_F_CLOSING;
799 c->flags |= CHN_F_CLOSING;
801 ret = chn_sleep(c, c->timeout);
803 c->flags |= CHN_F_ABORTING;
810 device_printf(c->dev,
814 __func__, c->timeout, count,
819 device_printf(c->dev,
823 __func__, c->timeout, count,
838 c->flags &= ~CHN_F_CLOSING;
839 c->flags |= cflag;
842 device_printf(c->dev,
845 __func__, c->timeout, count, hcount, resid, residp,
853 chn_poll(struct pcm_channel *c, int ev, struct thread *td)
855 struct snd_dbuf *bs = c->bufsoft;
858 CHN_LOCKASSERT(c);
860 if (!(c->flags & (CHN_F_MMAP | CHN_F_TRIGGERED))) {
861 ret = chn_start(c, 1);
867 if (chn_polltrigger(c)) {
868 chn_pollreset(c);
883 chn_abort(struct pcm_channel *c)
886 struct snd_dbuf *b = c->bufhard;
887 struct snd_dbuf *bs = c->bufsoft;
889 CHN_LOCKASSERT(c);
890 if (CHN_STOPPED(c))
892 c->flags |= CHN_F_ABORTING;
894 c->flags &= ~CHN_F_TRIGGERED;
896 chn_trigger(c, PCMTRIG_ABORT);
898 if (!(c->flags & CHN_F_VIRTUAL))
899 chn_dmaupdate(c);
902 c->flags &= ~CHN_F_ABORTING;
918 chn_flush(struct pcm_channel *c)
920 struct snd_dbuf *b = c->bufhard;
922 CHN_LOCKASSERT(c);
923 KASSERT(c->direction == PCMDIR_PLAY, ("chn_flush on bad channel"));
924 DEB(printf("chn_flush: c->flags 0x%08x\n", c->flags));
926 c->flags |= CHN_F_CLOSING;
927 chn_sync(c, 0);
928 c->flags &= ~CHN_F_TRIGGERED;
930 chn_trigger(c, PCMTRIG_ABORT);
933 c->flags &= ~CHN_F_CLOSING;
1085 chn_reset(struct pcm_channel *c, uint32_t fmt, uint32_t spd)
1089 CHN_LOCKASSERT(c);
1090 c->feedcount = 0;
1091 c->flags &= CHN_F_RESET;
1092 c->interrupts = 0;
1093 c->timeout = 1;
1094 c->xruns = 0;
1096 c->flags |= (pcm_getflags(c->dev) & SD_F_BITPERFECT) ?
1099 r = CHANNEL_RESET(c->methods, c->devinfo);
1101 r = chn_setparam(c, fmt, spd);
1106 r = chn_setformat(c, fmt);
1108 r = chn_setspeed(c, spd);
1110 r = chn_setlatency(c, chn_latency);
1112 chn_resetbuf(c);
1113 r = CHANNEL_RESETDONE(c->methods, c->devinfo);
1137 chn_mkname(char *buf, size_t len, struct pcm_channel *c)
1144 switch (c->type) {
1162 device_get_unit(c->dev), str, c->unit);
1171 struct pcm_channel *c;
1200 c = malloc(sizeof(*c), M_DEVBUF, M_WAITOK | M_ZERO);
1201 c->methods = kobj_create(cls, M_DEVBUF, M_WAITOK | M_ZERO);
1202 chn_lockinit(c, dir);
1203 CHN_INIT(c, children);
1204 CHN_INIT(c, children.busy);
1205 c->direction = direction;
1206 c->type = dir;
1207 c->unit = alloc_unr(chn_getunr(d, c->type));
1208 c->format = SND_FORMAT(AFMT_U8, 1, 0);
1209 c->speed = DSP_DEFAULT_SPEED;
1210 c->pid = -1;
1211 c->latency = -1;
1212 c->timeout = 1;
1213 strlcpy(c->comm, CHN_COMM_UNUSED, sizeof(c->comm));
1214 c->parentsnddev = d;
1215 c->parentchannel = parent;
1216 c->dev = d->dev;
1217 c->trigger = PCMTRIG_STOP;
1218 strlcpy(c->name, chn_mkname(buf, sizeof(buf), c), sizeof(c->name));
1220 c->matrix = *feeder_matrix_id_map(SND_CHN_MATRIX_1_0);
1221 c->matrix.id = SND_CHN_MATRIX_PCMCHANNEL;
1224 c->volume[SND_VOL_C_MASTER][i] = SND_VOL_0DB_MASTER;
1226 c->volume[SND_VOL_C_MASTER][SND_CHN_T_VOL_0DB] = SND_VOL_0DB_MASTER;
1227 c->volume[SND_VOL_C_PCM][SND_CHN_T_VOL_0DB] = chn_vol_0db_pcm;
1229 CHN_LOCK(c);
1230 chn_vpc_reset(c, SND_VOL_C_PCM, 1);
1231 CHN_UNLOCK(c);
1239 if (feeder_add(c, fc, NULL)) {
1244 b = sndbuf_create(c->dev, c->name, "primary", c);
1245 bs = sndbuf_create(c->dev, c->name, "secondary", c);
1251 c->bufhard = b;
1252 c->bufsoft = bs;
1254 c->devinfo = CHANNEL_INIT(c->methods, devinfo, b, c, direction);
1255 if (c->devinfo == NULL) {
1260 if ((sndbuf_getsize(b) == 0) && ((c->flags & CHN_F_VIRTUAL) == 0)) {
1266 sndbuf_setfmt(b, c->format);
1267 sndbuf_setspd(b, c->speed);
1268 sndbuf_setfmt(bs, c->format);
1269 sndbuf_setspd(bs, c->speed);
1277 if (c->direction == PCMDIR_PLAY) {
1283 CHN_INSERT_SORT_ASCEND(d, c, channels.pcm);
1285 switch (c->type) {
1302 return (c);
1305 free_unr(chn_getunr(d, c->type), c->unit);
1306 feeder_remove(c);
1307 if (c->devinfo && CHANNEL_FREE(c->methods, c->devinfo))
1313 CHN_LOCK(c);
1314 chn_lockdestroy(c);
1316 kobj_delete(c->methods, M_DEVBUF);
1317 free(c, M_DEVBUF);
1325 chn_kill(struct pcm_channel *c)
1327 struct snddev_info *d = c->parentsnddev;
1328 struct snd_dbuf *b = c->bufhard;
1329 struct snd_dbuf *bs = c->bufsoft;
1331 PCM_BUSYASSERT(c->parentsnddev);
1334 CHN_REMOVE(d, c, channels.pcm);
1336 switch (c->type) {
1354 if (CHN_STARTED(c)) {
1355 CHN_LOCK(c);
1356 chn_trigger(c, PCMTRIG_ABORT);
1357 CHN_UNLOCK(c);
1359 free_unr(chn_getunr(c->parentsnddev, c->type), c->unit);
1360 feeder_remove(c);
1361 if (CHANNEL_FREE(c->methods, c->devinfo))
1365 CHN_LOCK(c);
1366 c->flags |= CHN_F_DEAD;
1367 chn_lockdestroy(c);
1368 kobj_delete(c->methods, M_DEVBUF);
1369 free(c, M_DEVBUF);
1373 chn_shutdown(struct pcm_channel *c)
1375 CHN_LOCKASSERT(c);
1377 chn_wakeup(c);
1378 c->flags |= CHN_F_DEAD;
1383 chn_release(struct pcm_channel *c)
1385 PCM_BUSYASSERT(c->parentsnddev);
1386 CHN_LOCKASSERT(c);
1388 c->flags &= ~CHN_F_BUSY;
1389 c->pid = -1;
1390 strlcpy(c->comm, CHN_COMM_UNUSED, sizeof(c->comm));
1391 CHN_UNLOCK(c);
1397 chn_setvolume_multi(struct pcm_channel *c, int vc, int left, int right,
1406 ret |= chn_setvolume_matrix(c, vc, i, left);
1408 ret |= chn_setvolume_matrix(c, vc, i, right) << 8;
1410 ret |= chn_setvolume_matrix(c, vc, i, center) << 16;
1417 chn_setvolume_matrix(struct pcm_channel *c, int vc, int vt, int val)
1421 KASSERT(c != NULL && vc >= SND_VOL_C_MASTER && vc < SND_VOL_C_MAX &&
1426 ("%s(): invalid volume matrix c=%p vc=%d vt=%d val=%d",
1427 __func__, c, vc, vt, val));
1428 CHN_LOCKASSERT(c);
1435 c->volume[vc][vt] = val;
1444 c->volume[SND_VOL_C_VAL(vc)][vt] =
1445 SND_VOL_CALC_VAL(c->volume, vc, vt);
1450 c->volume[SND_VOL_C_VAL(vc)][i] =
1451 SND_VOL_CALC_VAL(c->volume, vc, i);
1454 c->volume[SND_VOL_C_VAL(vc)][vt] =
1455 SND_VOL_CALC_VAL(c->volume, vc, vt);
1462 chn_getvolume_matrix(struct pcm_channel *c, int vc, int vt)
1464 KASSERT(c != NULL && vc >= SND_VOL_C_MASTER && vc < SND_VOL_C_MAX &&
1467 ("%s(): invalid volume matrix c=%p vc=%d vt=%d",
1468 __func__, c, vc, vt));
1469 CHN_LOCKASSERT(c);
1471 return (c->volume[vc][vt]);
1475 chn_setmute_multi(struct pcm_channel *c, int vc, int mute)
1483 ret |= chn_setmute_matrix(c, vc, i, mute);
1485 ret |= chn_setmute_matrix(c, vc, i, mute) << 8;
1487 ret |= chn_setmute_matrix(c, vc, i, mute) << 16;
1493 chn_setmute_matrix(struct pcm_channel *c, int vc, int vt, int mute)
1497 KASSERT(c != NULL && vc >= SND_VOL_C_MASTER && vc < SND_VOL_C_MAX &&
1500 ("%s(): invalid mute matrix c=%p vc=%d vt=%d mute=%d",
1501 __func__, c, vc, vt, mute));
1503 CHN_LOCKASSERT(c);
1507 c->muted[vc][vt] = mute;
1516 c->muted[SND_VOL_C_VAL(vc)][vt] = mute;
1521 c->muted[SND_VOL_C_VAL(vc)][i] = mute;
1524 c->muted[SND_VOL_C_VAL(vc)][vt] = mute;
1531 chn_getmute_matrix(struct pcm_channel *c, int vc, int vt)
1533 KASSERT(c != NULL && vc >= SND_VOL_C_MASTER && vc < SND_VOL_C_MAX &&
1536 ("%s(): invalid mute matrix c=%p vc=%d vt=%d",
1537 __func__, c, vc, vt));
1538 CHN_LOCKASSERT(c);
1540 return (c->muted[vc][vt]);
1544 chn_getmatrix(struct pcm_channel *c)
1547 KASSERT(c != NULL, ("%s(): NULL channel", __func__));
1548 CHN_LOCKASSERT(c);
1550 if (!(c->format & AFMT_CONVERTIBLE))
1553 return (&c->matrix);
1557 chn_setmatrix(struct pcm_channel *c, struct pcmchan_matrix *m)
1560 KASSERT(c != NULL && m != NULL,
1562 CHN_LOCKASSERT(c);
1564 if (!(c->format & AFMT_CONVERTIBLE))
1567 c->matrix = *m;
1568 c->matrix.id = SND_CHN_MATRIX_PCMCHANNEL;
1570 return (chn_setformat(c, SND_FORMAT(c->format, m->channels, m->ext)));
1577 chn_oss_getorder(struct pcm_channel *c, unsigned long long *map)
1580 KASSERT(c != NULL && map != NULL,
1582 CHN_LOCKASSERT(c);
1584 if (!(c->format & AFMT_CONVERTIBLE))
1587 return (feeder_matrix_oss_get_channel_order(&c->matrix, map));
1591 chn_oss_setorder(struct pcm_channel *c, unsigned long long *map)
1596 KASSERT(c != NULL && map != NULL,
1598 CHN_LOCKASSERT(c);
1600 if (!(c->format & AFMT_CONVERTIBLE))
1603 m = c->matrix;
1608 return (chn_setmatrix(c, &m));
1617 chn_oss_getmask(struct pcm_channel *c, uint32_t *retmask)
1623 KASSERT(c != NULL && retmask != NULL,
1625 CHN_LOCKASSERT(c);
1627 caps = chn_getcaps(c);
1637 m = CHANNEL_GETMATRIX(c->methods, c->devinfo, format);
1651 if (!CHN_BITPERFECT(c) && report_soft_matrix)
1659 chn_vpc_reset(struct pcm_channel *c, int vc, int force)
1663 KASSERT(c != NULL && vc >= SND_VOL_C_BEGIN && vc <= SND_VOL_C_END,
1664 ("%s(): invalid reset c=%p vc=%d", __func__, c, vc));
1665 CHN_LOCKASSERT(c);
1671 CHN_SETVOLUME(c, vc, i, c->volume[vc][SND_CHN_T_VOL_0DB]);
1853 chn_resizebuf(struct pcm_channel *c, int latency,
1860 CHN_LOCKASSERT(c);
1862 if ((c->flags & (CHN_F_MMAP | CHN_F_TRIGGERED)) ||
1863 !(c->direction == PCMDIR_PLAY || c->direction == PCMDIR_REC))
1867 c->latency = -1;
1870 latency = c->latency;
1876 c->latency = latency;
1879 bs = c->bufsoft;
1880 b = c->bufhard;
1887 chn_calclatency(c->direction, latency, sndbuf_getalign(bs),
1893 c->flags &= ~CHN_F_HAS_SIZE;
1894 if (c->flags & CHN_F_HAS_SIZE) {
1899 c->flags |= CHN_F_HAS_SIZE;
1901 if (c->flags & CHN_F_HAS_SIZE) {
1913 if (c->parentchannel != NULL) {
1914 pb = c->parentchannel->bufsoft;
1915 CHN_UNLOCK(c);
1916 CHN_LOCK(c->parentchannel);
1917 chn_notify(c->parentchannel, CHN_N_BLOCKSIZE);
1918 CHN_UNLOCK(c->parentchannel);
1919 CHN_LOCK(c);
1920 if (c->direction == PCMDIR_PLAY) {
1929 if (c->flags & CHN_F_HAS_SIZE) {
1934 chn_calclatency(c->direction, latency,
1952 CHN_UNLOCK(c);
1954 CHANNEL_SETFRAGMENTS(c->methods, c->devinfo,
1956 sndbuf_setblksz(b, CHANNEL_SETBLOCKSIZE(c->methods,
1957 c->devinfo, hblksz));
1958 CHN_LOCK(c);
1960 if (!CHN_EMPTY(c, children)) {
1965 if (c->direction == PCMDIR_PLAY) {
1998 device_printf(c->dev, "%s(): Failed: %d %d\n",
2007 c->timeout = ((u_int64_t)hz * sndbuf_getsize(bs)) /
2009 if (c->parentchannel != NULL)
2010 c->timeout = min(c->timeout, c->parentchannel->timeout);
2011 if (c->timeout < 1)
2012 c->timeout = 1;
2018 c->lw = sndbuf_getblksz(bs);
2019 chn_resetbuf(c);
2022 device_printf(c->dev, "%s(): %s (%s) timeout=%u "
2024 __func__, CHN_DIRSTR(c),
2025 (c->flags & CHN_F_VIRTUAL) ? "virtual" : "hardware",
2026 c->timeout,
2036 chn_setlatency(struct pcm_channel *c, int latency)
2038 CHN_LOCKASSERT(c);
2040 return chn_resizebuf(c, latency, -1, 0);
2044 chn_setblocksize(struct pcm_channel *c, int blkcnt, int blksz)
2046 CHN_LOCKASSERT(c);
2048 return chn_resizebuf(c, -1, blkcnt, blksz);
2052 chn_setparam(struct pcm_channel *c, uint32_t format, uint32_t speed)
2058 CHN_LOCKASSERT(c);
2060 if (speed < 1 || format == 0 || CHN_STARTED(c))
2063 c->format = format;
2064 c->speed = speed;
2066 caps = chn_getcaps(c);
2071 sndbuf_setspd(c->bufhard, CHANNEL_SETSPEED(c->methods, c->devinfo,
2073 hwspeed = sndbuf_getspd(c->bufhard);
2078 c->speed = hwspeed;
2080 ret = feeder_chain(c);
2083 ret = CHANNEL_SETFORMAT(c->methods, c->devinfo,
2084 sndbuf_getfmt(c->bufhard));
2087 ret = chn_resizebuf(c, -2, 0, 0);
2093 chn_setspeed(struct pcm_channel *c, uint32_t speed)
2098 oldformat = c->format;
2099 oldspeed = c->speed;
2102 ret = chn_setparam(c, format, speed);
2105 device_printf(c->dev,
2109 chn_setparam(c, c->format, oldspeed);
2116 chn_setformat(struct pcm_channel *c, uint32_t format)
2127 oldformat = c->format;
2128 oldspeed = c->speed;
2131 ret = chn_setparam(c, format, speed);
2134 device_printf(c->dev,
2138 chn_setparam(c, oldformat, oldspeed);
2145 chn_syncstate(struct pcm_channel *c)
2150 d = (c != NULL) ? c->parentsnddev : NULL;
2157 CHN_LOCKASSERT(c);
2159 if (c->feederflags & (1 << FEEDER_VOLUME)) {
2163 if (c->direction == PCMDIR_PLAY &&
2165 /* CHN_UNLOCK(c); */
2172 /* CHN_LOCK(c); */
2179 device_printf(c->dev,
2186 device_printf(c->dev,
2196 chn_setvolume_multi(c, SND_VOL_C_MASTER, left, right, center);
2199 if (c->feederflags & (1 << FEEDER_EQ)) {
2203 /* CHN_UNLOCK(c); */
2206 /* CHN_LOCK(c); */
2219 f = feeder_find(c, FEEDER_EQ);
2222 device_printf(c->dev,
2226 device_printf(c->dev,
2230 device_printf(c->dev,
2240 device_printf(c->dev,
2247 chn_trigger(struct pcm_channel *c, int go)
2249 struct snddev_info *d = c->parentsnddev;
2252 CHN_LOCKASSERT(c);
2254 return (CHANNEL_TRIGGER(c->methods, c->devinfo, go));
2256 if (go == c->trigger)
2260 device_printf(c->dev, "%s() %s: calling go=0x%08x , "
2261 "prev=0x%08x\n", __func__, c->name, go, c->trigger);
2264 c->trigger = go;
2265 ret = CHANNEL_TRIGGER(c->methods, c->devinfo, go);
2269 CHN_UNLOCK(c);
2271 CHN_LOCK(c);
2277 if (go != c->trigger) {
2288 CHN_INSERT_HEAD_SAFE(d, c, channels.pcm.busy);
2290 chn_syncstate(c);
2294 CHN_REMOVE(d, c, channels.pcm.busy);
2313 * @param c PCM channel context
2317 chn_getptr(struct pcm_channel *c)
2321 CHN_LOCKASSERT(c);
2322 hwptr = (CHN_STARTED(c)) ? CHANNEL_GETPTR(c->methods, c->devinfo) : 0;
2323 return (hwptr - (hwptr % sndbuf_getalign(c->bufhard)));
2327 chn_getcaps(struct pcm_channel *c)
2329 CHN_LOCKASSERT(c);
2330 return CHANNEL_GETCAPS(c->methods, c->devinfo);
2334 chn_getformats(struct pcm_channel *c)
2339 fmtlist = chn_getcaps(c)->fmtlist;
2345 if (!CHN_BITPERFECT(c) && report_soft_formats)
2352 chn_notify(struct pcm_channel *c, u_int32_t flags)
2360 CHN_LOCKASSERT(c);
2362 if (CHN_EMPTY(c, children))
2371 run = (CHN_STARTED(c)) ? 1 : 0;
2403 chn_setlatency(c, chn_latency);
2406 if ((flags & CHN_N_TRIGGER) && !(c->flags & CHN_F_VCHAN_DYNAMIC)) {
2407 nrun = CHN_EMPTY(c, children.busy) ? 0 : 1;
2409 err = chn_start(c, 1);
2411 chn_abort(c);
2416 if (c->direction == PCMDIR_PLAY) {
2417 vchanformat = &c->parentsnddev->pvchanformat;
2418 vchanrate = &c->parentsnddev->pvchanrate;
2420 vchanformat = &c->parentsnddev->rvchanformat;
2421 vchanrate = &c->parentsnddev->rvchanrate;
2425 if (!(c->flags & CHN_F_VCHAN_ADAPTIVE)) {
2435 caps = chn_getcaps(c);
2439 CHN_FOREACH(ch, c, children.busy) {
2451 if (c->flags & CHN_F_VCHAN_ADAPTIVE) {
2465 if (!(c->flags & CHN_F_VCHAN_ADAPTIVE) ||
2494 bestformat = c->format;
2496 bestspeed = c->speed;
2498 if (bestformat != c->format || bestspeed != c->speed)
2501 c->flags &= ~(CHN_F_PASSTHROUGH | CHN_F_EXCLUSIVE);
2502 c->flags |= vpflags;
2506 bestspeed = CHANNEL_SETSPEED(c->methods,
2507 c->devinfo, bestspeed);
2508 err = chn_reset(c, bestformat, bestspeed);
2511 CHN_FOREACH(ch, c, children.busy) {
2520 c->flags |= CHN_F_DIRTY;
2521 err = chn_start(c, 1);
2526 chn_abort(c);
2527 bestspeed = CHANNEL_SETSPEED(c->methods, c->devinfo,
2529 err = chn_reset(c, bestformat, bestspeed);
2531 CHN_FOREACH(ch, c, children.busy) {
2539 c->flags |= CHN_F_DIRTY;
2540 err = chn_start(c, 1);
2551 c->flags &= ~(CHN_F_PASSTHROUGH | CHN_F_EXCLUSIVE);
2554 chn_abort(c);
2555 if (c->format != bestformat || c->speed != bestspeed)
2556 chn_reset(c, bestformat, bestspeed);
2573 * @param c pcm channel to examine
2576 * @return number of rates in the array pointed to be @c rates
2579 chn_getrates(struct pcm_channel *c, int **rates)
2582 CHN_LOCKASSERT(c);
2583 return CHANNEL_GETRATES(c->methods, c->devinfo, rates);
2590 * - Starting a syncgroup (@c SNDCTL_DSP_SYNCSTART ioctl)
2595 * whether @c c is locked or not.)
2597 * @param c channel device to be started or closed
2604 chn_syncdestroy(struct pcm_channel *c)
2614 if (c->sm != NULL) {
2615 sm = c->sm;
2617 c->sm = NULL;
2636 chn_getpeaks(struct pcm_channel *c, int *lpeak, int *rpeak)
2638 CHN_LOCKASSERT(c);
2639 return CHANNEL_GETPEAKS(c->methods, c->devinfo, lpeak, rpeak);