2 * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
3 * Portions Copyright by Luigi Rizzo - 1997-99
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * $FreeBSD: src/sys/dev/sound/pcm/channel.c,v 1.99.2.5 2007/05/13 20:53:39 ariff Exp $
32 #include <dev/sound/pcm/sound.h>
33 #include <sys/vnode.h> /* IO_NDELAY */
35 #include "feeder_if.h"
37 SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pcm/channel.c,v 1.15 2008/01/05 13:34:22 corecode Exp $");
39 #define MIN_CHUNK_SIZE 256 /* for uiomove etc. */
41 #define DMA_ALIGN_THRESHOLD 4
42 #define DMA_ALIGN_MASK (~(DMA_ALIGN_THRESHOLD - 1))
45 #define CANCHANGE(c) (!(c->flags & CHN_F_TRIGGERED))
51 static int chn_targetirqrate = 32;
52 TUNABLE_INT("hw.snd.targetirqrate", &chn_targetirqrate);
55 sysctl_hw_snd_targetirqrate(SYSCTL_HANDLER_ARGS)
59 val = chn_targetirqrate;
60 err = sysctl_handle_int(oidp, &val, sizeof(val), req);
61 if (val < 16 || val > 512)
64 chn_targetirqrate = val;
68 SYSCTL_PROC(_hw_snd, OID_AUTO, targetirqrate, CTLTYPE_INT | CTLFLAG_RW,
69 0, sizeof(int), sysctl_hw_snd_targetirqrate, "I", "");
70 static int report_soft_formats = 1;
71 SYSCTL_INT(_hw_snd, OID_AUTO, report_soft_formats, CTLFLAG_RW,
72 &report_soft_formats, 1, "report software-emulated formats");
74 static int chn_buildfeeder(struct pcm_channel *c);
77 chn_lockinit(struct pcm_channel *c, int dir)
81 c->lock = snd_mtxcreate(c->name, "pcm play channel");
84 c->lock = snd_mtxcreate(c->name, "pcm record channel");
87 c->lock = snd_mtxcreate(c->name, "pcm virtual play channel");
90 c->lock = snd_mtxcreate(c->name, "pcm fake channel");
96 chn_lockdestroy(struct pcm_channel *c)
102 chn_polltrigger(struct pcm_channel *c)
104 struct snd_dbuf *bs = c->bufsoft;
108 if (c->flags & CHN_F_MAPPED) {
109 if (sndbuf_getprevblocks(bs) == 0)
112 return (sndbuf_getblocks(bs) > sndbuf_getprevblocks(bs))? 1 : 0;
114 amt = (c->direction == PCMDIR_PLAY)? sndbuf_getfree(bs) : sndbuf_getready(bs);
116 lim = (c->flags & CHN_F_HAS_SIZE)? sndbuf_getblksz(bs) : 1;
119 return (amt >= lim)? 1 : 0;
125 chn_pollreset(struct pcm_channel *c)
127 struct snd_dbuf *bs = c->bufsoft;
130 sndbuf_updateprevtotal(bs);
135 chn_wakeup(struct pcm_channel *c)
137 struct snd_dbuf *bs = c->bufsoft;
138 struct pcmchan_children *pce;
141 if (SLIST_EMPTY(&c->children)) {
142 /*if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c))*/
143 if (SLIST_FIRST(&sndbuf_getkq(bs)->ki_note) && chn_polltrigger(c)) {
147 * We would call KNOTE() here, but as we
148 * are in interrupt context, we'd have to
149 * acquire the MP lock before.
150 * Instead, we'll queue a task in a software
151 * interrupt, which will run with the MP lock
154 * buffer.c:sndbuf_kqtask will then call
155 * KNOTE() from safer context.
157 taskqueue_enqueue(taskqueue_swi, &bs->kqtask);
160 SLIST_FOREACH(pce, &c->children, link) {
161 CHN_LOCK(pce->channel);
162 chn_wakeup(pce->channel);
163 CHN_UNLOCK(pce->channel);
171 chn_sleep(struct pcm_channel *c, char *str, int timeout)
173 struct snd_dbuf *bs = c->bufsoft;
178 ret = snd_mtxsleep(bs, c->lock, PCATCH, str, timeout);
180 ret = tsleep(bs, PRIBIO | PCATCH, str, timeout);
187 * chn_dmaupdate() tracks the status of a dma transfer,
192 chn_dmaupdate(struct pcm_channel *c)
194 struct snd_dbuf *b = c->bufhard;
195 unsigned int delta, old, hwptr, amt;
197 KASSERT(sndbuf_getsize(b) > 0, ("bufsize == 0"));
200 old = sndbuf_gethwptr(b);
201 hwptr = chn_getptr(c);
202 delta = (sndbuf_getsize(b) + hwptr - old) % sndbuf_getsize(b);
203 sndbuf_sethwptr(b, hwptr);
206 if (delta >= ((sndbuf_getsize(b) * 15) / 16)) {
207 if (!(c->flags & (CHN_F_CLOSING | CHN_F_ABORTING)))
208 device_printf(c->dev, "hwptr went backwards %d -> %d\n", old, hwptr);
212 if (c->direction == PCMDIR_PLAY) {
213 amt = MIN(delta, sndbuf_getready(b));
215 sndbuf_dispose(b, NULL, amt);
217 amt = MIN(delta, sndbuf_getfree(b));
219 sndbuf_acquire(b, NULL, amt);
226 chn_wrupdate(struct pcm_channel *c)
231 KASSERT(c->direction == PCMDIR_PLAY, ("chn_wrupdate on bad channel"));
233 if ((c->flags & (CHN_F_MAPPED | CHN_F_VIRTUAL)) || !(c->flags & CHN_F_TRIGGERED))
237 /* tell the driver we've updated the primary buffer */
238 chn_trigger(c, PCMTRIG_EMLDMAWR);
240 kprintf("chn_wrupdate: chn_wrfeed returned %d\n", ret);)
245 chn_wrfeed(struct pcm_channel *c)
247 struct snd_dbuf *b = c->bufhard;
248 struct snd_dbuf *bs = c->bufsoft;
249 unsigned int ret, amt;
254 if (c->flags & CHN_F_CLOSING) {
255 sndbuf_dump(b, "b", 0x02);
256 sndbuf_dump(bs, "bs", 0x02);
260 if (c->flags & CHN_F_MAPPED)
261 sndbuf_acquire(bs, NULL, sndbuf_getfree(bs));
263 amt = sndbuf_getfree(b);
264 KASSERT(amt <= sndbuf_getsize(bs),
265 ("%s(%s): amt %d > source size %d, flags 0x%x", __func__, c->name,
266 amt, sndbuf_getsize(bs), c->flags));
268 ret = (amt > 0) ? sndbuf_feed(bs, b, c, c->feeder, amt) : ENOSPC;
270 * Possible xruns. There should be no empty space left in buffer.
272 if (sndbuf_getfree(b) > 0)
275 if (ret == 0 && sndbuf_getfree(b) < amt)
282 chn_wrintr(struct pcm_channel *c)
287 /* update pointers in primary buffer */
289 /* ...and feed from secondary to primary */
291 /* tell the driver we've updated the primary buffer */
292 chn_trigger(c, PCMTRIG_EMLDMAWR);
294 kprintf("chn_wrintr: chn_wrfeed returned %d\n", ret);)
298 * user write routine - uiomove data into secondary buffer, trigger if necessary
299 * if blocking, sleep, rinse and repeat.
301 * called externally, so must handle locking
305 chn_write(struct pcm_channel *c, struct uio *buf, int ioflags)
307 int ret, timeout, newsize, count, sz;
309 struct snd_dbuf *bs = c->bufsoft;
315 * XXX Certain applications attempt to write larger size
316 * of pcm data than c->blocksize2nd without blocking,
317 * resulting partial write. Expand the block size so that
318 * the write operation avoids blocking.
320 nbio = (c->flags & CHN_F_NBIO) || (ioflags & IO_NDELAY);
321 if (nbio && buf->uio_resid > (size_t)sndbuf_getblksz(bs)) {
322 DEB(device_printf(c->dev, "broken app, nbio and tried to write %ld bytes with fragsz %d\n",
323 buf->uio_resid, sndbuf_getblksz(bs)));
325 while (newsize < (int)szmin(buf->uio_resid, CHN_2NDBUFMAXSIZE / 2))
327 chn_setblocksize(c, sndbuf_getblkcnt(bs), newsize);
328 DEB(device_printf(c->dev, "frags reset to %d x %d\n", sndbuf_getblkcnt(bs), sndbuf_getblksz(bs)));
333 while (!ret && (buf->uio_resid > 0) && (count > 0)) {
334 sz = sndbuf_getfree(bs);
339 timeout = (hz * sndbuf_getblksz(bs)) / (sndbuf_getspd(bs) * sndbuf_getbps(bs));
343 ret = chn_sleep(c, "pcmwr", timeout);
344 if (ret == EWOULDBLOCK) {
351 sz = (int)szmin(sz, buf->uio_resid);
352 KASSERT(sz > 0, ("confusion in chn_write"));
353 /* kprintf("sz: %d\n", sz); */
356 * The following assumes that the free space in
357 * the buffer can never be less around the
358 * unlock-uiomove-lock sequence.
361 while (ret == 0 && togo> 0) {
362 p = sndbuf_getfreeptr(bs);
363 t = MIN(togo, sndbuf_getsize(bs) - p);
364 off = sndbuf_getbufofs(bs, p);
366 ret = uiomove(off, t, buf);
369 x = sndbuf_acquire(bs, NULL, t);
372 if (ret == 0 && !(c->flags & CHN_F_TRIGGERED))
376 /* kprintf("ret: %d left: %d\n", ret, buf->uio_resid); */
379 c->flags |= CHN_F_DEAD;
380 kprintf("%s: play interrupt timeout, channel dead\n", c->name);
388 chn_rddump(struct pcm_channel *c, unsigned int cnt)
390 struct snd_dbuf *b = c->bufhard;
394 static uint32_t kk = 0;
395 printf("%u: dumping %d bytes\n", ++kk, cnt);
398 sndbuf_setxrun(b, sndbuf_getxrun(b) + cnt);
399 return sndbuf_dispose(b, NULL, cnt);
404 * Feed new data from the read buffer. Can be called in the bottom half.
407 chn_rdfeed(struct pcm_channel *c)
409 struct snd_dbuf *b = c->bufhard;
410 struct snd_dbuf *bs = c->bufsoft;
411 unsigned int ret, amt;
415 if (c->flags & CHN_F_CLOSING) {
416 sndbuf_dump(b, "b", 0x02);
417 sndbuf_dump(bs, "bs", 0x02);
421 amt = sndbuf_getready(b);
422 if (sndbuf_getfree(bs) < amt) {
424 amt = sndbuf_getfree(bs);
427 amt = sndbuf_getfree(bs);
428 ret = (amt > 0)? sndbuf_feed(b, bs, c, c->feeder, amt) : 0;
430 amt = sndbuf_getready(b);
433 sndbuf_dispose(b, NULL, amt);
442 chn_rdupdate(struct pcm_channel *c)
447 KASSERT(c->direction == PCMDIR_REC, ("chn_rdupdate on bad channel"));
449 if ((c->flags & CHN_F_MAPPED) || !(c->flags & CHN_F_TRIGGERED))
451 chn_trigger(c, PCMTRIG_EMLDMARD);
455 kprintf("chn_rdfeed: %d\n", ret);)
458 /* read interrupt routine. Must be called with interrupts blocked. */
460 chn_rdintr(struct pcm_channel *c)
465 /* tell the driver to update the primary buffer if non-dma */
466 chn_trigger(c, PCMTRIG_EMLDMARD);
467 /* update pointers in primary buffer */
469 /* ...and feed from primary to secondary */
474 * user read routine - trigger if necessary, uiomove data from secondary buffer
475 * if blocking, sleep, rinse and repeat.
477 * called externally, so must handle locking
481 chn_read(struct pcm_channel *c, struct uio *buf, int ioflags)
483 int ret, timeout, sz, count;
485 struct snd_dbuf *bs = c->bufsoft;
490 nbio = (c->flags & CHN_F_NBIO) || (ioflags & IO_NDELAY);
491 if (!(c->flags & CHN_F_TRIGGERED))
496 while (!ret && (buf->uio_resid > 0) && (count > 0)) {
497 sz = (int)szmin(buf->uio_resid, sndbuf_getready(bs));
501 * The following assumes that the free space in
502 * the buffer can never be less around the
503 * unlock-uiomove-lock sequence.
506 while (ret == 0 && togo> 0) {
507 p = sndbuf_getreadyptr(bs);
508 t = MIN(togo, sndbuf_getsize(bs) - p);
509 off = sndbuf_getbufofs(bs, p);
511 ret = uiomove(off, t, buf);
514 x = sndbuf_dispose(bs, NULL, t);
521 timeout = (hz * sndbuf_getblksz(bs)) / (sndbuf_getspd(bs) * sndbuf_getbps(bs));
524 ret = chn_sleep(c, "pcmrd", timeout);
525 if (ret == EWOULDBLOCK) {
537 c->flags |= CHN_F_DEAD;
538 kprintf("%s: record interrupt timeout, channel dead\n", c->name);
545 chn_intr(struct pcm_channel *c)
549 if (c->direction == PCMDIR_PLAY)
557 chn_start(struct pcm_channel *c, int force)
560 struct snd_dbuf *b = c->bufhard;
561 struct snd_dbuf *bs = c->bufsoft;
564 /* if we're running, or if we're prevented from triggering, bail */
565 if ((c->flags & CHN_F_TRIGGERED) || ((c->flags & CHN_F_NOTRIGGER) && !force))
568 i = (c->direction == PCMDIR_PLAY)? sndbuf_getready(bs) : sndbuf_getfree(bs);
569 j = (c->direction == PCMDIR_PLAY)? sndbuf_getfree(b) : sndbuf_getready(b);
570 if (force || (i >= j)) {
571 c->flags |= CHN_F_TRIGGERED;
573 * if we're starting because a vchan started, don't feed any data
574 * or it becomes impossible to start vchans synchronised with the
575 * first one. the hardbuf should be empty so we top it up with
576 * silence to give it something to chew. the real data will be
577 * fed at the first irq.
579 if (c->direction == PCMDIR_PLAY) {
581 * Reduce pops during playback startup.
583 sndbuf_fillsilence(b);
584 if (SLIST_EMPTY(&c->children))
589 chn_trigger(c, PCMTRIG_START);
597 chn_resetbuf(struct pcm_channel *c)
599 struct snd_dbuf *b = c->bufhard;
600 struct snd_dbuf *bs = c->bufsoft;
608 * chn_sync waits until the space in the given channel goes above
609 * a threshold. The threshold is checked against fl or rl respectively.
610 * Assume that the condition can become true, do not check here...
613 chn_sync(struct pcm_channel *c, int threshold)
617 struct snd_dbuf *bs = c->bufsoft;
621 /* if we haven't yet started and nothing is buffered, else start*/
622 if (!(c->flags & CHN_F_TRIGGERED)) {
623 if (sndbuf_getready(bs) > 0) {
624 ret = chn_start(c, 1);
633 rdy = (c->direction == PCMDIR_PLAY)? sndbuf_getfree(bs) : sndbuf_getready(bs);
634 if (rdy <= threshold) {
635 ret = chn_sleep(c, "pcmsyn", 1);
636 if (ret == ERESTART || ret == EINTR) {
637 DEB(kprintf("chn_sync: tsleep returns %d\n", ret));
646 /* called externally, handle locking */
648 chn_poll(struct pcm_channel *c, int ev, struct thread *td)
653 if (!(c->flags & CHN_F_MAPPED) && !(c->flags & CHN_F_TRIGGERED))
656 if (chn_polltrigger(c) && chn_pollreset(c))
662 * chn_abort terminates a running dma transfer. it may sleep up to 200ms.
663 * it returns the number of bytes that have not been transferred.
665 * called from: dsp_close, dsp_ioctl, with channel locked
668 chn_abort(struct pcm_channel *c)
671 struct snd_dbuf *b = c->bufhard;
672 struct snd_dbuf *bs = c->bufsoft;
675 if (!(c->flags & CHN_F_TRIGGERED))
677 c->flags |= CHN_F_ABORTING;
679 c->flags &= ~CHN_F_TRIGGERED;
680 /* kill the channel */
681 chn_trigger(c, PCMTRIG_ABORT);
683 if (!(c->flags & CHN_F_VIRTUAL))
685 missing = sndbuf_getready(bs) + sndbuf_getready(b);
687 c->flags &= ~CHN_F_ABORTING;
692 * this routine tries to flush the dma transfer. It is called
693 * on a close of a playback channel.
694 * first, if there is data in the buffer, but the dma has not yet
695 * begun, we need to start it.
696 * next, we wait for the play buffer to drain
697 * finally, we stop the dma.
699 * called from: dsp_close, not valid for record channels.
703 chn_flush(struct pcm_channel *c)
705 int ret, count, resid, resid_p;
706 struct snd_dbuf *b = c->bufhard;
707 struct snd_dbuf *bs = c->bufsoft;
710 KASSERT(c->direction == PCMDIR_PLAY, ("chn_flush on bad channel"));
711 DEB(kprintf("chn_flush: c->flags 0x%08x\n", c->flags));
713 /* if we haven't yet started and nothing is buffered, else start*/
714 if (!(c->flags & CHN_F_TRIGGERED)) {
715 if (sndbuf_getready(bs) > 0) {
716 ret = chn_start(c, 1);
724 c->flags |= CHN_F_CLOSING;
725 resid = sndbuf_getready(bs) + sndbuf_getready(b);
729 while ((count > 0) && (resid > sndbuf_getsize(b)) && (ret == 0)) {
730 /* still pending output data. */
731 ret = chn_sleep(c, "pcmflu", hz / 10);
732 if (ret == EWOULDBLOCK)
735 resid = sndbuf_getready(bs) + sndbuf_getready(b);
736 if (resid == resid_p)
739 DEB(printf("chn_flush: buffer length increasind %d -> %d\n", resid_p, resid));
744 DEB(kprintf("chn_flush: timeout, hw %d, sw %d\n",
745 sndbuf_getready(b), sndbuf_getready(bs)));
747 c->flags &= ~CHN_F_TRIGGERED;
748 /* kill the channel */
749 chn_trigger(c, PCMTRIG_ABORT);
752 c->flags &= ~CHN_F_CLOSING;
757 fmtvalid(u_int32_t fmt, u_int32_t *fmtlist)
761 for (i = 0; fmtlist[i]; i++)
762 if (fmt == fmtlist[i])
768 chn_reset(struct pcm_channel *c, u_int32_t fmt)
773 c->flags &= CHN_F_RESET;
777 r = CHANNEL_RESET(c->methods, c->devinfo);
780 hwspd = DSP_DEFAULT_SPEED;
781 /* only do this on a record channel until feederbuilder works */
782 if (c->direction == PCMDIR_REC)
783 RANGE(hwspd, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
786 hwspd = chn_getcaps(c)->minspeed;
790 r = chn_setformat(c, fmt);
792 r = chn_setspeed(c, hwspd);
795 r = chn_setvolume(c, 100, 100);
799 r = chn_setblocksize(c, 0, 0);
802 r = CHANNEL_RESETDONE(c->methods, c->devinfo);
808 chn_init(struct pcm_channel *c, void *devinfo, int dir, int direction)
810 struct feeder_class *fc;
811 struct snd_dbuf *b, *bs;
814 chn_lockinit(c, dir);
822 b = sndbuf_create(c->dev, c->name, "primary", c);
825 bs = sndbuf_create(c->dev, c->name, "secondary", c);
832 fc = feeder_getclass(NULL);
835 if (chn_addfeeder(c, fc, NULL))
839 * XXX - sndbuf_setup() & sndbuf_resize() expect to be called
840 * with the channel unlocked because they are also called
841 * from driver methods that don't know about locking
844 sndbuf_setup(bs, NULL, 0);
852 CHN_UNLOCK(c); /* XXX - Unlock for CHANNEL_INIT() kmalloc() call */
853 c->devinfo = CHANNEL_INIT(c->methods, devinfo, b, c, direction);
855 if (c->devinfo == NULL)
859 if ((sndbuf_getsize(b) == 0) && ((c->flags & CHN_F_VIRTUAL) == 0))
862 ret = chn_setdir(c, direction);
866 ret = sndbuf_setfmt(b, AFMT_U8);
870 ret = sndbuf_setfmt(bs, AFMT_U8);
874 ret = chn_setvolume(c, 100, 100);
883 if (CHANNEL_FREE(c->methods, c->devinfo))
890 c->flags |= CHN_F_DEAD;
900 chn_kill(struct pcm_channel *c)
902 struct snd_dbuf *b = c->bufhard;
903 struct snd_dbuf *bs = c->bufsoft;
905 if (c->flags & CHN_F_TRIGGERED)
906 chn_trigger(c, PCMTRIG_ABORT);
907 while (chn_removefeeder(c) == 0);
908 if (CHANNEL_FREE(c->methods, c->devinfo))
910 c->flags |= CHN_F_DEAD;
918 chn_setdir(struct pcm_channel *c, int dir)
921 struct snd_dbuf *b = c->bufhard;
927 r = CHANNEL_SETDIR(c->methods, c->devinfo, c->direction);
929 if (!r && SND_DMA(b))
930 sndbuf_dmasetdir(b, c->direction);
936 chn_setvolume(struct pcm_channel *c, int left, int right)
939 /* should add a feeder for volume changing if channel returns -1 */
948 c->volume = left | (right << 8);
953 chn_tryspeed(struct pcm_channel *c, int speed)
955 struct pcm_feeder *f;
956 struct snd_dbuf *b = c->bufhard;
957 struct snd_dbuf *bs = c->bufsoft;
962 DEB(kprintf("setspeed, channel %s\n", c->name));
963 DEB(kprintf("want speed %d, ", speed));
969 sndbuf_setspd(bs, speed);
970 RANGE(speed, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
971 DEB(kprintf("try speed %d, ", speed));
972 sndbuf_setspd(b, CHANNEL_SETSPEED(c->methods, c->devinfo, speed));
973 DEB(kprintf("got speed %d\n", sndbuf_getspd(b)));
975 delta = sndbuf_getspd(b) - sndbuf_getspd(bs);
979 c->feederflags &= ~(1 << FEEDER_RATE);
981 * Used to be 500. It was too big!
984 c->feederflags |= 1 << FEEDER_RATE;
986 sndbuf_setspd(bs, sndbuf_getspd(b));
988 r = chn_buildfeeder(c);
989 DEB(kprintf("r = %d\n", r));
993 r = chn_setblocksize(c, 0, 0);
997 if (!(c->feederflags & (1 << FEEDER_RATE)))
1001 f = chn_findfeeder(c, FEEDER_RATE);
1002 DEB(kprintf("feedrate = %p\n", f));
1006 x = (c->direction == PCMDIR_REC)? b : bs;
1007 r = FEEDER_SET(f, FEEDRATE_SRC, sndbuf_getspd(x));
1008 DEB(kprintf("feeder_set(FEEDRATE_SRC, %d) = %d\n", sndbuf_getspd(x), r));
1012 x = (c->direction == PCMDIR_REC)? bs : b;
1013 r = FEEDER_SET(f, FEEDRATE_DST, sndbuf_getspd(x));
1014 DEB(kprintf("feeder_set(FEEDRATE_DST, %d) = %d\n", sndbuf_getspd(x), r));
1017 r = CHANNEL_SETFORMAT(c->methods, c->devinfo,
1020 sndbuf_setfmt(bs, c->format);
1021 DEB(kprintf("setspeed done, r = %d\n", r));
1028 chn_setspeed(struct pcm_channel *c, int speed)
1030 int r, oldspeed = c->speed;
1032 r = chn_tryspeed(c, speed);
1034 DEB(kprintf("Failed to set speed %d falling back to %d\n", speed, oldspeed));
1035 r = chn_tryspeed(c, oldspeed);
1041 chn_tryformat(struct pcm_channel *c, u_int32_t fmt)
1043 struct snd_dbuf *b = c->bufhard;
1044 struct snd_dbuf *bs = c->bufsoft;
1049 DEB(kprintf("want format %d\n", fmt));
1051 r = chn_buildfeeder(c);
1053 sndbuf_setfmt(bs, c->format);
1055 r = CHANNEL_SETFORMAT(c->methods, c->devinfo, sndbuf_getfmt(b));
1057 r = chn_tryspeed(c, c->speed);
1065 chn_setformat(struct pcm_channel *c, u_int32_t fmt)
1067 u_int32_t oldfmt = c->format;
1070 r = chn_tryformat(c, fmt);
1072 DEB(kprintf("Format change %d failed, reverting to %d\n", fmt, oldfmt));
1073 chn_tryformat(c, oldfmt);
1079 * given a bufsz value, round it to a power of 2 in the min-max range
1080 * XXX only works if min and max are powers of 2
1083 round_bufsz(int bufsz, int min, int max)
1087 KASSERT((min & (min-1)) == 0, ("min %d must be power of 2", min));
1088 KASSERT((max & (max-1)) == 0, ("max %d must be power of 2", max));
1089 while (tmp <= bufsz)
1098 * set the channel's blocksize both for soft and hard buffers.
1100 * blksz should be a power of 2 between 2**4 and 2**16 -- it is useful
1101 * that it has the same value for both bufsoft and bufhard.
1102 * blksz == -1 computes values according to a target irq rate.
1103 * blksz == 0 reuses previous values if available, otherwise
1106 * blkcnt is set by the user, between 2 and (2**17)/blksz for bufsoft,
1107 * but should be a power of 2 for bufhard to simplify life to low
1109 * Note, for the rec channel a large blkcnt is ok,
1110 * but for the play channel we want blksz as small as possible to keep
1111 * the delay small, because routines in the write path always try to
1112 * keep bufhard full.
1114 * Unless we have good reason to, use the values suggested by the caller.
1117 chn_setblocksize(struct pcm_channel *c, int blkcnt, int blksz)
1119 struct snd_dbuf *b = c->bufhard;
1120 struct snd_dbuf *bs = c->bufsoft;
1121 int irqhz, ret, maxsz, maxsize, reqblksz;
1124 if (!CANCHANGE(c) || (c->flags & CHN_F_MAPPED)) {
1125 KASSERT(sndbuf_getsize(bs) == 0 ||
1126 sndbuf_getsize(bs) >= sndbuf_getsize(b),
1127 ("%s(%s): bufsoft size %d < bufhard size %d", __func__,
1128 c->name, sndbuf_getsize(bs), sndbuf_getsize(b)));
1131 c->flags |= CHN_F_SETBLOCKSIZE;
1134 DEB(kprintf("%s(%d, %d)\n", __func__, blkcnt, blksz));
1135 if (blksz == 0 || blksz == -1) { /* let the driver choose values */
1136 if (blksz == -1) /* delete previous values */
1137 c->flags &= ~CHN_F_HAS_SIZE;
1138 if (!(c->flags & CHN_F_HAS_SIZE)) { /* no previous value */
1140 * compute a base blksz according to the target irq
1141 * rate, then round to a suitable power of 2
1142 * in the range 16.. 2^17/2.
1143 * Finally compute a suitable blkcnt.
1145 blksz = round_bufsz( (sndbuf_getbps(bs) *
1146 sndbuf_getspd(bs)) / chn_targetirqrate,
1147 16, CHN_2NDBUFMAXSIZE / 2);
1148 blkcnt = CHN_2NDBUFMAXSIZE / blksz;
1149 } else { /* use previously defined value */
1150 blkcnt = sndbuf_getblkcnt(bs);
1151 blksz = sndbuf_getblksz(bs);
1155 * use supplied values if reasonable. Note that here we
1156 * might have blksz which is not a power of 2 if the
1157 * ioctl() to compute it allows such values.
1160 if ((blksz < 16) || (blkcnt < 2) || (blkcnt * blksz > CHN_2NDBUFMAXSIZE))
1163 c->flags |= CHN_F_HAS_SIZE;
1167 if (reqblksz < sndbuf_getbps(bs))
1168 reqblksz = sndbuf_getbps(bs);
1169 if (reqblksz % sndbuf_getbps(bs))
1170 reqblksz -= reqblksz % sndbuf_getbps(bs);
1172 /* adjust for different hw format/speed */
1174 * Now compute the approx irq rate for the given (soft) blksz,
1175 * reduce to the acceptable range and compute a corresponding blksz
1176 * for the hard buffer. Then set the channel's blocksize and
1177 * corresponding hardbuf value. The number of blocks used should
1178 * be set by the device-specific routine. In fact, even the
1179 * call to sndbuf_setblksz() should not be here! XXX
1182 irqhz = (sndbuf_getbps(bs) * sndbuf_getspd(bs)) / blksz;
1183 RANGE(irqhz, 16, 512);
1185 maxsz = sndbuf_getmaxsize(b);
1186 if (maxsz == 0) /* virtual channels don't appear to allocate bufhard */
1187 maxsz = CHN_2NDBUFMAXSIZE;
1188 blksz = round_bufsz( (sndbuf_getbps(b) * sndbuf_getspd(b)) / irqhz,
1191 /* Increase the size of bufsoft if before increasing bufhard. */
1192 maxsize = sndbuf_getsize(b);
1193 if (sndbuf_getsize(bs) > maxsize)
1194 maxsize = sndbuf_getsize(bs);
1195 if (reqblksz * blkcnt > maxsize)
1196 maxsize = reqblksz * blkcnt;
1197 if (sndbuf_getsize(bs) != maxsize || sndbuf_getblksz(bs) != reqblksz) {
1198 ret = sndbuf_remalloc(bs, maxsize/reqblksz, reqblksz);
1204 sndbuf_setblksz(b, CHANNEL_SETBLOCKSIZE(c->methods, c->devinfo, blksz));
1207 /* Decrease the size of bufsoft after decreasing bufhard. */
1208 maxsize = sndbuf_getsize(b);
1209 if (reqblksz * blkcnt > maxsize)
1210 maxsize = reqblksz * blkcnt;
1211 if (maxsize > sndbuf_getsize(bs))
1212 kprintf("Danger! %s bufsoft size increasing from %d to %d after CHANNEL_SETBLOCKSIZE()\n",
1213 c->name, sndbuf_getsize(bs), maxsize);
1214 if (sndbuf_getsize(bs) != maxsize || sndbuf_getblksz(bs) != reqblksz) {
1215 ret = sndbuf_remalloc(bs, maxsize/reqblksz, reqblksz);
1222 KASSERT(sndbuf_getsize(bs) == 0 ||
1223 sndbuf_getsize(bs) >= sndbuf_getsize(b),
1224 ("%s(%s): bufsoft size %d < bufhard size %d, reqblksz=%d blksz=%d maxsize=%d blkcnt=%d",
1225 __func__, c->name, sndbuf_getsize(bs), sndbuf_getsize(b), reqblksz,
1226 blksz, maxsize, blkcnt));
1228 c->flags &= ~CHN_F_SETBLOCKSIZE;
1231 static uint32_t kk = 0;
1232 printf("%u: b %d/%d/%d : (%d)%d/0x%0x | bs %d/%d/%d : (%d)%d/0x%0x\n", ++kk,
1233 sndbuf_getsize(b), sndbuf_getblksz(b), sndbuf_getblkcnt(b),
1235 sndbuf_getspd(b), sndbuf_getfmt(b),
1236 sndbuf_getsize(bs), sndbuf_getblksz(bs), sndbuf_getblkcnt(bs),
1238 sndbuf_getspd(bs), sndbuf_getfmt(bs));
1239 if (sndbuf_getsize(b) % sndbuf_getbps(b) ||
1240 sndbuf_getblksz(b) % sndbuf_getbps(b) ||
1241 sndbuf_getsize(bs) % sndbuf_getbps(bs) ||
1242 sndbuf_getblksz(b) % sndbuf_getbps(b)) {
1243 printf("%u: bps/blksz alignment screwed!\n", kk);
1251 chn_trigger(struct pcm_channel *c, int go)
1254 struct snd_dbuf *b = c->bufhard;
1260 if (SND_DMA(b) && (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD))
1261 sndbuf_dmabounce(b);
1263 ret = CHANNEL_TRIGGER(c->methods, c->devinfo, go);
1269 chn_getptr(struct pcm_channel *c)
1273 int a = (1 << c->align) - 1;
1276 hwptr = (c->flags & CHN_F_TRIGGERED)? CHANNEL_GETPTR(c->methods, c->devinfo) : 0;
1277 /* don't allow unaligned values in the hwa ptr */
1279 hwptr &= ~a ; /* Apply channel align mask */
1281 hwptr &= DMA_ALIGN_MASK; /* Apply DMA align mask */
1287 hwptr = (c->flags & CHN_F_TRIGGERED)? CHANNEL_GETPTR(c->methods, c->devinfo) : 0;
1288 return (hwptr - (hwptr % sndbuf_getbps(c->bufhard)));
1291 struct pcmchan_caps *
1292 chn_getcaps(struct pcm_channel *c)
1295 return CHANNEL_GETCAPS(c->methods, c->devinfo);
1299 chn_getformats(struct pcm_channel *c)
1301 u_int32_t *fmtlist, fmts;
1304 fmtlist = chn_getcaps(c)->fmtlist;
1306 for (i = 0; fmtlist[i]; i++)
1309 /* report software-supported formats */
1310 if (report_soft_formats)
1311 fmts |= AFMT_MU_LAW|AFMT_A_LAW|AFMT_U32_LE|AFMT_U32_BE|
1312 AFMT_S32_LE|AFMT_S32_BE|AFMT_U24_LE|AFMT_U24_BE|
1313 AFMT_S24_LE|AFMT_S24_BE|AFMT_U16_LE|AFMT_U16_BE|
1314 AFMT_S16_LE|AFMT_S16_BE|AFMT_U8|AFMT_S8;
1320 chn_buildfeeder(struct pcm_channel *c)
1322 struct feeder_class *fc;
1323 struct pcm_feederdesc desc;
1324 u_int32_t tmp[2], type, flags, hwfmt, *fmtlist;
1328 while (chn_removefeeder(c) == 0);
1329 KASSERT((c->feeder == NULL), ("feeder chain not empty"));
1331 c->align = sndbuf_getalign(c->bufsoft);
1333 if (SLIST_EMPTY(&c->children)) {
1334 fc = feeder_getclass(NULL);
1335 KASSERT(fc != NULL, ("can't find root feeder"));
1337 err = chn_addfeeder(c, fc, NULL);
1339 DEB(kprintf("can't add root feeder, err %d\n", err));
1343 c->feeder->desc->out = c->format;
1345 if (c->flags & CHN_F_HAS_VCHAN) {
1346 desc.type = FEEDER_MIXER;
1349 DEB(printf("can't decide which feeder type to use!\n"));
1352 desc.out = c->format;
1354 fc = feeder_getclass(&desc);
1356 DEB(kprintf("can't find vchan feeder\n"));
1361 err = chn_addfeeder(c, fc, &desc);
1363 DEB(kprintf("can't add vchan feeder, err %d\n", err));
1368 c->feederflags &= ~(1 << FEEDER_VOLUME);
1369 if (c->direction == PCMDIR_PLAY &&
1370 !(c->flags & CHN_F_VIRTUAL) &&
1371 c->parentsnddev && (c->parentsnddev->flags & SD_F_SOFTPCMVOL) &&
1372 c->parentsnddev->mixer_dev)
1373 c->feederflags |= 1 << FEEDER_VOLUME;
1374 flags = c->feederflags;
1375 fmtlist = chn_getcaps(c)->fmtlist;
1377 DEB(kprintf("feederflags %x\n", flags));
1379 for (type = FEEDER_RATE; type <= FEEDER_LAST; type++) {
1380 if (flags & (1 << type)) {
1385 DEB(kprintf("find feeder type %d, ", type));
1386 fc = feeder_getclass(&desc);
1387 DEB(kprintf("got %p\n", fc));
1389 DEB(kprintf("can't find required feeder type %d\n", type));
1394 DEB(kprintf("build fmtchain from 0x%08x to 0x%08x: ", c->feeder->desc->out, fc->desc->in));
1395 tmp[0] = fc->desc->in;
1397 if (chn_fmtchain(c, tmp) == 0) {
1398 DEB(printf("failed\n"));
1402 DEB(printf("ok\n"));
1404 err = chn_addfeeder(c, fc, fc->desc);
1406 DEB(kprintf("can't add feeder %p, output 0x%x, err %d\n", fc, fc->desc->out, err));
1410 DEB(kprintf("added feeder %p, output 0x%x\n", fc, c->feeder->desc->out));
1414 if (c->direction == PCMDIR_REC) {
1417 hwfmt = chn_fmtchain(c, tmp);
1419 hwfmt = chn_fmtchain(c, fmtlist);
1421 if (hwfmt == 0 || !fmtvalid(hwfmt, fmtlist)) {
1422 DEB(printf("Invalid hardware format: 0x%08x\n", hwfmt));
1426 sndbuf_setfmt(c->bufhard, hwfmt);
1428 if ((flags & (1 << FEEDER_VOLUME))) {
1429 struct dev_ioctl_args map;
1430 u_int32_t parent = SOUND_MIXER_NONE;
1431 int vol, left, right;
1433 vol = 100 | (100 << 8);
1437 * XXX This is ugly! The way mixer subs being so secretive
1438 * about its own internals force us to use this silly
1441 map.a_head.a_dev = c->parentsnddev->mixer_dev;
1442 map.a_cmd = MIXER_READ(SOUND_MIXER_PCM);
1443 map.a_data = (caddr_t)&vol;
1446 map.a_sysmsg = NULL;
1447 if (mixer_ioctl(&map) != 0)
1448 device_printf(c->dev, "Soft PCM Volume: Failed to read default value\n");
1450 right = (vol >> 8) & 0x7f;
1451 if (c->parentsnddev != NULL &&
1452 c->parentsnddev->mixer_dev != NULL &&
1453 c->parentsnddev->mixer_dev->si_drv1 != NULL)
1454 parent = mix_getparent(
1455 c->parentsnddev->mixer_dev->si_drv1,
1457 if (parent != SOUND_MIXER_NONE) {
1458 vol = 100 | (100 << 8);
1459 map.a_head.a_dev = c->parentsnddev->mixer_dev;
1460 map.a_cmd = MIXER_READ(parent);
1461 map.a_data = (caddr_t)&vol;
1464 if (mixer_ioctl(&map) != 0)
1465 device_printf(c->dev, "Soft Volume: Failed to read parent default value\n");
1466 left = (left * (vol & 0x7f)) / 100;
1467 right = (right * ((vol >> 8) & 0x7f)) / 100;
1471 chn_setvolume(c, left, right);
1478 chn_notify(struct pcm_channel *c, u_int32_t flags)
1480 struct pcmchan_children *pce;
1481 struct pcm_channel *child;
1486 if (SLIST_EMPTY(&c->children)) {
1491 run = (c->flags & CHN_F_TRIGGERED)? 1 : 0;
1493 * if the hwchan is running, we can't change its rate, format or
1497 flags &= CHN_N_VOLUME | CHN_N_TRIGGER;
1499 if (flags & CHN_N_RATE) {
1501 * we could do something here, like scan children and decide on
1502 * the most appropriate rate to mix at, but we don't for now
1505 if (flags & CHN_N_FORMAT) {
1507 * we could do something here, like scan children and decide on
1508 * the most appropriate mixer feeder to use, but we don't for now
1511 if (flags & CHN_N_VOLUME) {
1513 * we could do something here but we don't for now
1516 if (flags & CHN_N_BLOCKSIZE) {
1519 * scan the children, find the lowest blocksize and use that
1520 * for the hard blocksize
1522 blksz = sndbuf_getmaxsize(c->bufhard) / 2;
1523 SLIST_FOREACH(pce, &c->children, link) {
1524 child = pce->channel;
1526 if (sndbuf_getblksz(child->bufhard) < blksz)
1527 blksz = sndbuf_getblksz(child->bufhard);
1530 chn_setblocksize(c, 2, blksz);
1532 if (flags & CHN_N_TRIGGER) {
1535 * scan the children, and figure out if any are running
1536 * if so, we need to be running, otherwise we need to be stopped
1537 * if we aren't in our target sstate, move to it
1540 SLIST_FOREACH(pce, &c->children, link) {
1541 child = pce->channel;
1543 if (child->flags & CHN_F_TRIGGERED)
1557 chn_lock(struct pcm_channel *c)
1563 chn_unlock(struct pcm_channel *c)