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 $
28 * $DragonFly: src/sys/dev/sound/pcm/channel.c,v 1.15 2008/01/05 13:34:22 corecode Exp $
33 #include <dev/sound/pcm/sound.h>
34 #include <sys/vnode.h> /* IO_NDELAY */
36 #include "feeder_if.h"
38 SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pcm/channel.c,v 1.15 2008/01/05 13:34:22 corecode Exp $");
40 #define MIN_CHUNK_SIZE 256 /* for uiomove etc. */
42 #define DMA_ALIGN_THRESHOLD 4
43 #define DMA_ALIGN_MASK (~(DMA_ALIGN_THRESHOLD - 1))
46 #define CANCHANGE(c) (!(c->flags & CHN_F_TRIGGERED))
52 static int chn_targetirqrate
= 32;
53 TUNABLE_INT("hw.snd.targetirqrate", &chn_targetirqrate
);
56 sysctl_hw_snd_targetirqrate(SYSCTL_HANDLER_ARGS
)
60 val
= chn_targetirqrate
;
61 err
= sysctl_handle_int(oidp
, &val
, sizeof(val
), req
);
62 if (val
< 16 || val
> 512)
65 chn_targetirqrate
= val
;
69 SYSCTL_PROC(_hw_snd
, OID_AUTO
, targetirqrate
, CTLTYPE_INT
| CTLFLAG_RW
,
70 0, sizeof(int), sysctl_hw_snd_targetirqrate
, "I", "");
71 static int report_soft_formats
= 1;
72 SYSCTL_INT(_hw_snd
, OID_AUTO
, report_soft_formats
, CTLFLAG_RW
,
73 &report_soft_formats
, 1, "report software-emulated formats");
75 static int chn_buildfeeder(struct pcm_channel
*c
);
78 chn_lockinit(struct pcm_channel
*c
, int dir
)
82 c
->lock
= snd_mtxcreate(c
->name
, "pcm play channel");
85 c
->lock
= snd_mtxcreate(c
->name
, "pcm record channel");
88 c
->lock
= snd_mtxcreate(c
->name
, "pcm virtual play channel");
91 c
->lock
= snd_mtxcreate(c
->name
, "pcm fake channel");
97 chn_lockdestroy(struct pcm_channel
*c
)
103 chn_polltrigger(struct pcm_channel
*c
)
105 struct snd_dbuf
*bs
= c
->bufsoft
;
109 if (c
->flags
& CHN_F_MAPPED
) {
110 if (sndbuf_getprevblocks(bs
) == 0)
113 return (sndbuf_getblocks(bs
) > sndbuf_getprevblocks(bs
))? 1 : 0;
115 amt
= (c
->direction
== PCMDIR_PLAY
)? sndbuf_getfree(bs
) : sndbuf_getready(bs
);
117 lim
= (c
->flags
& CHN_F_HAS_SIZE
)? sndbuf_getblksz(bs
) : 1;
120 return (amt
>= lim
)? 1 : 0;
126 chn_pollreset(struct pcm_channel
*c
)
128 struct snd_dbuf
*bs
= c
->bufsoft
;
131 sndbuf_updateprevtotal(bs
);
136 chn_wakeup(struct pcm_channel
*c
)
138 struct snd_dbuf
*bs
= c
->bufsoft
;
139 struct pcmchan_children
*pce
;
142 if (SLIST_EMPTY(&c
->children
)) {
143 /*if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c))*/
144 if (sndbuf_getsel(bs
)->si_pid
&& chn_polltrigger(c
)) {
146 * We would call selwakeup() here, but as we
147 * are in interrupt context, we'd have to
148 * acquire the MP lock before.
149 * Instead, we'll queue a task in a software
150 * interrupt, which will run with the MP lock
153 * buffer.c:sndbuf_seltask will then call
154 * selwakeup() from safer context.
156 taskqueue_enqueue(taskqueue_swi
, &bs
->seltask
);
159 SLIST_FOREACH(pce
, &c
->children
, link
) {
160 CHN_LOCK(pce
->channel
);
161 chn_wakeup(pce
->channel
);
162 CHN_UNLOCK(pce
->channel
);
170 chn_sleep(struct pcm_channel
*c
, char *str
, int timeout
)
172 struct snd_dbuf
*bs
= c
->bufsoft
;
177 ret
= snd_mtxsleep(bs
, c
->lock
, PCATCH
, str
, timeout
);
179 ret
= tsleep(bs
, PRIBIO
| PCATCH
, str
, timeout
);
186 * chn_dmaupdate() tracks the status of a dma transfer,
191 chn_dmaupdate(struct pcm_channel
*c
)
193 struct snd_dbuf
*b
= c
->bufhard
;
194 unsigned int delta
, old
, hwptr
, amt
;
196 KASSERT(sndbuf_getsize(b
) > 0, ("bufsize == 0"));
199 old
= sndbuf_gethwptr(b
);
200 hwptr
= chn_getptr(c
);
201 delta
= (sndbuf_getsize(b
) + hwptr
- old
) % sndbuf_getsize(b
);
202 sndbuf_sethwptr(b
, hwptr
);
205 if (delta
>= ((sndbuf_getsize(b
) * 15) / 16)) {
206 if (!(c
->flags
& (CHN_F_CLOSING
| CHN_F_ABORTING
)))
207 device_printf(c
->dev
, "hwptr went backwards %d -> %d\n", old
, hwptr
);
211 if (c
->direction
== PCMDIR_PLAY
) {
212 amt
= MIN(delta
, sndbuf_getready(b
));
214 sndbuf_dispose(b
, NULL
, amt
);
216 amt
= MIN(delta
, sndbuf_getfree(b
));
218 sndbuf_acquire(b
, NULL
, amt
);
225 chn_wrupdate(struct pcm_channel
*c
)
230 KASSERT(c
->direction
== PCMDIR_PLAY
, ("chn_wrupdate on bad channel"));
232 if ((c
->flags
& (CHN_F_MAPPED
| CHN_F_VIRTUAL
)) || !(c
->flags
& CHN_F_TRIGGERED
))
236 /* tell the driver we've updated the primary buffer */
237 chn_trigger(c
, PCMTRIG_EMLDMAWR
);
239 kprintf("chn_wrupdate: chn_wrfeed returned %d\n", ret
);)
244 chn_wrfeed(struct pcm_channel
*c
)
246 struct snd_dbuf
*b
= c
->bufhard
;
247 struct snd_dbuf
*bs
= c
->bufsoft
;
248 unsigned int ret
, amt
;
253 if (c
->flags
& CHN_F_CLOSING
) {
254 sndbuf_dump(b
, "b", 0x02);
255 sndbuf_dump(bs
, "bs", 0x02);
259 if (c
->flags
& CHN_F_MAPPED
)
260 sndbuf_acquire(bs
, NULL
, sndbuf_getfree(bs
));
262 amt
= sndbuf_getfree(b
);
263 KASSERT(amt
<= sndbuf_getsize(bs
),
264 ("%s(%s): amt %d > source size %d, flags 0x%x", __func__
, c
->name
,
265 amt
, sndbuf_getsize(bs
), c
->flags
));
267 ret
= (amt
> 0) ? sndbuf_feed(bs
, b
, c
, c
->feeder
, amt
) : ENOSPC
;
269 * Possible xruns. There should be no empty space left in buffer.
271 if (sndbuf_getfree(b
) > 0)
274 if (ret
== 0 && sndbuf_getfree(b
) < amt
)
281 chn_wrintr(struct pcm_channel
*c
)
286 /* update pointers in primary buffer */
288 /* ...and feed from secondary to primary */
290 /* tell the driver we've updated the primary buffer */
291 chn_trigger(c
, PCMTRIG_EMLDMAWR
);
293 kprintf("chn_wrintr: chn_wrfeed returned %d\n", ret
);)
297 * user write routine - uiomove data into secondary buffer, trigger if necessary
298 * if blocking, sleep, rinse and repeat.
300 * called externally, so must handle locking
304 chn_write(struct pcm_channel
*c
, struct uio
*buf
, int ioflags
)
306 int ret
, timeout
, newsize
, count
, sz
;
308 struct snd_dbuf
*bs
= c
->bufsoft
;
314 * XXX Certain applications attempt to write larger size
315 * of pcm data than c->blocksize2nd without blocking,
316 * resulting partial write. Expand the block size so that
317 * the write operation avoids blocking.
319 nbio
= (c
->flags
& CHN_F_NBIO
) || (ioflags
& IO_NDELAY
);
320 if (nbio
&& buf
->uio_resid
> (size_t)sndbuf_getblksz(bs
)) {
321 DEB(device_printf(c
->dev
, "broken app, nbio and tried to write %ld bytes with fragsz %d\n",
322 buf
->uio_resid
, sndbuf_getblksz(bs
)));
324 while (newsize
< (int)szmin(buf
->uio_resid
, CHN_2NDBUFMAXSIZE
/ 2))
326 chn_setblocksize(c
, sndbuf_getblkcnt(bs
), newsize
);
327 DEB(device_printf(c
->dev
, "frags reset to %d x %d\n", sndbuf_getblkcnt(bs
), sndbuf_getblksz(bs
)));
332 while (!ret
&& (buf
->uio_resid
> 0) && (count
> 0)) {
333 sz
= sndbuf_getfree(bs
);
338 timeout
= (hz
* sndbuf_getblksz(bs
)) / (sndbuf_getspd(bs
) * sndbuf_getbps(bs
));
342 ret
= chn_sleep(c
, "pcmwr", timeout
);
343 if (ret
== EWOULDBLOCK
) {
350 sz
= (int)szmin(sz
, buf
->uio_resid
);
351 KASSERT(sz
> 0, ("confusion in chn_write"));
352 /* kprintf("sz: %d\n", sz); */
355 * The following assumes that the free space in
356 * the buffer can never be less around the
357 * unlock-uiomove-lock sequence.
360 while (ret
== 0 && togo
> 0) {
361 p
= sndbuf_getfreeptr(bs
);
362 t
= MIN(togo
, sndbuf_getsize(bs
) - p
);
363 off
= sndbuf_getbufofs(bs
, p
);
365 ret
= uiomove(off
, t
, buf
);
368 x
= sndbuf_acquire(bs
, NULL
, t
);
371 if (ret
== 0 && !(c
->flags
& CHN_F_TRIGGERED
))
375 /* kprintf("ret: %d left: %d\n", ret, buf->uio_resid); */
378 c
->flags
|= CHN_F_DEAD
;
379 kprintf("%s: play interrupt timeout, channel dead\n", c
->name
);
387 chn_rddump(struct pcm_channel
*c
, unsigned int cnt
)
389 struct snd_dbuf
*b
= c
->bufhard
;
393 static uint32_t kk
= 0;
394 printf("%u: dumping %d bytes\n", ++kk
, cnt
);
397 sndbuf_setxrun(b
, sndbuf_getxrun(b
) + cnt
);
398 return sndbuf_dispose(b
, NULL
, cnt
);
403 * Feed new data from the read buffer. Can be called in the bottom half.
406 chn_rdfeed(struct pcm_channel
*c
)
408 struct snd_dbuf
*b
= c
->bufhard
;
409 struct snd_dbuf
*bs
= c
->bufsoft
;
410 unsigned int ret
, amt
;
414 if (c
->flags
& CHN_F_CLOSING
) {
415 sndbuf_dump(b
, "b", 0x02);
416 sndbuf_dump(bs
, "bs", 0x02);
420 amt
= sndbuf_getready(b
);
421 if (sndbuf_getfree(bs
) < amt
) {
423 amt
= sndbuf_getfree(bs
);
426 amt
= sndbuf_getfree(bs
);
427 ret
= (amt
> 0)? sndbuf_feed(b
, bs
, c
, c
->feeder
, amt
) : 0;
429 amt
= sndbuf_getready(b
);
432 sndbuf_dispose(b
, NULL
, amt
);
441 chn_rdupdate(struct pcm_channel
*c
)
446 KASSERT(c
->direction
== PCMDIR_REC
, ("chn_rdupdate on bad channel"));
448 if ((c
->flags
& CHN_F_MAPPED
) || !(c
->flags
& CHN_F_TRIGGERED
))
450 chn_trigger(c
, PCMTRIG_EMLDMARD
);
454 kprintf("chn_rdfeed: %d\n", ret
);)
457 /* read interrupt routine. Must be called with interrupts blocked. */
459 chn_rdintr(struct pcm_channel
*c
)
464 /* tell the driver to update the primary buffer if non-dma */
465 chn_trigger(c
, PCMTRIG_EMLDMARD
);
466 /* update pointers in primary buffer */
468 /* ...and feed from primary to secondary */
473 * user read routine - trigger if necessary, uiomove data from secondary buffer
474 * if blocking, sleep, rinse and repeat.
476 * called externally, so must handle locking
480 chn_read(struct pcm_channel
*c
, struct uio
*buf
, int ioflags
)
482 int ret
, timeout
, sz
, count
;
484 struct snd_dbuf
*bs
= c
->bufsoft
;
489 nbio
= (c
->flags
& CHN_F_NBIO
) || (ioflags
& IO_NDELAY
);
490 if (!(c
->flags
& CHN_F_TRIGGERED
))
495 while (!ret
&& (buf
->uio_resid
> 0) && (count
> 0)) {
496 sz
= (int)szmin(buf
->uio_resid
, sndbuf_getready(bs
));
500 * The following assumes that the free space in
501 * the buffer can never be less around the
502 * unlock-uiomove-lock sequence.
505 while (ret
== 0 && togo
> 0) {
506 p
= sndbuf_getreadyptr(bs
);
507 t
= MIN(togo
, sndbuf_getsize(bs
) - p
);
508 off
= sndbuf_getbufofs(bs
, p
);
510 ret
= uiomove(off
, t
, buf
);
513 x
= sndbuf_dispose(bs
, NULL
, t
);
520 timeout
= (hz
* sndbuf_getblksz(bs
)) / (sndbuf_getspd(bs
) * sndbuf_getbps(bs
));
523 ret
= chn_sleep(c
, "pcmrd", timeout
);
524 if (ret
== EWOULDBLOCK
) {
536 c
->flags
|= CHN_F_DEAD
;
537 kprintf("%s: record interrupt timeout, channel dead\n", c
->name
);
544 chn_intr(struct pcm_channel
*c
)
548 if (c
->direction
== PCMDIR_PLAY
)
556 chn_start(struct pcm_channel
*c
, int force
)
559 struct snd_dbuf
*b
= c
->bufhard
;
560 struct snd_dbuf
*bs
= c
->bufsoft
;
563 /* if we're running, or if we're prevented from triggering, bail */
564 if ((c
->flags
& CHN_F_TRIGGERED
) || ((c
->flags
& CHN_F_NOTRIGGER
) && !force
))
567 i
= (c
->direction
== PCMDIR_PLAY
)? sndbuf_getready(bs
) : sndbuf_getfree(bs
);
568 j
= (c
->direction
== PCMDIR_PLAY
)? sndbuf_getfree(b
) : sndbuf_getready(b
);
569 if (force
|| (i
>= j
)) {
570 c
->flags
|= CHN_F_TRIGGERED
;
572 * if we're starting because a vchan started, don't feed any data
573 * or it becomes impossible to start vchans synchronised with the
574 * first one. the hardbuf should be empty so we top it up with
575 * silence to give it something to chew. the real data will be
576 * fed at the first irq.
578 if (c
->direction
== PCMDIR_PLAY
) {
580 * Reduce pops during playback startup.
582 sndbuf_fillsilence(b
);
583 if (SLIST_EMPTY(&c
->children
))
588 chn_trigger(c
, PCMTRIG_START
);
596 chn_resetbuf(struct pcm_channel
*c
)
598 struct snd_dbuf
*b
= c
->bufhard
;
599 struct snd_dbuf
*bs
= c
->bufsoft
;
607 * chn_sync waits until the space in the given channel goes above
608 * a threshold. The threshold is checked against fl or rl respectively.
609 * Assume that the condition can become true, do not check here...
612 chn_sync(struct pcm_channel
*c
, int threshold
)
616 struct snd_dbuf
*bs
= c
->bufsoft
;
620 /* if we haven't yet started and nothing is buffered, else start*/
621 if (!(c
->flags
& CHN_F_TRIGGERED
)) {
622 if (sndbuf_getready(bs
) > 0) {
623 ret
= chn_start(c
, 1);
632 rdy
= (c
->direction
== PCMDIR_PLAY
)? sndbuf_getfree(bs
) : sndbuf_getready(bs
);
633 if (rdy
<= threshold
) {
634 ret
= chn_sleep(c
, "pcmsyn", 1);
635 if (ret
== ERESTART
|| ret
== EINTR
) {
636 DEB(kprintf("chn_sync: tsleep returns %d\n", ret
));
645 /* called externally, handle locking */
647 chn_poll(struct pcm_channel
*c
, int ev
, struct thread
*td
)
649 struct snd_dbuf
*bs
= c
->bufsoft
;
653 if (!(c
->flags
& CHN_F_MAPPED
) && !(c
->flags
& CHN_F_TRIGGERED
))
656 if (chn_polltrigger(c
) && chn_pollreset(c
))
659 selrecord(td
, sndbuf_getsel(bs
));
664 * chn_abort terminates a running dma transfer. it may sleep up to 200ms.
665 * it returns the number of bytes that have not been transferred.
667 * called from: dsp_close, dsp_ioctl, with channel locked
670 chn_abort(struct pcm_channel
*c
)
673 struct snd_dbuf
*b
= c
->bufhard
;
674 struct snd_dbuf
*bs
= c
->bufsoft
;
677 if (!(c
->flags
& CHN_F_TRIGGERED
))
679 c
->flags
|= CHN_F_ABORTING
;
681 c
->flags
&= ~CHN_F_TRIGGERED
;
682 /* kill the channel */
683 chn_trigger(c
, PCMTRIG_ABORT
);
685 if (!(c
->flags
& CHN_F_VIRTUAL
))
687 missing
= sndbuf_getready(bs
) + sndbuf_getready(b
);
689 c
->flags
&= ~CHN_F_ABORTING
;
694 * this routine tries to flush the dma transfer. It is called
695 * on a close of a playback channel.
696 * first, if there is data in the buffer, but the dma has not yet
697 * begun, we need to start it.
698 * next, we wait for the play buffer to drain
699 * finally, we stop the dma.
701 * called from: dsp_close, not valid for record channels.
705 chn_flush(struct pcm_channel
*c
)
707 int ret
, count
, resid
, resid_p
;
708 struct snd_dbuf
*b
= c
->bufhard
;
709 struct snd_dbuf
*bs
= c
->bufsoft
;
712 KASSERT(c
->direction
== PCMDIR_PLAY
, ("chn_flush on bad channel"));
713 DEB(kprintf("chn_flush: c->flags 0x%08x\n", c
->flags
));
715 /* if we haven't yet started and nothing is buffered, else start*/
716 if (!(c
->flags
& CHN_F_TRIGGERED
)) {
717 if (sndbuf_getready(bs
) > 0) {
718 ret
= chn_start(c
, 1);
726 c
->flags
|= CHN_F_CLOSING
;
727 resid
= sndbuf_getready(bs
) + sndbuf_getready(b
);
731 while ((count
> 0) && (resid
> sndbuf_getsize(b
)) && (ret
== 0)) {
732 /* still pending output data. */
733 ret
= chn_sleep(c
, "pcmflu", hz
/ 10);
734 if (ret
== EWOULDBLOCK
)
737 resid
= sndbuf_getready(bs
) + sndbuf_getready(b
);
738 if (resid
== resid_p
)
741 DEB(printf("chn_flush: buffer length increasind %d -> %d\n", resid_p
, resid
));
746 DEB(kprintf("chn_flush: timeout, hw %d, sw %d\n",
747 sndbuf_getready(b
), sndbuf_getready(bs
)));
749 c
->flags
&= ~CHN_F_TRIGGERED
;
750 /* kill the channel */
751 chn_trigger(c
, PCMTRIG_ABORT
);
754 c
->flags
&= ~CHN_F_CLOSING
;
759 fmtvalid(u_int32_t fmt
, u_int32_t
*fmtlist
)
763 for (i
= 0; fmtlist
[i
]; i
++)
764 if (fmt
== fmtlist
[i
])
770 chn_reset(struct pcm_channel
*c
, u_int32_t fmt
)
775 c
->flags
&= CHN_F_RESET
;
779 r
= CHANNEL_RESET(c
->methods
, c
->devinfo
);
782 hwspd
= DSP_DEFAULT_SPEED
;
783 /* only do this on a record channel until feederbuilder works */
784 if (c
->direction
== PCMDIR_REC
)
785 RANGE(hwspd
, chn_getcaps(c
)->minspeed
, chn_getcaps(c
)->maxspeed
);
788 hwspd
= chn_getcaps(c
)->minspeed
;
792 r
= chn_setformat(c
, fmt
);
794 r
= chn_setspeed(c
, hwspd
);
797 r
= chn_setvolume(c
, 100, 100);
801 r
= chn_setblocksize(c
, 0, 0);
804 r
= CHANNEL_RESETDONE(c
->methods
, c
->devinfo
);
810 chn_init(struct pcm_channel
*c
, void *devinfo
, int dir
, int direction
)
812 struct feeder_class
*fc
;
813 struct snd_dbuf
*b
, *bs
;
816 chn_lockinit(c
, dir
);
824 b
= sndbuf_create(c
->dev
, c
->name
, "primary", c
);
827 bs
= sndbuf_create(c
->dev
, c
->name
, "secondary", c
);
834 fc
= feeder_getclass(NULL
);
837 if (chn_addfeeder(c
, fc
, NULL
))
841 * XXX - sndbuf_setup() & sndbuf_resize() expect to be called
842 * with the channel unlocked because they are also called
843 * from driver methods that don't know about locking
846 sndbuf_setup(bs
, NULL
, 0);
854 CHN_UNLOCK(c
); /* XXX - Unlock for CHANNEL_INIT() kmalloc() call */
855 c
->devinfo
= CHANNEL_INIT(c
->methods
, devinfo
, b
, c
, direction
);
857 if (c
->devinfo
== NULL
)
861 if ((sndbuf_getsize(b
) == 0) && ((c
->flags
& CHN_F_VIRTUAL
) == 0))
864 ret
= chn_setdir(c
, direction
);
868 ret
= sndbuf_setfmt(b
, AFMT_U8
);
872 ret
= sndbuf_setfmt(bs
, AFMT_U8
);
876 ret
= chn_setvolume(c
, 100, 100);
885 if (CHANNEL_FREE(c
->methods
, c
->devinfo
))
892 c
->flags
|= CHN_F_DEAD
;
902 chn_kill(struct pcm_channel
*c
)
904 struct snd_dbuf
*b
= c
->bufhard
;
905 struct snd_dbuf
*bs
= c
->bufsoft
;
907 if (c
->flags
& CHN_F_TRIGGERED
)
908 chn_trigger(c
, PCMTRIG_ABORT
);
909 while (chn_removefeeder(c
) == 0);
910 if (CHANNEL_FREE(c
->methods
, c
->devinfo
))
912 c
->flags
|= CHN_F_DEAD
;
920 chn_setdir(struct pcm_channel
*c
, int dir
)
923 struct snd_dbuf
*b
= c
->bufhard
;
929 r
= CHANNEL_SETDIR(c
->methods
, c
->devinfo
, c
->direction
);
931 if (!r
&& SND_DMA(b
))
932 sndbuf_dmasetdir(b
, c
->direction
);
938 chn_setvolume(struct pcm_channel
*c
, int left
, int right
)
941 /* should add a feeder for volume changing if channel returns -1 */
950 c
->volume
= left
| (right
<< 8);
955 chn_tryspeed(struct pcm_channel
*c
, int speed
)
957 struct pcm_feeder
*f
;
958 struct snd_dbuf
*b
= c
->bufhard
;
959 struct snd_dbuf
*bs
= c
->bufsoft
;
964 DEB(kprintf("setspeed, channel %s\n", c
->name
));
965 DEB(kprintf("want speed %d, ", speed
));
971 sndbuf_setspd(bs
, speed
);
972 RANGE(speed
, chn_getcaps(c
)->minspeed
, chn_getcaps(c
)->maxspeed
);
973 DEB(kprintf("try speed %d, ", speed
));
974 sndbuf_setspd(b
, CHANNEL_SETSPEED(c
->methods
, c
->devinfo
, speed
));
975 DEB(kprintf("got speed %d\n", sndbuf_getspd(b
)));
977 delta
= sndbuf_getspd(b
) - sndbuf_getspd(bs
);
981 c
->feederflags
&= ~(1 << FEEDER_RATE
);
983 * Used to be 500. It was too big!
986 c
->feederflags
|= 1 << FEEDER_RATE
;
988 sndbuf_setspd(bs
, sndbuf_getspd(b
));
990 r
= chn_buildfeeder(c
);
991 DEB(kprintf("r = %d\n", r
));
995 r
= chn_setblocksize(c
, 0, 0);
999 if (!(c
->feederflags
& (1 << FEEDER_RATE
)))
1003 f
= chn_findfeeder(c
, FEEDER_RATE
);
1004 DEB(kprintf("feedrate = %p\n", f
));
1008 x
= (c
->direction
== PCMDIR_REC
)? b
: bs
;
1009 r
= FEEDER_SET(f
, FEEDRATE_SRC
, sndbuf_getspd(x
));
1010 DEB(kprintf("feeder_set(FEEDRATE_SRC, %d) = %d\n", sndbuf_getspd(x
), r
));
1014 x
= (c
->direction
== PCMDIR_REC
)? bs
: b
;
1015 r
= FEEDER_SET(f
, FEEDRATE_DST
, sndbuf_getspd(x
));
1016 DEB(kprintf("feeder_set(FEEDRATE_DST, %d) = %d\n", sndbuf_getspd(x
), r
));
1019 r
= CHANNEL_SETFORMAT(c
->methods
, c
->devinfo
,
1022 sndbuf_setfmt(bs
, c
->format
);
1023 DEB(kprintf("setspeed done, r = %d\n", r
));
1030 chn_setspeed(struct pcm_channel
*c
, int speed
)
1032 int r
, oldspeed
= c
->speed
;
1034 r
= chn_tryspeed(c
, speed
);
1036 DEB(kprintf("Failed to set speed %d falling back to %d\n", speed
, oldspeed
));
1037 r
= chn_tryspeed(c
, oldspeed
);
1043 chn_tryformat(struct pcm_channel
*c
, u_int32_t fmt
)
1045 struct snd_dbuf
*b
= c
->bufhard
;
1046 struct snd_dbuf
*bs
= c
->bufsoft
;
1051 DEB(kprintf("want format %d\n", fmt
));
1053 r
= chn_buildfeeder(c
);
1055 sndbuf_setfmt(bs
, c
->format
);
1057 r
= CHANNEL_SETFORMAT(c
->methods
, c
->devinfo
, sndbuf_getfmt(b
));
1059 r
= chn_tryspeed(c
, c
->speed
);
1067 chn_setformat(struct pcm_channel
*c
, u_int32_t fmt
)
1069 u_int32_t oldfmt
= c
->format
;
1072 r
= chn_tryformat(c
, fmt
);
1074 DEB(kprintf("Format change %d failed, reverting to %d\n", fmt
, oldfmt
));
1075 chn_tryformat(c
, oldfmt
);
1081 * given a bufsz value, round it to a power of 2 in the min-max range
1082 * XXX only works if min and max are powers of 2
1085 round_bufsz(int bufsz
, int min
, int max
)
1089 KASSERT((min
& (min
-1)) == 0, ("min %d must be power of 2\n", min
));
1090 KASSERT((max
& (max
-1)) == 0, ("max %d must be power of 2\n", max
));
1091 while (tmp
<= bufsz
)
1100 * set the channel's blocksize both for soft and hard buffers.
1102 * blksz should be a power of 2 between 2**4 and 2**16 -- it is useful
1103 * that it has the same value for both bufsoft and bufhard.
1104 * blksz == -1 computes values according to a target irq rate.
1105 * blksz == 0 reuses previous values if available, otherwise
1108 * blkcnt is set by the user, between 2 and (2**17)/blksz for bufsoft,
1109 * but should be a power of 2 for bufhard to simplify life to low
1111 * Note, for the rec channel a large blkcnt is ok,
1112 * but for the play channel we want blksz as small as possible to keep
1113 * the delay small, because routines in the write path always try to
1114 * keep bufhard full.
1116 * Unless we have good reason to, use the values suggested by the caller.
1119 chn_setblocksize(struct pcm_channel
*c
, int blkcnt
, int blksz
)
1121 struct snd_dbuf
*b
= c
->bufhard
;
1122 struct snd_dbuf
*bs
= c
->bufsoft
;
1123 int irqhz
, ret
, maxsz
, maxsize
, reqblksz
;
1126 if (!CANCHANGE(c
) || (c
->flags
& CHN_F_MAPPED
)) {
1127 KASSERT(sndbuf_getsize(bs
) == 0 ||
1128 sndbuf_getsize(bs
) >= sndbuf_getsize(b
),
1129 ("%s(%s): bufsoft size %d < bufhard size %d", __func__
,
1130 c
->name
, sndbuf_getsize(bs
), sndbuf_getsize(b
)));
1133 c
->flags
|= CHN_F_SETBLOCKSIZE
;
1136 DEB(kprintf("%s(%d, %d)\n", __func__
, blkcnt
, blksz
));
1137 if (blksz
== 0 || blksz
== -1) { /* let the driver choose values */
1138 if (blksz
== -1) /* delete previous values */
1139 c
->flags
&= ~CHN_F_HAS_SIZE
;
1140 if (!(c
->flags
& CHN_F_HAS_SIZE
)) { /* no previous value */
1142 * compute a base blksz according to the target irq
1143 * rate, then round to a suitable power of 2
1144 * in the range 16.. 2^17/2.
1145 * Finally compute a suitable blkcnt.
1147 blksz
= round_bufsz( (sndbuf_getbps(bs
) *
1148 sndbuf_getspd(bs
)) / chn_targetirqrate
,
1149 16, CHN_2NDBUFMAXSIZE
/ 2);
1150 blkcnt
= CHN_2NDBUFMAXSIZE
/ blksz
;
1151 } else { /* use previously defined value */
1152 blkcnt
= sndbuf_getblkcnt(bs
);
1153 blksz
= sndbuf_getblksz(bs
);
1157 * use supplied values if reasonable. Note that here we
1158 * might have blksz which is not a power of 2 if the
1159 * ioctl() to compute it allows such values.
1162 if ((blksz
< 16) || (blkcnt
< 2) || (blkcnt
* blksz
> CHN_2NDBUFMAXSIZE
))
1165 c
->flags
|= CHN_F_HAS_SIZE
;
1169 if (reqblksz
< sndbuf_getbps(bs
))
1170 reqblksz
= sndbuf_getbps(bs
);
1171 if (reqblksz
% sndbuf_getbps(bs
))
1172 reqblksz
-= reqblksz
% sndbuf_getbps(bs
);
1174 /* adjust for different hw format/speed */
1176 * Now compute the approx irq rate for the given (soft) blksz,
1177 * reduce to the acceptable range and compute a corresponding blksz
1178 * for the hard buffer. Then set the channel's blocksize and
1179 * corresponding hardbuf value. The number of blocks used should
1180 * be set by the device-specific routine. In fact, even the
1181 * call to sndbuf_setblksz() should not be here! XXX
1184 irqhz
= (sndbuf_getbps(bs
) * sndbuf_getspd(bs
)) / blksz
;
1185 RANGE(irqhz
, 16, 512);
1187 maxsz
= sndbuf_getmaxsize(b
);
1188 if (maxsz
== 0) /* virtual channels don't appear to allocate bufhard */
1189 maxsz
= CHN_2NDBUFMAXSIZE
;
1190 blksz
= round_bufsz( (sndbuf_getbps(b
) * sndbuf_getspd(b
)) / irqhz
,
1193 /* Increase the size of bufsoft if before increasing bufhard. */
1194 maxsize
= sndbuf_getsize(b
);
1195 if (sndbuf_getsize(bs
) > maxsize
)
1196 maxsize
= sndbuf_getsize(bs
);
1197 if (reqblksz
* blkcnt
> maxsize
)
1198 maxsize
= reqblksz
* blkcnt
;
1199 if (sndbuf_getsize(bs
) != maxsize
|| sndbuf_getblksz(bs
) != reqblksz
) {
1200 ret
= sndbuf_remalloc(bs
, maxsize
/reqblksz
, reqblksz
);
1206 sndbuf_setblksz(b
, CHANNEL_SETBLOCKSIZE(c
->methods
, c
->devinfo
, blksz
));
1209 /* Decrease the size of bufsoft after decreasing bufhard. */
1210 maxsize
= sndbuf_getsize(b
);
1211 if (reqblksz
* blkcnt
> maxsize
)
1212 maxsize
= reqblksz
* blkcnt
;
1213 if (maxsize
> sndbuf_getsize(bs
))
1214 kprintf("Danger! %s bufsoft size increasing from %d to %d after CHANNEL_SETBLOCKSIZE()\n",
1215 c
->name
, sndbuf_getsize(bs
), maxsize
);
1216 if (sndbuf_getsize(bs
) != maxsize
|| sndbuf_getblksz(bs
) != reqblksz
) {
1217 ret
= sndbuf_remalloc(bs
, maxsize
/reqblksz
, reqblksz
);
1224 KASSERT(sndbuf_getsize(bs
) == 0 ||
1225 sndbuf_getsize(bs
) >= sndbuf_getsize(b
),
1226 ("%s(%s): bufsoft size %d < bufhard size %d, reqblksz=%d blksz=%d maxsize=%d blkcnt=%d",
1227 __func__
, c
->name
, sndbuf_getsize(bs
), sndbuf_getsize(b
), reqblksz
,
1228 blksz
, maxsize
, blkcnt
));
1230 c
->flags
&= ~CHN_F_SETBLOCKSIZE
;
1233 static uint32_t kk
= 0;
1234 printf("%u: b %d/%d/%d : (%d)%d/0x%0x | bs %d/%d/%d : (%d)%d/0x%0x\n", ++kk
,
1235 sndbuf_getsize(b
), sndbuf_getblksz(b
), sndbuf_getblkcnt(b
),
1237 sndbuf_getspd(b
), sndbuf_getfmt(b
),
1238 sndbuf_getsize(bs
), sndbuf_getblksz(bs
), sndbuf_getblkcnt(bs
),
1240 sndbuf_getspd(bs
), sndbuf_getfmt(bs
));
1241 if (sndbuf_getsize(b
) % sndbuf_getbps(b
) ||
1242 sndbuf_getblksz(b
) % sndbuf_getbps(b
) ||
1243 sndbuf_getsize(bs
) % sndbuf_getbps(bs
) ||
1244 sndbuf_getblksz(b
) % sndbuf_getbps(b
)) {
1245 printf("%u: bps/blksz alignment screwed!\n", kk
);
1253 chn_trigger(struct pcm_channel
*c
, int go
)
1256 struct snd_dbuf
*b
= c
->bufhard
;
1262 if (SND_DMA(b
) && (go
== PCMTRIG_EMLDMAWR
|| go
== PCMTRIG_EMLDMARD
))
1263 sndbuf_dmabounce(b
);
1265 ret
= CHANNEL_TRIGGER(c
->methods
, c
->devinfo
, go
);
1271 chn_getptr(struct pcm_channel
*c
)
1275 int a
= (1 << c
->align
) - 1;
1278 hwptr
= (c
->flags
& CHN_F_TRIGGERED
)? CHANNEL_GETPTR(c
->methods
, c
->devinfo
) : 0;
1279 /* don't allow unaligned values in the hwa ptr */
1281 hwptr
&= ~a
; /* Apply channel align mask */
1283 hwptr
&= DMA_ALIGN_MASK
; /* Apply DMA align mask */
1289 hwptr
= (c
->flags
& CHN_F_TRIGGERED
)? CHANNEL_GETPTR(c
->methods
, c
->devinfo
) : 0;
1290 return (hwptr
- (hwptr
% sndbuf_getbps(c
->bufhard
)));
1293 struct pcmchan_caps
*
1294 chn_getcaps(struct pcm_channel
*c
)
1297 return CHANNEL_GETCAPS(c
->methods
, c
->devinfo
);
1301 chn_getformats(struct pcm_channel
*c
)
1303 u_int32_t
*fmtlist
, fmts
;
1306 fmtlist
= chn_getcaps(c
)->fmtlist
;
1308 for (i
= 0; fmtlist
[i
]; i
++)
1311 /* report software-supported formats */
1312 if (report_soft_formats
)
1313 fmts
|= AFMT_MU_LAW
|AFMT_A_LAW
|AFMT_U32_LE
|AFMT_U32_BE
|
1314 AFMT_S32_LE
|AFMT_S32_BE
|AFMT_U24_LE
|AFMT_U24_BE
|
1315 AFMT_S24_LE
|AFMT_S24_BE
|AFMT_U16_LE
|AFMT_U16_BE
|
1316 AFMT_S16_LE
|AFMT_S16_BE
|AFMT_U8
|AFMT_S8
;
1322 chn_buildfeeder(struct pcm_channel
*c
)
1324 struct feeder_class
*fc
;
1325 struct pcm_feederdesc desc
;
1326 u_int32_t tmp
[2], type
, flags
, hwfmt
, *fmtlist
;
1330 while (chn_removefeeder(c
) == 0);
1331 KASSERT((c
->feeder
== NULL
), ("feeder chain not empty"));
1333 c
->align
= sndbuf_getalign(c
->bufsoft
);
1335 if (SLIST_EMPTY(&c
->children
)) {
1336 fc
= feeder_getclass(NULL
);
1337 KASSERT(fc
!= NULL
, ("can't find root feeder"));
1339 err
= chn_addfeeder(c
, fc
, NULL
);
1341 DEB(kprintf("can't add root feeder, err %d\n", err
));
1345 c
->feeder
->desc
->out
= c
->format
;
1347 if (c
->flags
& CHN_F_HAS_VCHAN
) {
1348 desc
.type
= FEEDER_MIXER
;
1351 DEB(printf("can't decide which feeder type to use!\n"));
1354 desc
.out
= c
->format
;
1356 fc
= feeder_getclass(&desc
);
1358 DEB(kprintf("can't find vchan feeder\n"));
1363 err
= chn_addfeeder(c
, fc
, &desc
);
1365 DEB(kprintf("can't add vchan feeder, err %d\n", err
));
1370 c
->feederflags
&= ~(1 << FEEDER_VOLUME
);
1371 if (c
->direction
== PCMDIR_PLAY
&&
1372 !(c
->flags
& CHN_F_VIRTUAL
) &&
1373 c
->parentsnddev
&& (c
->parentsnddev
->flags
& SD_F_SOFTPCMVOL
) &&
1374 c
->parentsnddev
->mixer_dev
)
1375 c
->feederflags
|= 1 << FEEDER_VOLUME
;
1376 flags
= c
->feederflags
;
1377 fmtlist
= chn_getcaps(c
)->fmtlist
;
1379 DEB(kprintf("feederflags %x\n", flags
));
1381 for (type
= FEEDER_RATE
; type
<= FEEDER_LAST
; type
++) {
1382 if (flags
& (1 << type
)) {
1387 DEB(kprintf("find feeder type %d, ", type
));
1388 fc
= feeder_getclass(&desc
);
1389 DEB(kprintf("got %p\n", fc
));
1391 DEB(kprintf("can't find required feeder type %d\n", type
));
1396 DEB(kprintf("build fmtchain from 0x%08x to 0x%08x: ", c
->feeder
->desc
->out
, fc
->desc
->in
));
1397 tmp
[0] = fc
->desc
->in
;
1399 if (chn_fmtchain(c
, tmp
) == 0) {
1400 DEB(printf("failed\n"));
1404 DEB(printf("ok\n"));
1406 err
= chn_addfeeder(c
, fc
, fc
->desc
);
1408 DEB(kprintf("can't add feeder %p, output 0x%x, err %d\n", fc
, fc
->desc
->out
, err
));
1412 DEB(kprintf("added feeder %p, output 0x%x\n", fc
, c
->feeder
->desc
->out
));
1416 if (c
->direction
== PCMDIR_REC
) {
1419 hwfmt
= chn_fmtchain(c
, tmp
);
1421 hwfmt
= chn_fmtchain(c
, fmtlist
);
1423 if (hwfmt
== 0 || !fmtvalid(hwfmt
, fmtlist
)) {
1424 DEB(printf("Invalid hardware format: 0x%08x\n", hwfmt
));
1428 sndbuf_setfmt(c
->bufhard
, hwfmt
);
1430 if ((flags
& (1 << FEEDER_VOLUME
))) {
1431 struct dev_ioctl_args map
;
1432 u_int32_t parent
= SOUND_MIXER_NONE
;
1433 int vol
, left
, right
;
1435 vol
= 100 | (100 << 8);
1439 * XXX This is ugly! The way mixer subs being so secretive
1440 * about its own internals force us to use this silly
1443 map
.a_head
.a_dev
= c
->parentsnddev
->mixer_dev
;
1444 map
.a_cmd
= MIXER_READ(SOUND_MIXER_PCM
);
1445 map
.a_data
= (caddr_t
)&vol
;
1448 map
.a_sysmsg
= NULL
;
1449 if (mixer_ioctl(&map
) != 0)
1450 device_printf(c
->dev
, "Soft PCM Volume: Failed to read default value\n");
1452 right
= (vol
>> 8) & 0x7f;
1453 if (c
->parentsnddev
!= NULL
&&
1454 c
->parentsnddev
->mixer_dev
!= NULL
&&
1455 c
->parentsnddev
->mixer_dev
->si_drv1
!= NULL
)
1456 parent
= mix_getparent(
1457 c
->parentsnddev
->mixer_dev
->si_drv1
,
1459 if (parent
!= SOUND_MIXER_NONE
) {
1460 vol
= 100 | (100 << 8);
1461 map
.a_head
.a_dev
= c
->parentsnddev
->mixer_dev
;
1462 map
.a_cmd
= MIXER_READ(parent
);
1463 map
.a_data
= (caddr_t
)&vol
;
1466 if (mixer_ioctl(&map
) != 0)
1467 device_printf(c
->dev
, "Soft Volume: Failed to read parent default value\n");
1468 left
= (left
* (vol
& 0x7f)) / 100;
1469 right
= (right
* ((vol
>> 8) & 0x7f)) / 100;
1473 chn_setvolume(c
, left
, right
);
1480 chn_notify(struct pcm_channel
*c
, u_int32_t flags
)
1482 struct pcmchan_children
*pce
;
1483 struct pcm_channel
*child
;
1488 if (SLIST_EMPTY(&c
->children
)) {
1493 run
= (c
->flags
& CHN_F_TRIGGERED
)? 1 : 0;
1495 * if the hwchan is running, we can't change its rate, format or
1499 flags
&= CHN_N_VOLUME
| CHN_N_TRIGGER
;
1501 if (flags
& CHN_N_RATE
) {
1503 * we could do something here, like scan children and decide on
1504 * the most appropriate rate to mix at, but we don't for now
1507 if (flags
& CHN_N_FORMAT
) {
1509 * we could do something here, like scan children and decide on
1510 * the most appropriate mixer feeder to use, but we don't for now
1513 if (flags
& CHN_N_VOLUME
) {
1515 * we could do something here but we don't for now
1518 if (flags
& CHN_N_BLOCKSIZE
) {
1521 * scan the children, find the lowest blocksize and use that
1522 * for the hard blocksize
1524 blksz
= sndbuf_getmaxsize(c
->bufhard
) / 2;
1525 SLIST_FOREACH(pce
, &c
->children
, link
) {
1526 child
= pce
->channel
;
1528 if (sndbuf_getblksz(child
->bufhard
) < blksz
)
1529 blksz
= sndbuf_getblksz(child
->bufhard
);
1532 chn_setblocksize(c
, 2, blksz
);
1534 if (flags
& CHN_N_TRIGGER
) {
1537 * scan the children, and figure out if any are running
1538 * if so, we need to be running, otherwise we need to be stopped
1539 * if we aren't in our target sstate, move to it
1542 SLIST_FOREACH(pce
, &c
->children
, link
) {
1543 child
= pce
->channel
;
1545 if (child
->flags
& CHN_F_TRIGGERED
)
1559 chn_lock(struct pcm_channel
*c
)
1565 chn_unlock(struct pcm_channel
*c
)