Merge branch 'vendor/BMAKE'
[dragonfly.git] / sys / dev / sound / pcm / channel.c
1 /*-
2  * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
3  * Portions Copyright by Luigi Rizzo - 1997-99
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
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.
14  *
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
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD: src/sys/dev/sound/pcm/channel.c,v 1.99.2.5 2007/05/13 20:53:39 ariff Exp $
28  */
29
30 #include <dev/sound/pcm/sound.h>
31 #include <sys/vnode.h>          /* IO_NDELAY */
32
33 #include "feeder_if.h"
34
35 SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pcm/channel.c,v 1.15 2008/01/05 13:34:22 corecode Exp $");
36
37 #define MIN_CHUNK_SIZE          256     /* for uiomove etc. */
38 #if 0
39 #define DMA_ALIGN_THRESHOLD     4
40 #define DMA_ALIGN_MASK          (~(DMA_ALIGN_THRESHOLD - 1))
41 #endif
42
43 #define CANCHANGE(c) (!(c->flags & CHN_F_TRIGGERED))
44
45 /*
46 #define DEB(x) x
47 */
48
49 static int chn_targetirqrate = 32;
50 TUNABLE_INT("hw.snd.targetirqrate", &chn_targetirqrate);
51
52 static int
53 sysctl_hw_snd_targetirqrate(SYSCTL_HANDLER_ARGS)
54 {
55         int err, val;
56
57         val = chn_targetirqrate;
58         err = sysctl_handle_int(oidp, &val, sizeof(val), req);
59         if (val < 16 || val > 512)
60                 err = EINVAL;
61         else
62                 chn_targetirqrate = val;
63
64         return err;
65 }
66 SYSCTL_PROC(_hw_snd, OID_AUTO, targetirqrate, CTLTYPE_INT | CTLFLAG_RW,
67         0, sizeof(int), sysctl_hw_snd_targetirqrate, "I", "");
68 static int report_soft_formats = 1;
69 SYSCTL_INT(_hw_snd, OID_AUTO, report_soft_formats, CTLFLAG_RW,
70         &report_soft_formats, 1, "report software-emulated formats");
71
72 static int chn_buildfeeder(struct pcm_channel *c);
73
74 static void
75 chn_lockinit(struct pcm_channel *c, int dir)
76 {
77         switch(dir) {
78         case PCMDIR_PLAY:
79                 c->lock = snd_mtxcreate(c->name, "pcm play channel");
80                 break;
81         case PCMDIR_REC:
82                 c->lock = snd_mtxcreate(c->name, "pcm record channel");
83                 break;
84         case PCMDIR_VIRTUAL:
85                 c->lock = snd_mtxcreate(c->name, "pcm virtual play channel");
86                 break;
87         case 0:
88                 c->lock = snd_mtxcreate(c->name, "pcm fake channel");
89                 break;
90         }
91 }
92
93 static void
94 chn_lockdestroy(struct pcm_channel *c)
95 {
96         snd_mtxfree(c->lock);
97 }
98
99 static int
100 chn_polltrigger(struct pcm_channel *c)
101 {
102         struct snd_dbuf *bs = c->bufsoft;
103         unsigned amt, lim;
104
105         CHN_LOCKASSERT(c);
106         if (c->flags & CHN_F_MAPPED) {
107                 if (sndbuf_getprevblocks(bs) == 0)
108                         return 1;
109                 else
110                         return (sndbuf_getblocks(bs) > sndbuf_getprevblocks(bs))? 1 : 0;
111         } else {
112                 amt = (c->direction == PCMDIR_PLAY)? sndbuf_getfree(bs) : sndbuf_getready(bs);
113 #if 0
114                 lim = (c->flags & CHN_F_HAS_SIZE)? sndbuf_getblksz(bs) : 1;
115 #endif
116                 lim = 1;
117                 return (amt >= lim)? 1 : 0;
118         }
119         return 0;
120 }
121
122 static int
123 chn_pollreset(struct pcm_channel *c)
124 {
125         struct snd_dbuf *bs = c->bufsoft;
126
127         CHN_LOCKASSERT(c);
128         sndbuf_updateprevtotal(bs);
129         return 1;
130 }
131
132 static void
133 chn_wakeup(struct pcm_channel *c)
134 {
135         struct snd_dbuf *bs = c->bufsoft;
136         struct pcmchan_children *pce;
137
138         CHN_LOCKASSERT(c);
139         if (SLIST_EMPTY(&c->children)) {
140                 /*if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c))*/
141                 if (SLIST_FIRST(&sndbuf_getkq(bs)->ki_note) && chn_polltrigger(c)) {
142                         /*
143                          * XXX
144                          *
145                          * We would call KNOTE() here, but as we
146                          * are in interrupt context, we'd have to
147                          * acquire the MP lock before.
148                          * Instead, we'll queue a task in a software
149                          * interrupt, which will run with the MP lock
150                          * held.
151                          *
152                          * buffer.c:sndbuf_kqtask will then call
153                          * KNOTE() from safer context.
154                          */
155                         taskqueue_enqueue(taskqueue_swi, &bs->kqtask);
156                 }
157         } else {
158                 SLIST_FOREACH(pce, &c->children, link) {
159                         CHN_LOCK(pce->channel);
160                         chn_wakeup(pce->channel);
161                         CHN_UNLOCK(pce->channel);
162                 }
163         }
164
165         wakeup(bs);
166 }
167
168 static int
169 chn_sleep(struct pcm_channel *c, char *str, int timeout)
170 {
171         struct snd_dbuf *bs = c->bufsoft;
172         int ret;
173
174         CHN_LOCKASSERT(c);
175 #ifdef USING_MUTEX
176         ret = snd_mtxsleep(bs, c->lock, PCATCH, str, timeout);
177 #else
178         ret = tsleep(bs, PRIBIO | PCATCH, str, timeout);
179 #endif
180
181         return ret;
182 }
183
184 /*
185  * chn_dmaupdate() tracks the status of a dma transfer,
186  * updating pointers.
187  */
188
189 static unsigned int
190 chn_dmaupdate(struct pcm_channel *c)
191 {
192         struct snd_dbuf *b = c->bufhard;
193         unsigned int delta, old, hwptr, amt;
194
195         KASSERT(sndbuf_getsize(b) > 0, ("bufsize == 0"));
196         CHN_LOCKASSERT(c);
197
198         old = sndbuf_gethwptr(b);
199         hwptr = chn_getptr(c);
200         delta = (sndbuf_getsize(b) + hwptr - old) % sndbuf_getsize(b);
201         sndbuf_sethwptr(b, hwptr);
202
203         DEB(
204         if (delta >= ((sndbuf_getsize(b) * 15) / 16)) {
205                 if (!(c->flags & (CHN_F_CLOSING | CHN_F_ABORTING)))
206                         device_printf(c->dev, "hwptr went backwards %d -> %d\n", old, hwptr);
207         }
208         );
209
210         if (c->direction == PCMDIR_PLAY) {
211                 amt = MIN(delta, sndbuf_getready(b));
212                 if (amt > 0)
213                         sndbuf_dispose(b, NULL, amt);
214         } else {
215                 amt = MIN(delta, sndbuf_getfree(b));
216                 if (amt > 0)
217                        sndbuf_acquire(b, NULL, amt);
218         }
219
220         return delta;
221 }
222
223 void
224 chn_wrupdate(struct pcm_channel *c)
225 {
226         int ret;
227
228         CHN_LOCKASSERT(c);
229         KASSERT(c->direction == PCMDIR_PLAY, ("chn_wrupdate on bad channel"));
230
231         if ((c->flags & (CHN_F_MAPPED | CHN_F_VIRTUAL)) || !(c->flags & CHN_F_TRIGGERED))
232                 return;
233         chn_dmaupdate(c);
234         if (sndbuf_getsize(c->bufsoft) == 0) {
235                 DEB(kprintf("chn_wrupdate: avoid calling chn_wrfeed without any data in soft buffer");)
236                 return;
237         }
238         ret = chn_wrfeed(c);
239         /* tell the driver we've updated the primary buffer */
240         chn_trigger(c, PCMTRIG_EMLDMAWR);
241         DEB(if (ret)
242                 kprintf("chn_wrupdate: chn_wrfeed returned %d\n", ret);)
243
244 }
245
246 int
247 chn_wrfeed(struct pcm_channel *c)
248 {
249         struct snd_dbuf *b = c->bufhard;
250         struct snd_dbuf *bs = c->bufsoft;
251         unsigned int ret, amt;
252
253         CHN_LOCKASSERT(c);
254 #if 0
255         DEB(
256         if (c->flags & CHN_F_CLOSING) {
257                 sndbuf_dump(b, "b", 0x02);
258                 sndbuf_dump(bs, "bs", 0x02);
259         })
260 #endif
261
262         if (c->flags & CHN_F_MAPPED)
263                 sndbuf_acquire(bs, NULL, sndbuf_getfree(bs));
264
265         amt = sndbuf_getfree(b);
266         KASSERT(amt <= sndbuf_getsize(bs),
267             ("%s(%s): amt %d > source size %d, flags 0x%x", __func__, c->name,
268            amt, sndbuf_getsize(bs), c->flags));
269
270         ret = (amt > 0) ? sndbuf_feed(bs, b, c, c->feeder, amt) : ENOSPC;
271         /*
272          * Possible xruns. There should be no empty space left in buffer.
273          */
274         if (sndbuf_getfree(b) > 0)
275                 c->xruns++;
276
277         if (ret == 0 && sndbuf_getfree(b) < amt)
278                 chn_wakeup(c);
279
280         return ret;
281 }
282
283 static void
284 chn_wrintr(struct pcm_channel *c)
285 {
286         int ret;
287
288         CHN_LOCKASSERT(c);
289         /* update pointers in primary buffer */
290         chn_dmaupdate(c);
291         /* ...and feed from secondary to primary */
292         if (sndbuf_getsize(c->bufsoft) == 0) {
293                 DEB(kprintf("chn_wrintr: avoid calling chn_wrfeed without any data in soft buffer");)
294                 return;
295         }
296         ret = chn_wrfeed(c);
297         /* tell the driver we've updated the primary buffer */
298         chn_trigger(c, PCMTRIG_EMLDMAWR);
299         DEB(if (ret)
300                 kprintf("chn_wrintr: chn_wrfeed returned %d\n", ret);)
301 }
302
303 /*
304  * user write routine - uiomove data into secondary buffer, trigger if necessary
305  * if blocking, sleep, rinse and repeat.
306  *
307  * called externally, so must handle locking
308  */
309
310 int
311 chn_write(struct pcm_channel *c, struct uio *buf, int ioflags)
312 {
313         int ret, timeout, newsize, count, sz;
314         int nbio;
315         struct snd_dbuf *bs = c->bufsoft;
316         void *off;
317         int t, x,togo,p;
318
319         CHN_LOCKASSERT(c);
320         /*
321          * XXX Certain applications attempt to write larger size
322          * of pcm data than c->blocksize2nd without blocking,
323          * resulting partial write. Expand the block size so that
324          * the write operation avoids blocking.
325          */
326         nbio = (c->flags & CHN_F_NBIO) || (ioflags & IO_NDELAY);
327         if (nbio && buf->uio_resid > (size_t)sndbuf_getblksz(bs)) {
328                 DEB(device_printf(c->dev, "broken app, nbio and tried to write %ld bytes with fragsz %d\n",
329                         buf->uio_resid, sndbuf_getblksz(bs)));
330                 newsize = 16;
331                 while (newsize < (int)szmin(buf->uio_resid, CHN_2NDBUFMAXSIZE / 2))
332                         newsize <<= 1;
333                 chn_setblocksize(c, sndbuf_getblkcnt(bs), newsize);
334                 DEB(device_printf(c->dev, "frags reset to %d x %d\n", sndbuf_getblkcnt(bs), sndbuf_getblksz(bs)));
335         }
336
337         ret = 0;
338         count = hz;
339         while (!ret && (buf->uio_resid > 0) && (count > 0)) {
340                 sz = sndbuf_getfree(bs);
341                 if (sz == 0) {
342                         if (nbio)
343                                 ret = EWOULDBLOCK;
344                         else {
345                                 timeout = (hz * sndbuf_getblksz(bs)) / (sndbuf_getspd(bs) * sndbuf_getbps(bs));
346                                 if (timeout < 1)
347                                         timeout = 1;
348                                 timeout = 1;
349                                 ret = chn_sleep(c, "pcmwr", timeout);
350                                 if (ret == EWOULDBLOCK) {
351                                         count -= timeout;
352                                         ret = 0;
353                                 } else if (ret == 0)
354                                         count = hz;
355                         }
356                 } else {
357                         sz = (int)szmin(sz, buf->uio_resid);
358                         KASSERT(sz > 0, ("confusion in chn_write"));
359                         /* kprintf("sz: %d\n", sz); */
360
361                         /*
362                          * The following assumes that the free space in
363                          * the buffer can never be less around the
364                          * unlock-uiomove-lock sequence.
365                          */
366                         togo = sz;
367                         while (ret == 0 && togo> 0) {
368                                 p = sndbuf_getfreeptr(bs);
369                                 t = MIN(togo, sndbuf_getsize(bs) - p);
370                                 off = sndbuf_getbufofs(bs, p);
371                                 CHN_UNLOCK(c);
372                                 ret = uiomove(off, t, buf);
373                                 CHN_LOCK(c);
374                                 togo -= t;
375                                 x = sndbuf_acquire(bs, NULL, t);
376                         }
377                         ret = 0;
378                         if (ret == 0 && !(c->flags & CHN_F_TRIGGERED))
379                                 chn_start(c, 0);
380                 }
381         }
382         /* kprintf("ret: %d left: %d\n", ret, buf->uio_resid); */
383
384         if (count <= 0) {
385                 c->flags |= CHN_F_DEAD;
386                 kprintf("%s: play interrupt timeout, channel dead\n", c->name);
387         }
388
389         return ret;
390 }
391
392 #if 0
393 static int
394 chn_rddump(struct pcm_channel *c, unsigned int cnt)
395 {
396         struct snd_dbuf *b = c->bufhard;
397
398         CHN_LOCKASSERT(c);
399 #if 0
400         static uint32_t kk = 0;
401         printf("%u: dumping %d bytes\n", ++kk, cnt);
402 #endif
403         c->xruns++;
404         sndbuf_setxrun(b, sndbuf_getxrun(b) + cnt);
405         return sndbuf_dispose(b, NULL, cnt);
406 }
407 #endif
408
409 /*
410  * Feed new data from the read buffer. Can be called in the bottom half.
411  */
412 int
413 chn_rdfeed(struct pcm_channel *c)
414 {
415         struct snd_dbuf *b = c->bufhard;
416         struct snd_dbuf *bs = c->bufsoft;
417         unsigned int ret, amt;
418
419         CHN_LOCKASSERT(c);
420         DEB(
421         if (c->flags & CHN_F_CLOSING) {
422                 sndbuf_dump(b, "b", 0x02);
423                 sndbuf_dump(bs, "bs", 0x02);
424         })
425
426 #if 0
427         amt = sndbuf_getready(b);
428         if (sndbuf_getfree(bs) < amt) {
429                 c->xruns++;
430                 amt = sndbuf_getfree(bs);
431         }
432 #endif
433         amt = sndbuf_getfree(bs);
434         ret = (amt > 0)? sndbuf_feed(b, bs, c, c->feeder, amt) : 0;
435
436         amt = sndbuf_getready(b);
437         if (amt > 0) {
438                 c->xruns++;
439                 sndbuf_dispose(b, NULL, amt);
440         }
441
442         chn_wakeup(c);
443
444         return ret;
445 }
446
447 void
448 chn_rdupdate(struct pcm_channel *c)
449 {
450         int ret;
451
452         CHN_LOCKASSERT(c);
453         KASSERT(c->direction == PCMDIR_REC, ("chn_rdupdate on bad channel"));
454
455         if ((c->flags & CHN_F_MAPPED) || !(c->flags & CHN_F_TRIGGERED))
456                 return;
457         chn_trigger(c, PCMTRIG_EMLDMARD);
458         chn_dmaupdate(c);
459         ret = chn_rdfeed(c);
460         DEB(if (ret)
461                 kprintf("chn_rdfeed: %d\n", ret);)
462 }
463
464 /* read interrupt routine. Must be called with interrupts blocked. */
465 static void
466 chn_rdintr(struct pcm_channel *c)
467 {
468         int ret;
469
470         CHN_LOCKASSERT(c);
471         /* tell the driver to update the primary buffer if non-dma */
472         chn_trigger(c, PCMTRIG_EMLDMARD);
473         /* update pointers in primary buffer */
474         chn_dmaupdate(c);
475         /* ...and feed from primary to secondary */
476         ret = chn_rdfeed(c);
477 }
478
479 /*
480  * user read routine - trigger if necessary, uiomove data from secondary buffer
481  * if blocking, sleep, rinse and repeat.
482  *
483  * called externally, so must handle locking
484  */
485
486 int
487 chn_read(struct pcm_channel *c, struct uio *buf, int ioflags)
488 {
489         int             ret, timeout, sz, count;
490         int nbio;
491         struct snd_dbuf       *bs = c->bufsoft;
492         void *off;
493         int t, x,togo,p;
494
495         CHN_LOCKASSERT(c);
496         nbio = (c->flags & CHN_F_NBIO) || (ioflags & IO_NDELAY);
497         if (!(c->flags & CHN_F_TRIGGERED))
498                 chn_start(c, 0);
499
500         ret = 0;
501         count = hz;
502         while (!ret && (buf->uio_resid > 0) && (count > 0)) {
503                 sz = (int)szmin(buf->uio_resid, sndbuf_getready(bs));
504
505                 if (sz > 0) {
506                         /*
507                          * The following assumes that the free space in
508                          * the buffer can never be less around the
509                          * unlock-uiomove-lock sequence.
510                          */
511                         togo = sz;
512                         while (ret == 0 && togo> 0) {
513                                 p = sndbuf_getreadyptr(bs);
514                                 t = MIN(togo, sndbuf_getsize(bs) - p);
515                                 off = sndbuf_getbufofs(bs, p);
516                                 CHN_UNLOCK(c);
517                                 ret = uiomove(off, t, buf);
518                                 CHN_LOCK(c);
519                                 togo -= t;
520                                 x = sndbuf_dispose(bs, NULL, t);
521                         }
522                         ret = 0;
523                 } else {
524                         if (nbio) {
525                                 ret = EWOULDBLOCK;
526                         } else {
527                                 timeout = (hz * sndbuf_getblksz(bs)) / (sndbuf_getspd(bs) * sndbuf_getbps(bs));
528                                 if (timeout < 1)
529                                         timeout = 1;
530                                 ret = chn_sleep(c, "pcmrd", timeout);
531                                 if (ret == EWOULDBLOCK) {
532                                         count -= timeout;
533                                         ret = 0;
534                                 } else {
535                                         count = hz;
536                                 }
537
538                         }
539                 }
540         }
541
542         if (count <= 0) {
543                 c->flags |= CHN_F_DEAD;
544                 kprintf("%s: record interrupt timeout, channel dead\n", c->name);
545         }
546
547         return ret;
548 }
549
550 void
551 chn_intr(struct pcm_channel *c)
552 {
553         CHN_LOCK(c);
554         c->interrupts++;
555         if (c->direction == PCMDIR_PLAY)
556                 chn_wrintr(c);
557         else
558                 chn_rdintr(c);
559         CHN_UNLOCK(c);
560 }
561
562 u_int32_t
563 chn_start(struct pcm_channel *c, int force)
564 {
565         u_int32_t i, j;
566         struct snd_dbuf *b = c->bufhard;
567         struct snd_dbuf *bs = c->bufsoft;
568
569         CHN_LOCKASSERT(c);
570         /* if we're running, or if we're prevented from triggering, bail */
571         if ((c->flags & CHN_F_TRIGGERED) || ((c->flags & CHN_F_NOTRIGGER) && !force))
572                 return EINVAL;
573
574         i = (c->direction == PCMDIR_PLAY)? sndbuf_getready(bs) : sndbuf_getfree(bs);
575         j = (c->direction == PCMDIR_PLAY)? sndbuf_getfree(b) : sndbuf_getready(b);
576         if (force || (i >= j)) {
577                 c->flags |= CHN_F_TRIGGERED;
578                 /*
579                  * if we're starting because a vchan started, don't feed any data
580                  * or it becomes impossible to start vchans synchronised with the
581                  * first one.  the hardbuf should be empty so we top it up with
582                  * silence to give it something to chew.  the real data will be
583                  * fed at the first irq.
584                  */
585                 if (c->direction == PCMDIR_PLAY) {
586                         /*
587                          * Reduce pops during playback startup.
588                          */
589                         sndbuf_fillsilence(b);
590                         if (SLIST_EMPTY(&c->children))
591                                 chn_wrfeed(c);
592                 }
593                 sndbuf_setrun(b, 1);
594                 c->xruns = 0;
595                 chn_trigger(c, PCMTRIG_START);
596                 return 0;
597         }
598
599         return 0;
600 }
601
602 void
603 chn_resetbuf(struct pcm_channel *c)
604 {
605         struct snd_dbuf *b = c->bufhard;
606         struct snd_dbuf *bs = c->bufsoft;
607
608         c->blocks = 0;
609         sndbuf_reset(b);
610         sndbuf_reset(bs);
611 }
612
613 /*
614  * chn_sync waits until the space in the given channel goes above
615  * a threshold. The threshold is checked against fl or rl respectively.
616  * Assume that the condition can become true, do not check here...
617  */
618 int
619 chn_sync(struct pcm_channel *c, int threshold)
620 {
621         u_long rdy;
622         int ret;
623         struct snd_dbuf *bs = c->bufsoft;
624
625         CHN_LOCKASSERT(c);
626
627         /* if we haven't yet started and nothing is buffered, else start*/
628         if (!(c->flags & CHN_F_TRIGGERED)) {
629                 if (sndbuf_getready(bs) > 0) {
630                         ret = chn_start(c, 1);
631                         if (ret)
632                                 return ret;
633                 } else {
634                         return 0;
635                 }
636         }
637
638         for (;;) {
639                 rdy = (c->direction == PCMDIR_PLAY)? sndbuf_getfree(bs) : sndbuf_getready(bs);
640                 if (rdy <= threshold) {
641                         ret = chn_sleep(c, "pcmsyn", 1);
642                         if (ret == ERESTART || ret == EINTR) {
643                                 DEB(kprintf("chn_sync: tsleep returns %d\n", ret));
644                                 return -1;
645                         }
646                 } else
647                         break;
648         }
649         return 0;
650 }
651
652 /* called externally, handle locking */
653 int
654 chn_poll(struct pcm_channel *c, int ev, struct thread *td)
655 {
656         int ret;
657
658         CHN_LOCKASSERT(c);
659         if (!(c->flags & CHN_F_MAPPED) && !(c->flags & CHN_F_TRIGGERED))
660                 chn_start(c, 1);
661         ret = 0;
662         if (chn_polltrigger(c) && chn_pollreset(c))
663                 ret = ev;
664         return ret;
665 }
666
667 /*
668  * chn_abort terminates a running dma transfer.  it may sleep up to 200ms.
669  * it returns the number of bytes that have not been transferred.
670  *
671  * called from: dsp_close, dsp_ioctl, with channel locked
672  */
673 int
674 chn_abort(struct pcm_channel *c)
675 {
676         int missing = 0;
677         struct snd_dbuf *b = c->bufhard;
678         struct snd_dbuf *bs = c->bufsoft;
679
680         CHN_LOCKASSERT(c);
681         if (!(c->flags & CHN_F_TRIGGERED))
682                 return 0;
683         c->flags |= CHN_F_ABORTING;
684
685         c->flags &= ~CHN_F_TRIGGERED;
686         /* kill the channel */
687         chn_trigger(c, PCMTRIG_ABORT);
688         sndbuf_setrun(b, 0);
689         if (!(c->flags & CHN_F_VIRTUAL))
690                 chn_dmaupdate(c);
691         missing = sndbuf_getready(bs) + sndbuf_getready(b);
692
693         c->flags &= ~CHN_F_ABORTING;
694         return missing;
695 }
696
697 /*
698  * this routine tries to flush the dma transfer. It is called
699  * on a close of a playback channel.
700  * first, if there is data in the buffer, but the dma has not yet
701  * begun, we need to start it.
702  * next, we wait for the play buffer to drain
703  * finally, we stop the dma.
704  *
705  * called from: dsp_close, not valid for record channels.
706  */
707
708 int
709 chn_flush(struct pcm_channel *c)
710 {
711         int ret, count, resid, resid_p;
712         struct snd_dbuf *b = c->bufhard;
713         struct snd_dbuf *bs = c->bufsoft;
714
715         CHN_LOCKASSERT(c);
716         KASSERT(c->direction == PCMDIR_PLAY, ("chn_flush on bad channel"));
717         DEB(kprintf("chn_flush: c->flags 0x%08x\n", c->flags));
718
719         /* if we haven't yet started and nothing is buffered, else start*/
720         if (!(c->flags & CHN_F_TRIGGERED)) {
721                 if (sndbuf_getready(bs) > 0) {
722                         ret = chn_start(c, 1);
723                         if (ret)
724                                 return ret;
725                 } else {
726                         return 0;
727                 }
728         }
729
730         c->flags |= CHN_F_CLOSING;
731         resid = sndbuf_getready(bs) + sndbuf_getready(b);
732         resid_p = resid;
733         count = 10;
734         ret = 0;
735         while ((count > 0) && (resid > sndbuf_getsize(b)) && (ret == 0)) {
736                 /* still pending output data. */
737                 ret = chn_sleep(c, "pcmflu", hz / 10);
738                 if (ret == EWOULDBLOCK)
739                         ret = 0;
740                 if (ret == 0) {
741                         resid = sndbuf_getready(bs) + sndbuf_getready(b);
742                         if (resid == resid_p)
743                                 count--;
744                         if (resid > resid_p)
745                                 DEB(kprintf("chn_flush: buffer length increasind %d -> %d\n", resid_p, resid));
746                         resid_p = resid;
747                 }
748         }
749         if (count == 0)
750                 DEB(kprintf("chn_flush: timeout, hw %d, sw %d\n",
751                         sndbuf_getready(b), sndbuf_getready(bs)));
752
753         c->flags &= ~CHN_F_TRIGGERED;
754         /* kill the channel */
755         chn_trigger(c, PCMTRIG_ABORT);
756         sndbuf_setrun(b, 0);
757
758         c->flags &= ~CHN_F_CLOSING;
759         return 0;
760 }
761
762 int
763 fmtvalid(u_int32_t fmt, u_int32_t *fmtlist)
764 {
765         int i;
766
767         for (i = 0; fmtlist[i]; i++)
768                 if (fmt == fmtlist[i])
769                         return 1;
770         return 0;
771 }
772
773 int
774 chn_reset(struct pcm_channel *c, u_int32_t fmt)
775 {
776         int hwspd, r;
777
778         CHN_LOCKASSERT(c);
779         c->flags &= CHN_F_RESET;
780         c->interrupts = 0;
781         c->xruns = 0;
782
783         r = CHANNEL_RESET(c->methods, c->devinfo);
784         if (fmt != 0) {
785 #if 0
786                 hwspd = DSP_DEFAULT_SPEED;
787                 /* only do this on a record channel until feederbuilder works */
788                 if (c->direction == PCMDIR_REC)
789                         RANGE(hwspd, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
790                 c->speed = hwspd;
791 #endif
792                 hwspd = chn_getcaps(c)->minspeed;
793                 c->speed = hwspd;
794
795                 if (r == 0)
796                         r = chn_setformat(c, fmt);
797                 if (r == 0)
798                         r = chn_setspeed(c, hwspd);
799 #if 0
800                 if (r == 0)
801                         r = chn_setvolume(c, 100, 100);
802 #endif
803         }
804         if (r == 0)
805                 r = chn_setblocksize(c, 0, 0);
806         if (r == 0) {
807                 chn_resetbuf(c);
808                 r = CHANNEL_RESETDONE(c->methods, c->devinfo);
809         }
810         return r;
811 }
812
813 int
814 chn_init(struct pcm_channel *c, void *devinfo, int dir, int direction)
815 {
816         struct feeder_class *fc;
817         struct snd_dbuf *b, *bs;
818         int ret;
819
820         chn_lockinit(c, dir);
821
822         b = NULL;
823         bs = NULL;
824         c->devinfo = NULL;
825         c->feeder = NULL;
826
827         ret = ENOMEM;
828         b = sndbuf_create(c->dev, c->name, "primary", c);
829         if (b == NULL)
830                 goto out;
831         bs = sndbuf_create(c->dev, c->name, "secondary", c);
832         if (bs == NULL)
833                 goto out;
834
835         CHN_LOCK(c);
836
837         ret = EINVAL;
838         fc = feeder_getclass(NULL);
839         if (fc == NULL)
840                 goto out;
841         if (chn_addfeeder(c, fc, NULL))
842                 goto out;
843
844         /*
845          * XXX - sndbuf_setup() & sndbuf_resize() expect to be called
846          *       with the channel unlocked because they are also called
847          *       from driver methods that don't know about locking
848          */
849         CHN_UNLOCK(c);
850         sndbuf_setup(bs, NULL, 0);
851         CHN_LOCK(c);
852         c->bufhard = b;
853         c->bufsoft = bs;
854         c->flags = 0;
855         c->feederflags = 0;
856
857         ret = ENODEV;
858         CHN_UNLOCK(c); /* XXX - Unlock for CHANNEL_INIT() kmalloc() call */
859         c->devinfo = CHANNEL_INIT(c->methods, devinfo, b, c, direction);
860         CHN_LOCK(c);
861         if (c->devinfo == NULL)
862                 goto out;
863
864         ret = ENOMEM;
865         if ((sndbuf_getsize(b) == 0) && ((c->flags & CHN_F_VIRTUAL) == 0))
866                 goto out;
867
868         ret = chn_setdir(c, direction);
869         if (ret)
870                 goto out;
871
872         ret = sndbuf_setfmt(b, AFMT_U8);
873         if (ret)
874                 goto out;
875
876         ret = sndbuf_setfmt(bs, AFMT_U8);
877         if (ret)
878                 goto out;
879
880         ret = chn_setvolume(c, 100, 100);
881         if (ret)
882                 goto out;
883
884
885 out:
886         CHN_UNLOCK(c);
887         if (ret) {
888                 if (c->devinfo) {
889                         if (CHANNEL_FREE(c->methods, c->devinfo))
890                                 sndbuf_free(b);
891                 }
892                 if (bs)
893                         sndbuf_destroy(bs);
894                 if (b)
895                         sndbuf_destroy(b);
896                 c->flags |= CHN_F_DEAD;
897                 chn_lockdestroy(c);
898
899                 return ret;
900         }
901
902         return 0;
903 }
904
905 int
906 chn_kill(struct pcm_channel *c)
907 {
908         struct snd_dbuf *b = c->bufhard;
909         struct snd_dbuf *bs = c->bufsoft;
910
911         if (c->flags & CHN_F_TRIGGERED)
912                 chn_trigger(c, PCMTRIG_ABORT);
913         while (chn_removefeeder(c) == 0);
914         if (CHANNEL_FREE(c->methods, c->devinfo))
915                 sndbuf_free(b);
916         c->flags |= CHN_F_DEAD;
917         sndbuf_destroy(bs);
918         sndbuf_destroy(b);
919         chn_lockdestroy(c);
920         return 0;
921 }
922
923 int
924 chn_setdir(struct pcm_channel *c, int dir)
925 {
926         int r;
927
928         CHN_LOCKASSERT(c);
929         c->direction = dir;
930         r = CHANNEL_SETDIR(c->methods, c->devinfo, c->direction);
931         return r;
932 }
933
934 int
935 chn_setvolume(struct pcm_channel *c, int left, int right)
936 {
937         CHN_LOCKASSERT(c);
938         /* should add a feeder for volume changing if channel returns -1 */
939         if (left > 100)
940                 left = 100;
941         if (left < 0)
942                 left = 0;
943         if (right > 100)
944                 right = 100;
945         if (right < 0)
946                 right = 0;
947         c->volume = left | (right << 8);
948         return 0;
949 }
950
951 static int
952 chn_tryspeed(struct pcm_channel *c, int speed)
953 {
954         struct pcm_feeder *f;
955         struct snd_dbuf *b = c->bufhard;
956         struct snd_dbuf *bs = c->bufsoft;
957         struct snd_dbuf *x;
958         int r, delta;
959
960         CHN_LOCKASSERT(c);
961         DEB(kprintf("setspeed, channel %s\n", c->name));
962         DEB(kprintf("want speed %d, ", speed));
963         if (speed <= 0)
964                 return EINVAL;
965         if (CANCHANGE(c)) {
966                 r = 0;
967                 c->speed = speed;
968                 sndbuf_setspd(bs, speed);
969                 RANGE(speed, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
970                 DEB(kprintf("try speed %d, ", speed));
971                 sndbuf_setspd(b, CHANNEL_SETSPEED(c->methods, c->devinfo, speed));
972                 DEB(kprintf("got speed %d\n", sndbuf_getspd(b)));
973
974                 delta = sndbuf_getspd(b) - sndbuf_getspd(bs);
975                 if (delta < 0)
976                         delta = -delta;
977
978                 c->feederflags &= ~(1 << FEEDER_RATE);
979                 /*
980                  * Used to be 500. It was too big!
981                  */
982                 if (delta > 25)
983                         c->feederflags |= 1 << FEEDER_RATE;
984                 else
985                         sndbuf_setspd(bs, sndbuf_getspd(b));
986
987                 r = chn_buildfeeder(c);
988                 DEB(kprintf("r = %d\n", r));
989                 if (r)
990                         goto out;
991
992                 r = chn_setblocksize(c, 0, 0);
993                 if (r)
994                         goto out;
995
996                 if (!(c->feederflags & (1 << FEEDER_RATE)))
997                         goto out;
998
999                 r = EINVAL;
1000                 f = chn_findfeeder(c, FEEDER_RATE);
1001                 DEB(kprintf("feedrate = %p\n", f));
1002                 if (f == NULL)
1003                         goto out;
1004
1005                 x = (c->direction == PCMDIR_REC)? b : bs;
1006                 r = FEEDER_SET(f, FEEDRATE_SRC, sndbuf_getspd(x));
1007                 DEB(kprintf("feeder_set(FEEDRATE_SRC, %d) = %d\n", sndbuf_getspd(x), r));
1008                 if (r)
1009                         goto out;
1010
1011                 x = (c->direction == PCMDIR_REC)? bs : b;
1012                 r = FEEDER_SET(f, FEEDRATE_DST, sndbuf_getspd(x));
1013                 DEB(kprintf("feeder_set(FEEDRATE_DST, %d) = %d\n", sndbuf_getspd(x), r));
1014 out:
1015                 if (!r)
1016                         r = CHANNEL_SETFORMAT(c->methods, c->devinfo,
1017                                                         sndbuf_getfmt(b));
1018                 if (!r)
1019                         sndbuf_setfmt(bs, c->format);
1020                 DEB(kprintf("setspeed done, r = %d\n", r));
1021                 return r;
1022         } else
1023                 return EINVAL;
1024 }
1025
1026 int
1027 chn_setspeed(struct pcm_channel *c, int speed)
1028 {
1029         int r, oldspeed = c->speed;
1030
1031         r = chn_tryspeed(c, speed);
1032         if (r) {
1033                 DEB(kprintf("Failed to set speed %d falling back to %d\n", speed, oldspeed));
1034                 r = chn_tryspeed(c, oldspeed);
1035         }
1036         return r;
1037 }
1038
1039 static int
1040 chn_tryformat(struct pcm_channel *c, u_int32_t fmt)
1041 {
1042         struct snd_dbuf *b = c->bufhard;
1043         struct snd_dbuf *bs = c->bufsoft;
1044         int r;
1045
1046         CHN_LOCKASSERT(c);
1047         if (CANCHANGE(c)) {
1048                 DEB(kprintf("want format %d\n", fmt));
1049                 c->format = fmt;
1050                 r = chn_buildfeeder(c);
1051                 if (r == 0) {
1052                         sndbuf_setfmt(bs, c->format);
1053                         chn_resetbuf(c);
1054                         r = CHANNEL_SETFORMAT(c->methods, c->devinfo, sndbuf_getfmt(b));
1055                         if (r == 0)
1056                                 r = chn_tryspeed(c, c->speed);
1057                 }
1058                 return r;
1059         } else
1060                 return EINVAL;
1061 }
1062
1063 int
1064 chn_setformat(struct pcm_channel *c, u_int32_t fmt)
1065 {
1066         u_int32_t oldfmt = c->format;
1067         int r;
1068
1069         r = chn_tryformat(c, fmt);
1070         if (r) {
1071                 DEB(kprintf("Format change %d failed, reverting to %d\n", fmt, oldfmt));
1072                 chn_tryformat(c, oldfmt);
1073         }
1074         return r;
1075 }
1076
1077 /*
1078  * given a bufsz value, round it to a power of 2 in the min-max range
1079  * XXX only works if min and max are powers of 2
1080  */
1081 static int
1082 round_bufsz(int bufsz, int min, int max)
1083 {
1084         int tmp = min * 2;
1085
1086         KASSERT((min & (min-1)) == 0, ("min %d must be power of 2", min));
1087         KASSERT((max & (max-1)) == 0, ("max %d must be power of 2", max));
1088         while (tmp <= bufsz)
1089                 tmp <<= 1;
1090         tmp >>= 1;
1091         if (tmp > max)
1092                 tmp = max;
1093         return tmp;
1094 }
1095
1096 /*
1097  * set the channel's blocksize both for soft and hard buffers.
1098  *
1099  * blksz should be a power of 2 between 2**4 and 2**16 -- it is useful
1100  * that it has the same value for both bufsoft and bufhard.
1101  * blksz == -1 computes values according to a target irq rate.
1102  * blksz == 0 reuses previous values if available, otherwise
1103  * behaves as for -1
1104  *
1105  * blkcnt is set by the user, between 2 and (2**17)/blksz for bufsoft,
1106  * but should be a power of 2 for bufhard to simplify life to low
1107  * level drivers.
1108  * Note, for the rec channel a large blkcnt is ok,
1109  * but for the play channel we want blksz as small as possible to keep
1110  * the delay small, because routines in the write path always try to
1111  * keep bufhard full.
1112  *
1113  * Unless we have good reason to, use the values suggested by the caller.
1114  */
1115 int
1116 chn_setblocksize(struct pcm_channel *c, int blkcnt, int blksz)
1117 {
1118         struct snd_dbuf *b = c->bufhard;
1119         struct snd_dbuf *bs = c->bufsoft;
1120         int irqhz, ret, maxsz, maxsize, reqblksz;
1121
1122         CHN_LOCKASSERT(c);
1123         if (!CANCHANGE(c) || (c->flags & CHN_F_MAPPED)) {
1124                 KASSERT(sndbuf_getsize(bs) ==  0 ||
1125                     sndbuf_getsize(bs) >= sndbuf_getsize(b),
1126                     ("%s(%s): bufsoft size %d < bufhard size %d", __func__,
1127                     c->name, sndbuf_getsize(bs), sndbuf_getsize(b)));
1128                 return EINVAL;
1129         }
1130         c->flags |= CHN_F_SETBLOCKSIZE;
1131
1132         ret = 0;
1133         DEB(kprintf("%s(%d, %d)\n", __func__, blkcnt, blksz));
1134         if (blksz == 0 || blksz == -1) { /* let the driver choose values */
1135                 if (blksz == -1)        /* delete previous values */
1136                         c->flags &= ~CHN_F_HAS_SIZE;
1137                 if (!(c->flags & CHN_F_HAS_SIZE)) { /* no previous value */
1138                         /*
1139                          * compute a base blksz according to the target irq
1140                          * rate, then round to a suitable power of 2
1141                          * in the range 16.. 2^17/2.
1142                          * Finally compute a suitable blkcnt.
1143                          */
1144                         blksz = round_bufsz( (sndbuf_getbps(bs) *
1145                                 sndbuf_getspd(bs)) / chn_targetirqrate,
1146                                 16, CHN_2NDBUFMAXSIZE / 2);
1147                         blkcnt = CHN_2NDBUFMAXSIZE / blksz;
1148                 } else { /* use previously defined value */
1149                         blkcnt = sndbuf_getblkcnt(bs);
1150                         blksz = sndbuf_getblksz(bs);
1151                 }
1152         } else {
1153                 /*
1154                  * use supplied values if reasonable. Note that here we
1155                  * might have blksz which is not a power of 2 if the
1156                  * ioctl() to compute it allows such values.
1157                  */
1158                 ret = EINVAL;
1159                 if ((blksz < 16) || (blkcnt < 2) || (blkcnt * blksz > CHN_2NDBUFMAXSIZE))
1160                         goto out;
1161                 ret = 0;
1162                 c->flags |= CHN_F_HAS_SIZE;
1163         }
1164
1165         reqblksz = blksz;
1166         if (reqblksz < sndbuf_getbps(bs))
1167                 reqblksz = sndbuf_getbps(bs);
1168         if (reqblksz % sndbuf_getbps(bs))
1169                 reqblksz -= reqblksz % sndbuf_getbps(bs);
1170
1171         /* adjust for different hw format/speed */
1172         /*
1173          * Now compute the approx irq rate for the given (soft) blksz,
1174          * reduce to the acceptable range and compute a corresponding blksz
1175          * for the hard buffer. Then set the channel's blocksize and
1176          * corresponding hardbuf value. The number of blocks used should
1177          * be set by the device-specific routine. In fact, even the
1178          * call to sndbuf_setblksz() should not be here! XXX
1179          */
1180
1181         irqhz = (sndbuf_getbps(bs) * sndbuf_getspd(bs)) / blksz;
1182         RANGE(irqhz, 16, 512);
1183
1184         maxsz = sndbuf_getmaxsize(b);
1185         if (maxsz == 0) /* virtual channels don't appear to allocate bufhard */
1186                 maxsz = CHN_2NDBUFMAXSIZE;
1187         blksz = round_bufsz( (sndbuf_getbps(b) * sndbuf_getspd(b)) / irqhz,
1188                         16, maxsz / 2);
1189
1190         /* Increase the size of bufsoft if before increasing bufhard. */
1191         maxsize = sndbuf_getsize(b);
1192         if (sndbuf_getsize(bs) > maxsize)
1193                 maxsize = sndbuf_getsize(bs);
1194         if (reqblksz * blkcnt > maxsize)
1195                 maxsize = reqblksz * blkcnt;
1196         if (sndbuf_getsize(bs) != maxsize || sndbuf_getblksz(bs) != reqblksz) {
1197                 ret = sndbuf_remalloc(bs, maxsize/reqblksz, reqblksz);
1198                 if (ret)
1199                         goto out1;
1200         }
1201
1202         CHN_UNLOCK(c);
1203         sndbuf_setblksz(b, CHANNEL_SETBLOCKSIZE(c->methods, c->devinfo, blksz));
1204         CHN_LOCK(c);
1205
1206         /* Decrease the size of bufsoft after decreasing bufhard. */
1207         maxsize = sndbuf_getsize(b);
1208         if (reqblksz * blkcnt > maxsize)
1209                 maxsize = reqblksz * blkcnt;
1210         if (maxsize > sndbuf_getsize(bs))
1211                 kprintf("Danger! %s bufsoft size increasing from %d to %d after CHANNEL_SETBLOCKSIZE()\n",
1212                     c->name, sndbuf_getsize(bs), maxsize);
1213         if (sndbuf_getsize(bs) != maxsize || sndbuf_getblksz(bs) != reqblksz) {
1214                 ret = sndbuf_remalloc(bs, maxsize/reqblksz, reqblksz);
1215                 if (ret)
1216                         goto out1;
1217         }
1218
1219         chn_resetbuf(c);
1220 out1:
1221         KASSERT(sndbuf_getsize(bs) ==  0 ||
1222             sndbuf_getsize(bs) >= sndbuf_getsize(b),
1223             ("%s(%s): bufsoft size %d < bufhard size %d, reqblksz=%d blksz=%d maxsize=%d blkcnt=%d",
1224             __func__, c->name, sndbuf_getsize(bs), sndbuf_getsize(b), reqblksz,
1225             blksz, maxsize, blkcnt));
1226 out:
1227         c->flags &= ~CHN_F_SETBLOCKSIZE;
1228 #if 0
1229         if (1) {
1230                 static uint32_t kk = 0;
1231                 printf("%u: b %d/%d/%d : (%d)%d/0x%0x | bs %d/%d/%d : (%d)%d/0x%0x\n", ++kk,
1232                         sndbuf_getsize(b), sndbuf_getblksz(b), sndbuf_getblkcnt(b),
1233                         sndbuf_getbps(b),
1234                         sndbuf_getspd(b), sndbuf_getfmt(b),
1235                         sndbuf_getsize(bs), sndbuf_getblksz(bs), sndbuf_getblkcnt(bs),
1236                         sndbuf_getbps(bs),
1237                         sndbuf_getspd(bs), sndbuf_getfmt(bs));
1238                 if (sndbuf_getsize(b) % sndbuf_getbps(b) ||
1239                                 sndbuf_getblksz(b) % sndbuf_getbps(b) ||
1240                                 sndbuf_getsize(bs) % sndbuf_getbps(bs) ||
1241                                 sndbuf_getblksz(b) % sndbuf_getbps(b)) {
1242                         printf("%u: bps/blksz alignment screwed!\n", kk);
1243                 }
1244         }
1245 #endif
1246         return ret;
1247 }
1248
1249 int
1250 chn_trigger(struct pcm_channel *c, int go)
1251 {
1252         int ret;
1253
1254         CHN_LOCKASSERT(c);
1255         ret = CHANNEL_TRIGGER(c->methods, c->devinfo, go);
1256
1257         return ret;
1258 }
1259
1260 int
1261 chn_getptr(struct pcm_channel *c)
1262 {
1263 #if 0
1264         int hwptr;
1265         int a = (1 << c->align) - 1;
1266
1267         CHN_LOCKASSERT(c);
1268         hwptr = (c->flags & CHN_F_TRIGGERED)? CHANNEL_GETPTR(c->methods, c->devinfo) : 0;
1269         /* don't allow unaligned values in the hwa ptr */
1270 #if 1
1271         hwptr &= ~a ; /* Apply channel align mask */
1272 #endif
1273         hwptr &= DMA_ALIGN_MASK; /* Apply DMA align mask */
1274         return hwptr;
1275 #endif
1276         int hwptr;
1277
1278         CHN_LOCKASSERT(c);
1279         hwptr = (c->flags & CHN_F_TRIGGERED)? CHANNEL_GETPTR(c->methods, c->devinfo) : 0;
1280         return (hwptr - (hwptr % sndbuf_getbps(c->bufhard)));
1281 }
1282
1283 struct pcmchan_caps *
1284 chn_getcaps(struct pcm_channel *c)
1285 {
1286         CHN_LOCKASSERT(c);
1287         return CHANNEL_GETCAPS(c->methods, c->devinfo);
1288 }
1289
1290 u_int32_t
1291 chn_getformats(struct pcm_channel *c)
1292 {
1293         u_int32_t *fmtlist, fmts;
1294         int i;
1295
1296         fmtlist = chn_getcaps(c)->fmtlist;
1297         fmts = 0;
1298         for (i = 0; fmtlist[i]; i++)
1299                 fmts |= fmtlist[i];
1300
1301         /* report software-supported formats */
1302         if (report_soft_formats)
1303                 fmts |= AFMT_MU_LAW|AFMT_A_LAW|AFMT_U32_LE|AFMT_U32_BE|
1304                     AFMT_S32_LE|AFMT_S32_BE|AFMT_U24_LE|AFMT_U24_BE|
1305                     AFMT_S24_LE|AFMT_S24_BE|AFMT_U16_LE|AFMT_U16_BE|
1306                     AFMT_S16_LE|AFMT_S16_BE|AFMT_U8|AFMT_S8;
1307
1308         return fmts;
1309 }
1310
1311 static int
1312 chn_buildfeeder(struct pcm_channel *c)
1313 {
1314         struct feeder_class *fc;
1315         struct pcm_feederdesc desc;
1316         u_int32_t tmp[2], type, flags, hwfmt, *fmtlist;
1317         int err;
1318
1319         CHN_LOCKASSERT(c);
1320         while (chn_removefeeder(c) == 0);
1321         KASSERT((c->feeder == NULL), ("feeder chain not empty"));
1322
1323         c->align = sndbuf_getalign(c->bufsoft);
1324
1325         if (SLIST_EMPTY(&c->children)) {
1326                 fc = feeder_getclass(NULL);
1327                 KASSERT(fc != NULL, ("can't find root feeder"));
1328
1329                 err = chn_addfeeder(c, fc, NULL);
1330                 if (err) {
1331                         DEB(kprintf("can't add root feeder, err %d\n", err));
1332
1333                         return err;
1334                 }
1335                 c->feeder->desc->out = c->format;
1336         } else {
1337                 if (c->flags & CHN_F_HAS_VCHAN) {
1338                         desc.type = FEEDER_MIXER;
1339                         desc.in = 0;
1340                 } else {
1341                         DEB(kprintf("can't decide which feeder type to use!\n"));
1342                         return EOPNOTSUPP;
1343                 }
1344                 desc.out = c->format;
1345                 desc.flags = 0;
1346                 fc = feeder_getclass(&desc);
1347                 if (fc == NULL) {
1348                         DEB(kprintf("can't find vchan feeder\n"));
1349
1350                         return EOPNOTSUPP;
1351                 }
1352
1353                 err = chn_addfeeder(c, fc, &desc);
1354                 if (err) {
1355                         DEB(kprintf("can't add vchan feeder, err %d\n", err));
1356
1357                         return err;
1358                 }
1359         }
1360         c->feederflags &= ~(1 << FEEDER_VOLUME);
1361         if (c->direction == PCMDIR_PLAY &&
1362                         !(c->flags & CHN_F_VIRTUAL) &&
1363                         c->parentsnddev && (c->parentsnddev->flags & SD_F_SOFTPCMVOL) &&
1364                         c->parentsnddev->mixer_dev)
1365                 c->feederflags |= 1 << FEEDER_VOLUME;
1366         flags = c->feederflags;
1367         fmtlist = chn_getcaps(c)->fmtlist;
1368
1369         DEB(kprintf("feederflags %x\n", flags));
1370
1371         for (type = FEEDER_RATE; type <= FEEDER_LAST; type++) {
1372                 if (flags & (1 << type)) {
1373                         desc.type = type;
1374                         desc.in = 0;
1375                         desc.out = 0;
1376                         desc.flags = 0;
1377                         DEB(kprintf("find feeder type %d, ", type));
1378                         fc = feeder_getclass(&desc);
1379                         DEB(kprintf("got %p\n", fc));
1380                         if (fc == NULL) {
1381                                 DEB(kprintf("can't find required feeder type %d\n", type));
1382
1383                                 return EOPNOTSUPP;
1384                         }
1385
1386                         DEB(kprintf("build fmtchain from 0x%08x to 0x%08x: ", c->feeder->desc->out, fc->desc->in));
1387                         tmp[0] = fc->desc->in;
1388                         tmp[1] = 0;
1389                         if (chn_fmtchain(c, tmp) == 0) {
1390                                 DEB(kprintf("failed\n"));
1391
1392                                 return ENODEV;
1393                         }
1394                         DEB(kprintf("ok\n"));
1395
1396                         err = chn_addfeeder(c, fc, fc->desc);
1397                         if (err) {
1398                                 DEB(kprintf("can't add feeder %p, output 0x%x, err %d\n", fc, fc->desc->out, err));
1399
1400                                 return err;
1401                         }
1402                         DEB(kprintf("added feeder %p, output 0x%x\n", fc, c->feeder->desc->out));
1403                 }
1404         }
1405
1406         if (c->direction == PCMDIR_REC) {
1407                 tmp[0] = c->format;
1408                 tmp[1] = 0;
1409                 hwfmt = chn_fmtchain(c, tmp);
1410         } else
1411                 hwfmt = chn_fmtchain(c, fmtlist);
1412
1413         if (hwfmt == 0 || !fmtvalid(hwfmt, fmtlist)) {
1414                 DEB(kprintf("Invalid hardware format: 0x%08x\n", hwfmt));
1415                 return ENODEV;
1416         }
1417
1418         sndbuf_setfmt(c->bufhard, hwfmt);
1419
1420         if ((flags & (1 << FEEDER_VOLUME))) {
1421                 struct dev_ioctl_args map;
1422                 u_int32_t parent = SOUND_MIXER_NONE;
1423                 int vol, left, right;
1424
1425                 vol = 100 | (100 << 8);
1426
1427                 CHN_UNLOCK(c);
1428                 /*
1429                  * XXX This is ugly! The way mixer subs being so secretive
1430                  * about its own internals force us to use this silly
1431                  * monkey trick.
1432                  */
1433                 map.a_head.a_dev = c->parentsnddev->mixer_dev;
1434                 map.a_cmd = MIXER_READ(SOUND_MIXER_PCM);
1435                 map.a_data = (caddr_t)&vol;
1436                 map.a_fflag = -1;
1437                 map.a_cred = NULL;
1438                 map.a_sysmsg = NULL;
1439                 if (mixer_ioctl(&map) != 0)
1440                         device_printf(c->dev, "Soft PCM Volume: Failed to read default value\n");
1441                 left = vol & 0x7f;
1442                 right = (vol >> 8) & 0x7f;
1443                 if (c->parentsnddev != NULL &&
1444                     c->parentsnddev->mixer_dev != NULL &&
1445                     c->parentsnddev->mixer_dev->si_drv1 != NULL)
1446                         parent = mix_getparent(
1447                             c->parentsnddev->mixer_dev->si_drv1,
1448                             SOUND_MIXER_PCM);
1449                 if (parent != SOUND_MIXER_NONE) {
1450                         vol = 100 | (100 << 8);
1451                         map.a_head.a_dev = c->parentsnddev->mixer_dev;
1452                         map.a_cmd = MIXER_READ(parent);
1453                         map.a_data = (caddr_t)&vol;
1454                         map.a_fflag = -1;
1455                         map.a_cred = NULL;
1456                         if (mixer_ioctl(&map) != 0)
1457                                 device_printf(c->dev, "Soft Volume: Failed to read parent default value\n");
1458                         left = (left * (vol & 0x7f)) / 100;
1459                         right = (right * ((vol >> 8) & 0x7f)) / 100;
1460                 }
1461
1462                 CHN_LOCK(c);
1463                 chn_setvolume(c, left, right);
1464         }
1465
1466         return 0;
1467 }
1468
1469 int
1470 chn_notify(struct pcm_channel *c, u_int32_t flags)
1471 {
1472         struct pcmchan_children *pce;
1473         struct pcm_channel *child;
1474         int run;
1475
1476         CHN_LOCK(c);
1477
1478         if (SLIST_EMPTY(&c->children)) {
1479                 CHN_UNLOCK(c);
1480                 return ENODEV;
1481         }
1482
1483         run = (c->flags & CHN_F_TRIGGERED)? 1 : 0;
1484         /*
1485          * if the hwchan is running, we can't change its rate, format or
1486          * blocksize
1487          */
1488         if (run)
1489                 flags &= CHN_N_VOLUME | CHN_N_TRIGGER;
1490
1491         if (flags & CHN_N_RATE) {
1492                 /*
1493                  * we could do something here, like scan children and decide on
1494                  * the most appropriate rate to mix at, but we don't for now
1495                  */
1496         }
1497         if (flags & CHN_N_FORMAT) {
1498                 /*
1499                  * we could do something here, like scan children and decide on
1500                  * the most appropriate mixer feeder to use, but we don't for now
1501                  */
1502         }
1503         if (flags & CHN_N_VOLUME) {
1504                 /*
1505                  * we could do something here but we don't for now
1506                  */
1507         }
1508         if (flags & CHN_N_BLOCKSIZE) {
1509                 int blksz;
1510                 /*
1511                  * scan the children, find the lowest blocksize and use that
1512                  * for the hard blocksize
1513                  */
1514                 blksz = sndbuf_getmaxsize(c->bufhard) / 2;
1515                 SLIST_FOREACH(pce, &c->children, link) {
1516                         child = pce->channel;
1517                         CHN_LOCK(child);
1518                         if (sndbuf_getblksz(child->bufhard) < blksz)
1519                                 blksz = sndbuf_getblksz(child->bufhard);
1520                         CHN_UNLOCK(child);
1521                 }
1522                 chn_setblocksize(c, 2, blksz);
1523         }
1524         if (flags & CHN_N_TRIGGER) {
1525                 int nrun;
1526                 /*
1527                  * scan the children, and figure out if any are running
1528                  * if so, we need to be running, otherwise we need to be stopped
1529                  * if we aren't in our target sstate, move to it
1530                  */
1531                 nrun = 0;
1532                 SLIST_FOREACH(pce, &c->children, link) {
1533                         child = pce->channel;
1534                         CHN_LOCK(child);
1535                         if (child->flags & CHN_F_TRIGGERED)
1536                                 nrun = 1;
1537                         CHN_UNLOCK(child);
1538                 }
1539                 if (nrun && !run)
1540                         chn_start(c, 1);
1541                 if (!nrun && run)
1542                         chn_abort(c);
1543         }
1544         CHN_UNLOCK(c);
1545         return 0;
1546 }
1547
1548 void
1549 chn_lock(struct pcm_channel *c)
1550 {
1551         CHN_LOCK(c);
1552 }
1553
1554 void
1555 chn_unlock(struct pcm_channel *c)
1556 {
1557         CHN_UNLOCK(c);
1558 }