1 /*        $NetBSD: aucc.c,v 1.48 2020/02/29 06:03:55 isaki Exp $ */
2 
3 /*
4  * Copyright (c) 1999 Bernardo Innocenti
5  * All rights reserved.
6  *
7  * Copyright (c) 1997 Stephan Thesing
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by Stephan Thesing.
21  * 4. The name of the author may not be used to endorse or promote products
22  *    derived from this software without specific prior written permission
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 /* TODO:
37  *
38  * - channel allocation is wrong for 14bit mono
39  * - perhaps use a calibration table for better 14bit output
40  * - set 31 kHz AGA video mode to allow 44.1 kHz even if grfcc is missing
41  *        in the kernel
42  * - 14bit output requires maximum volume
43  */
44 
45 #include "aucc.h"
46 #if NAUCC > 0
47 
48 #include <sys/cdefs.h>
49 __KERNEL_RCSID(0, "$NetBSD: aucc.c,v 1.48 2020/02/29 06:03:55 isaki Exp $");
50 
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/errno.h>
54 #include <sys/ioctl.h>
55 #include <sys/device.h>
56 #include <sys/proc.h>
57 #include <machine/cpu.h>
58 
59 #include <sys/audioio.h>
60 #include <dev/audio/audio_if.h>
61 #include <dev/audio/audiovar.h>         /* for AUDIO_MIN_FREQUENCY */
62 
63 #include <amiga/amiga/cc.h>
64 #include <amiga/amiga/custom.h>
65 #include <amiga/amiga/device.h>
66 #include <amiga/dev/auccvar.h>
67 
68 #include "opt_lev6_defer.h"
69 
70 
71 #ifdef LEV6_DEFER
72 #define AUCC_MAXINT 3
73 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2)
74 #else
75 #define AUCC_MAXINT 4
76 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3)
77 #endif
78 /* this unconditionally; we may use AUD3 as slave channel with LEV6_DEFER */
79 #define AUCC_ALLDMAF (DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3)
80 
81 #ifdef AUDIO_DEBUG
82 /*extern printf(const char *,...);*/
83 int     auccdebug = 1;
84 #define DPRINTF(x)      if (auccdebug) printf x
85 #else
86 #define DPRINTF(x)
87 #endif
88 
89 /* clock frequency.. */
90 extern int eclockfreq;
91 
92 
93 /* hw audio ch */
94 extern struct audio_channel channel[4];
95 
96 
97 /*
98  * Software state.
99  */
100 struct aucc_softc {
101           aucc_data_t sc_channel[4];    /* per channel freq, ... */
102           u_int     sc_encoding;                  /* encoding AUDIO_ENCODING_.*/
103           int       sc_channels;                  /* # of channels used */
104           int       sc_precision;                 /* 8 or 16 bits */
105           int       sc_14bit;           /* 14bit output enabled */
106 
107           int       sc_intrcnt;                   /* interrupt count */
108           int       sc_channelmask;               /* which channels are used ? */
109           void (*sc_decodefunc)(u_char **, u_char *, int);
110                                         /* pointer to format conversion routine */
111 
112           kmutex_t sc_lock;
113           kmutex_t sc_intr_lock;
114 };
115 
116 /* interrupt interfaces */
117 void aucc_inthdl(int);
118 
119 /* forward declarations */
120 static int init_aucc(struct aucc_softc *);
121 static u_int freqtoper(u_int);
122 static u_int pertofreq(u_int);
123 
124 /* autoconfiguration driver */
125 void      auccattach(device_t, device_t, void *);
126 int       auccmatch(device_t, cfdata_t, void *);
127 
128 CFATTACH_DECL_NEW(aucc, sizeof(struct aucc_softc),
129     auccmatch, auccattach, NULL, NULL);
130 
131 struct audio_device aucc_device = {
132           "Amiga-audio",
133           "2.0",
134           "aucc"
135 };
136 
137 
138 struct aucc_softc *aucc = NULL;
139 
140 
141 /*
142  * Define our interface to the higher level audio driver.
143  */
144 int       aucc_open(void *, int);
145 void      aucc_close(void *);
146 int       aucc_set_out_sr(void *, u_int);
147 int       aucc_query_format(void *, audio_format_query_t *);
148 int       aucc_round_blocksize(void *, int, int, const audio_params_t *);
149 int       aucc_commit_settings(void *);
150 int       aucc_start_output(void *, void *, int, void (*)(void *), void *);
151 int       aucc_start_input(void *, void *, int, void (*)(void *), void *);
152 int       aucc_halt_output(void *);
153 int       aucc_halt_input(void *);
154 int       aucc_getdev(void *, struct audio_device *);
155 int       aucc_set_port(void *, mixer_ctrl_t *);
156 int       aucc_get_port(void *, mixer_ctrl_t *);
157 int       aucc_query_devinfo(void *, mixer_devinfo_t *);
158 void      aucc_encode(int, int, int, int, u_char *, u_short **);
159 int       aucc_set_format(void *, int,
160                               const audio_params_t *, const audio_params_t *,
161                               audio_filter_reg_t *, audio_filter_reg_t *);
162 int       aucc_get_props(void *);
163 void      aucc_get_locks(void *, kmutex_t **, kmutex_t **);
164 
165 
166 static void aucc_decode_slinear16_1ch(u_char **, u_char *, int);
167 static void aucc_decode_slinear16_2ch(u_char **, u_char *, int);
168 static void aucc_decode_slinear16_3ch(u_char **, u_char *, int);
169 static void aucc_decode_slinear16_4ch(u_char **, u_char *, int);
170 
171 
172 const struct audio_hw_if sa_hw_if = {
173           .open                         = aucc_open,
174           .close                        = aucc_close,
175           .query_format                 = aucc_query_format,
176           .set_format                   = aucc_set_format,
177           .round_blocksize    = aucc_round_blocksize,
178           .commit_settings    = aucc_commit_settings,
179           .start_output                 = aucc_start_output,
180           .start_input                  = aucc_start_input,
181           .halt_output                  = aucc_halt_output,
182           .halt_input                   = aucc_halt_input,
183           .getdev                       = aucc_getdev,
184           .set_port           = aucc_set_port,
185           .get_port           = aucc_get_port,
186           .query_devinfo                = aucc_query_devinfo,
187           .get_props                    = aucc_get_props,
188           .get_locks                    = aucc_get_locks,
189 };
190 
191 /*
192  * XXX *1 How lower limit of frequency should be?  same as audio(4)?
193  * XXX *2 Should avoid a magic number at the upper limit of frequency.
194  * XXX *3 In fact, there is a number in this range that have minimal errors.
195  *        It would be better if there is a mechanism which such frequency
196  *        is prioritized.
197  * XXX *4 3/4ch modes use 8bits, 1/2ch modes use 14bits,
198  *        so I imagined that 1/2ch modes are better.
199  */
200 #define AUCC_FORMAT(prio, ch, chmask) \
201           { \
202                     .mode               = AUMODE_PLAY, \
203                     .priority = (prio), \
204                     .encoding = AUDIO_ENCODING_SLINEAR_BE, \
205                     .validbits          = 16, \
206                     .precision          = 16, \
207                     .channels = (ch), \
208                     .channel_mask       = (chmask), \
209                     .frequency_type     = 0, \
210                     .frequency          = { AUDIO_MIN_FREQUENCY, 28867 }, \
211           }
212 static const struct audio_format aucc_formats[] = {
213           AUCC_FORMAT(1, 1, AUFMT_MONAURAL),
214           AUCC_FORMAT(1, 2, AUFMT_STEREO),
215           AUCC_FORMAT(0, 3, AUFMT_UNKNOWN_POSITION),
216           AUCC_FORMAT(0, 4, AUFMT_UNKNOWN_POSITION),
217 };
218 #define AUCC_NFORMATS __arraycount(aucc_formats)
219 
220 /* autoconfig routines */
221 
222 int
auccmatch(device_t parent,cfdata_t cf,void * aux)223 auccmatch(device_t parent, cfdata_t cf, void *aux)
224 {
225           static int aucc_matched = 0;
226 
227           if (!matchname((char *)aux, "aucc") ||
228 #ifdef DRACO
229               is_draco() ||
230 #endif
231               aucc_matched)
232                     return 0;
233 
234           aucc_matched = 1;
235           return 1;
236 }
237 
238 /*
239  * Audio chip found.
240  */
241 void
auccattach(device_t parent,device_t self,void * args)242 auccattach(device_t parent, device_t self, void *args)
243 {
244           struct aucc_softc *sc;
245           int i;
246 
247           sc = device_private(self);
248           printf("\n");
249 
250           if ((i=init_aucc(sc))) {
251                     printf("audio: no chipmem\n");
252                     return;
253           }
254 
255           audio_attach_mi(&sa_hw_if, sc, self);
256 }
257 
258 
259 static int
init_aucc(struct aucc_softc * sc)260 init_aucc(struct aucc_softc *sc)
261 {
262           int i, err;
263 
264           err = 0;
265           /* init values per channel */
266           for (i = 0; i < 4; i++) {
267                     sc->sc_channel[i].nd_freq = 8000;
268                     sc->sc_channel[i].nd_per = freqtoper(8000);
269                     sc->sc_channel[i].nd_busy = 0;
270                     sc->sc_channel[i].nd_dma = alloc_chipmem(AUDIO_BUF_SIZE*2);
271                     if (sc->sc_channel[i].nd_dma == NULL)
272                               err = 1;
273                     sc->sc_channel[i].nd_dmalength = 0;
274                     sc->sc_channel[i].nd_volume = 64;
275                     sc->sc_channel[i].nd_intr = NULL;
276                     sc->sc_channel[i].nd_intrdata = NULL;
277                     sc->sc_channel[i].nd_doublebuf = 0;
278                     DPRINTF(("DMA buffer for channel %d is %p\n", i,
279                         sc->sc_channel[i].nd_dma));
280           }
281 
282           if (err) {
283                     for (i = 0; i < 4; i++)
284                               if (sc->sc_channel[i].nd_dma)
285                                         free_chipmem(sc->sc_channel[i].nd_dma);
286           }
287 
288           sc->sc_channels = 1;
289           sc->sc_channelmask = 0xf;
290           sc->sc_precision = 16;
291           sc->sc_14bit = 1;
292           sc->sc_encoding = AUDIO_ENCODING_SLINEAR_BE;
293           sc->sc_decodefunc = aucc_decode_slinear16_2ch;
294 
295           /* clear interrupts and DMA: */
296           custom.intena = AUCC_ALLINTF;
297           custom.dmacon = AUCC_ALLDMAF;
298 
299           mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
300           mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
301 
302           return err;
303 }
304 
305 int
aucc_open(void * addr,int flags)306 aucc_open(void *addr, int flags)
307 {
308           struct aucc_softc *sc;
309           int i;
310 
311           sc = addr;
312           DPRINTF(("sa_open: unit %p\n",sc));
313 
314           for (i = 0; i < AUCC_MAXINT; i++) {
315                     sc->sc_channel[i].nd_intr = NULL;
316                     sc->sc_channel[i].nd_intrdata = NULL;
317           }
318           aucc = sc;
319           sc->sc_channelmask = 0xf;
320 
321           DPRINTF(("saopen: ok -> sc=%p\n",sc));
322 
323           return 0;
324 }
325 
326 void
aucc_close(void * addr)327 aucc_close(void *addr)
328 {
329 
330           DPRINTF(("sa_close: closed.\n"));
331 }
332 
333 int
aucc_set_out_sr(void * addr,u_int sr)334 aucc_set_out_sr(void *addr, u_int sr)
335 {
336           struct aucc_softc *sc;
337           u_long per;
338           int i;
339 
340           sc = addr;
341           per = freqtoper(sr);
342           if (per > 0xffff)
343                     return EINVAL;
344           sr = pertofreq(per);
345 
346           for (i = 0; i < 4; i++) {
347                     sc->sc_channel[i].nd_freq = sr;
348                     sc->sc_channel[i].nd_per = per;
349           }
350 
351           return 0;
352 }
353 
354 int
aucc_query_format(void * addr,audio_format_query_t * afp)355 aucc_query_format(void *addr, audio_format_query_t *afp)
356 {
357 
358           return audio_query_format(aucc_formats, AUCC_NFORMATS, afp);
359 }
360 
361 int
aucc_set_format(void * addr,int setmode,const audio_params_t * p,const audio_params_t * r,audio_filter_reg_t * pfil,audio_filter_reg_t * rfil)362 aucc_set_format(void *addr, int setmode,
363           const audio_params_t *p, const audio_params_t *r,
364           audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
365 {
366           struct aucc_softc *sc;
367 
368           sc = addr;
369           KASSERT((setmode & AUMODE_RECORD) == 0);
370 
371 #ifdef AUCCDEBUG
372           printf("%s(setmode 0x%x,"
373               "enc %u bits %u, chn %u, sr %u)\n", setmode,
374               p->encoding, p->precision, p->channels, p->sample_rate);
375 #endif
376 
377           switch (p->channels) {
378           case 1:
379                     sc->sc_decodefunc = aucc_decode_slinear16_1ch;
380                     break;
381           case 2:
382                     sc->sc_decodefunc = aucc_decode_slinear16_2ch;
383                     break;
384           case 3:
385                     sc->sc_decodefunc = aucc_decode_slinear16_3ch;
386                     break;
387           case 4:
388                     sc->sc_decodefunc = aucc_decode_slinear16_4ch;
389                     break;
390           default:
391                     return EINVAL;
392           }
393 
394           sc->sc_encoding = p->encoding;
395           sc->sc_precision = p->precision;
396           sc->sc_14bit = ((p->precision == 16) && (p->channels <= 2));
397           sc->sc_channels = sc->sc_14bit ? (p->channels * 2) : p->channels;
398 
399           return aucc_set_out_sr(addr, p->sample_rate);
400 }
401 
402 int
aucc_round_blocksize(void * addr,int blk,int mode,const audio_params_t * param)403 aucc_round_blocksize(void *addr, int blk,
404                          int mode, const audio_params_t *param)
405 {
406 
407           if (blk > AUDIO_BUF_SIZE)
408                     blk = AUDIO_BUF_SIZE;
409 
410           blk = rounddown(blk, param->channels * param->precision / NBBY);
411           return blk;
412 }
413 
414 int
aucc_commit_settings(void * addr)415 aucc_commit_settings(void *addr)
416 {
417           struct aucc_softc *sc;
418           int i;
419 
420           DPRINTF(("sa_commit.\n"));
421 
422           sc = addr;
423           for (i = 0; i < 4; i++) {
424                     custom.aud[i].vol = sc->sc_channel[i].nd_volume;
425                     custom.aud[i].per = sc->sc_channel[i].nd_per;
426           }
427 
428           DPRINTF(("commit done\n"));
429 
430           return 0;
431 }
432 
433 static int masks[4] = {1,3,7,15}; /* masks for n first channels */
434 static int masks2[4] = {1,2,4,8};
435 
436 int
aucc_start_output(void * addr,void * p,int cc,void (* intr)(void *),void * arg)437 aucc_start_output(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
438 {
439           struct aucc_softc *sc;
440           int mask;
441           int i, j, k, len;
442           u_char *dmap[4];
443 
444 
445           sc = addr;
446           mask = sc->sc_channelmask;
447 
448           dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL;
449 
450           DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
451 
452           if (sc->sc_channels > 1)
453                     mask &= masks[sc->sc_channels - 1];
454                     /* we use first sc_channels channels */
455           if (mask == 0) /* active and used channels are disjoint */
456                     return EINVAL;
457 
458           for (i = 0; i < 4; i++) {
459                     /* channels available ? */
460                     if ((masks2[i] & mask) && (sc->sc_channel[i].nd_busy))
461                               return EBUSY; /* channel is busy */
462                     if (channel[i].isaudio == -1)
463                               return EBUSY; /* system uses them */
464           }
465 
466           /* enable interrupt on 1st channel */
467           for (i = j = 0; i < AUCC_MAXINT; i++) {
468                     if (masks2[i] & mask) {
469                               DPRINTF(("first channel is %d\n",i));
470                               j = i;
471                               sc->sc_channel[i].nd_intr = intr;
472                               sc->sc_channel[i].nd_intrdata = arg;
473                               break;
474                     }
475           }
476 
477           DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
478                      dmap[2], dmap[3], mask));
479 
480           /* disable ints, DMA for channels, until all parameters set */
481           /* XXX dont disable DMA! custom.dmacon=mask;*/
482           custom.intreq = mask << INTB_AUD0;
483           custom.intena = mask << INTB_AUD0;
484 
485           /* copy data to DMA buffer */
486 
487           if (sc->sc_channels == 1) {
488                     dmap[0] =
489                     dmap[1] =
490                     dmap[2] =
491                     dmap[3] = (u_char *)sc->sc_channel[j].nd_dma;
492           } else {
493                     for (k = 0; k < 4; k++) {
494                               if (masks2[k+j] & mask)
495                                         dmap[k] = (u_char *)sc->sc_channel[k+j].nd_dma;
496                     }
497           }
498 
499           sc->sc_channel[j].nd_doublebuf ^= 1;
500           if (sc->sc_channel[j].nd_doublebuf) {
501                     dmap[0] += AUDIO_BUF_SIZE;
502                     dmap[1] += AUDIO_BUF_SIZE;
503                     dmap[2] += AUDIO_BUF_SIZE;
504                     dmap[3] += AUDIO_BUF_SIZE;
505           }
506 
507           /*
508            * compute output length in bytes per channel.
509            * divide by two only for 16bit->8bit conversion.
510            */
511           len = cc / sc->sc_channels;
512           if (!sc->sc_14bit && (sc->sc_precision == 16))
513                     len /= 2;
514 
515           /* call audio decoding routine */
516           sc->sc_decodefunc (dmap, (u_char *)p, len);
517 
518           /* DMA buffers: we use same buffer 4 all channels
519            * write DMA location and length
520            */
521           for (i = k = 0; i < 4; i++) {
522                     if (masks2[i] & mask) {
523                               DPRINTF(("turning channel %d on\n",i));
524                               /* sc->sc_channel[i].nd_busy=1; */
525                               channel[i].isaudio = 1;
526                               channel[i].play_count = 1;
527                               channel[i].handler = NULL;
528                               custom.aud[i].per = sc->sc_channel[i].nd_per;
529                               if (sc->sc_14bit && (i > 1))
530                                         custom.aud[i].vol = 1;
531                               else
532                                         custom.aud[i].vol = sc->sc_channel[i].nd_volume;
533                               custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
534                               custom.aud[i].len = len / 2;
535                               sc->sc_channel[i].nd_mask = mask;
536                               DPRINTF(("per is %d, vol is %d, len is %d\n",\
537                                   sc->sc_channel[i].nd_per,
538                                   sc->sc_channel[i].nd_volume, len));
539                     }
540           }
541 
542           channel[j].handler = aucc_inthdl;
543 
544           /* enable ints */
545           custom.intena = INTF_SETCLR | INTF_INTEN | (masks2[j] << INTB_AUD0);
546 
547           DPRINTF(("enabled ints: 0x%x\n", (masks2[j] << INTB_AUD0)));
548 
549           /* enable DMA */
550           custom.dmacon = DMAF_SETCLR | DMAF_MASTER | mask;
551 
552           DPRINTF(("enabled DMA, mask=0x%x\n",mask));
553 
554           return 0;
555 }
556 
557 /* ARGSUSED */
558 int
aucc_start_input(void * addr,void * p,int cc,void (* intr)(void *),void * arg)559 aucc_start_input(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
560 {
561 
562           return ENXIO; /* no input */
563 }
564 
565 int
aucc_halt_output(void * addr)566 aucc_halt_output(void *addr)
567 {
568           struct aucc_softc *sc;
569           int i;
570 
571           /* XXX only halt, if input is also halted ?? */
572           sc = addr;
573           /* stop DMA, etc */
574           custom.intena = AUCC_ALLINTF;
575           custom.dmacon = AUCC_ALLDMAF;
576           /* mark every busy unit idle */
577           for (i = 0; i < 4; i++) {
578                     sc->sc_channel[i].nd_busy = sc->sc_channel[i].nd_mask = 0;
579                     channel[i].isaudio = 0;
580                     channel[i].play_count = 0;
581           }
582 
583           return 0;
584 }
585 
586 int
aucc_halt_input(void * addr)587 aucc_halt_input(void *addr)
588 {
589 
590           /* no input */
591           return ENXIO;
592 }
593 
594 int
aucc_getdev(void * addr,struct audio_device * retp)595 aucc_getdev(void *addr, struct audio_device *retp)
596 {
597 
598           *retp = aucc_device;
599           return 0;
600 }
601 
602 int
aucc_set_port(void * addr,mixer_ctrl_t * cp)603 aucc_set_port(void *addr, mixer_ctrl_t *cp)
604 {
605           struct aucc_softc *sc;
606           int i,j;
607 
608           DPRINTF(("aucc_set_port: port=%d", cp->dev));
609           sc = addr;
610           switch (cp->type) {
611           case AUDIO_MIXER_SET:
612                     if (cp->dev != AUCC_CHANNELS)
613                               return EINVAL;
614                     i = cp->un.mask;
615                     if ((i < 1) || (i > 15))
616                               return EINVAL;
617 
618                     sc->sc_channelmask = i;
619                     break;
620 
621           case AUDIO_MIXER_VALUE:
622                     i = cp->un.value.num_channels;
623                     if ((i < 1) || (i > 4))
624                               return EINVAL;
625 
626 #ifdef __XXXwhatsthat
627                     if (cp->dev != AUCC_VOLUME)
628                               return EINVAL;
629 #endif
630 
631                     /* set volume for channel 0..i-1 */
632 
633                     /* evil workaround for xanim bug, IMO */
634                     if ((sc->sc_channels == 1) && (i == 2)) {
635                               sc->sc_channel[0].nd_volume =
636                                   sc->sc_channel[3].nd_volume =
637                                   cp->un.value.level[0] >> 2;
638                               sc->sc_channel[1].nd_volume =
639                                   sc->sc_channel[2].nd_volume =
640                                   cp->un.value.level[1] >> 2;
641                     } else if (i > 1) {
642                               for (j = 0; j < i; j++)
643                                         sc->sc_channel[j].nd_volume =
644                                             cp->un.value.level[j] >> 2;
645                     } else if (sc->sc_channels > 1)
646                               for (j = 0; j < sc->sc_channels; j++)
647                                         sc->sc_channel[j].nd_volume =
648                                             cp->un.value.level[0] >> 2;
649                     else
650                               for (j = 0; j < 4; j++)
651                                         sc->sc_channel[j].nd_volume =
652                                             cp->un.value.level[0] >> 2;
653                     break;
654 
655           default:
656                     return EINVAL;
657                     break;
658           }
659           return 0;
660 }
661 
662 
663 int
aucc_get_port(void * addr,mixer_ctrl_t * cp)664 aucc_get_port(void *addr, mixer_ctrl_t *cp)
665 {
666           struct aucc_softc *sc;
667           int i,j;
668 
669           DPRINTF(("aucc_get_port: port=%d", cp->dev));
670           sc = addr;
671           switch (cp->type) {
672           case AUDIO_MIXER_SET:
673                     if (cp->dev != AUCC_CHANNELS)
674                               return EINVAL;
675                     cp->un.mask = sc->sc_channelmask;
676                     break;
677 
678           case AUDIO_MIXER_VALUE:
679                     i = cp->un.value.num_channels;
680                     if ((i < 1) || (i > 4))
681                               return EINVAL;
682 
683                     for (j = 0; j < i; j++)
684                               cp->un.value.level[j] =
685                                   (sc->sc_channel[j].nd_volume << 2) +
686                                   (sc->sc_channel[j].nd_volume >> 4);
687                     break;
688 
689           default:
690                     return EINVAL;
691           }
692           return 0;
693 }
694 
695 
696 int
aucc_get_props(void * addr)697 aucc_get_props(void *addr)
698 {
699 
700           return AUDIO_PROP_PLAYBACK;
701 }
702 
703 
704 void
aucc_get_locks(void * opaque,kmutex_t ** intr,kmutex_t ** thread)705 aucc_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread)
706 {
707           struct aucc_softc *sc = opaque;
708 
709           *intr = &sc->sc_intr_lock;
710           *thread = &sc->sc_lock;
711 }
712 
713 int
aucc_query_devinfo(void * addr,register mixer_devinfo_t * dip)714 aucc_query_devinfo(void *addr, register mixer_devinfo_t *dip)
715 {
716           int i;
717 
718           switch(dip->index) {
719           case AUCC_CHANNELS:
720                     dip->type = AUDIO_MIXER_SET;
721                     dip->mixer_class = AUCC_OUTPUT_CLASS;
722                     dip->prev = dip->next = AUDIO_MIXER_LAST;
723 #define setname(a) strlcpy(dip->label.name, (a), sizeof(dip->label.name))
724                     setname(AudioNspeaker);
725                     for (i = 0; i < 16; i++) {
726                               snprintf(dip->un.s.member[i].label.name,
727                                   sizeof(dip->un.s.member[i].label.name),
728                                   "channelmask%d", i);
729                               dip->un.s.member[i].mask = i;
730                     }
731                     dip->un.s.num_mem = 16;
732                     break;
733 
734           case AUCC_VOLUME:
735                     dip->type = AUDIO_MIXER_VALUE;
736                     dip->mixer_class = AUCC_OUTPUT_CLASS;
737                     dip->prev = dip->next = AUDIO_MIXER_LAST;
738                     setname(AudioNmaster);
739                     dip->un.v.num_channels = 4;
740                     strcpy(dip->un.v.units.name, AudioNvolume);
741                     break;
742 
743           case AUCC_OUTPUT_CLASS:
744                     dip->type = AUDIO_MIXER_CLASS;
745                     dip->mixer_class = AUCC_OUTPUT_CLASS;
746                     dip->next = dip->prev = AUDIO_MIXER_LAST;
747                     setname(AudioCoutputs);
748                     break;
749 
750           default:
751                     return ENXIO;
752           }
753 
754           DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
755 
756           return 0;
757 }
758 
759 /* audio int handler */
760 void
aucc_inthdl(int ch)761 aucc_inthdl(int ch)
762 {
763           int i;
764           int mask;
765 
766           mutex_spin_enter(&aucc->sc_intr_lock);
767           mask = aucc->sc_channel[ch].nd_mask;
768           /*
769            * for all channels in this maskgroup:
770            * disable DMA, int
771            * mark idle
772            */
773           DPRINTF(("inthandler called, channel %d, mask 0x%x\n", ch, mask));
774 
775           custom.intreq = mask << INTB_AUD0; /* clear request */
776           /*
777            * XXX: maybe we can leave ints and/or DMA on,
778            * if another sample has to be played?
779            */
780           custom.intena = mask << INTB_AUD0;
781           /*
782            * XXX custom.dmacon=mask; NO!!!
783            */
784           for (i = 0; i < 4; i++) {
785                     if (masks2[i] && mask) {
786                               DPRINTF(("marking channel %d idle\n",i));
787                               aucc->sc_channel[i].nd_busy = 0;
788                               aucc->sc_channel[i].nd_mask = 0;
789                               channel[i].isaudio = channel[i].play_count = 0;
790                     }
791           }
792 
793           /* call handler */
794           if (aucc->sc_channel[ch].nd_intr) {
795                     DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
796                     (*(aucc->sc_channel[ch].nd_intr))
797                         (aucc->sc_channel[ch].nd_intrdata);
798           } else
799                     DPRINTF(("zero int handler\n"));
800           mutex_spin_exit(&aucc->sc_intr_lock);
801           DPRINTF(("ints done\n"));
802 }
803 
804 /* transform frequency to period, adjust bounds */
805 static u_int
freqtoper(u_int freq)806 freqtoper(u_int freq)
807 {
808           u_int per;
809 
810           per = eclockfreq * 5 / freq;
811           if (per < 124)
812                     per = 124;   /* must have at least 124 ticks between samples */
813 
814           return per;
815 }
816 
817 /* transform period to frequency */
818 static u_int
pertofreq(u_int per)819 pertofreq(u_int per)
820 {
821 
822           return eclockfreq * 5 / per;
823 }
824 
825 
826 /* 14bit output */
827 static void
aucc_decode_slinear16_1ch(u_char ** dmap,u_char * p,int i)828 aucc_decode_slinear16_1ch(u_char **dmap, u_char *p, int i)
829 {
830           u_char *ch0;
831           u_char *ch3;
832 
833           ch0 = dmap[0];
834           ch3 = dmap[1];                /* XXX should be 3 */
835           while (i--) {
836                     *ch0++ = *p++;
837                     *ch3++ = *p++ >> 2;
838           }
839 }
840 
841 /* 14bit stereo output */
842 static void
aucc_decode_slinear16_2ch(u_char ** dmap,u_char * p,int i)843 aucc_decode_slinear16_2ch(u_char **dmap, u_char *p, int i)
844 {
845           u_char *ch0;
846           u_char *ch1;
847           u_char *ch2;
848           u_char *ch3;
849 
850           ch0 = dmap[0];
851           ch1 = dmap[1];
852           ch2 = dmap[2];
853           ch3 = dmap[3];
854           while (i--) {
855                     *ch0++ = *p++;
856                     *ch3++ = *p++ >> 2;
857                     *ch1++ = *p++;
858                     *ch2++ = *p++ >> 2;
859           }
860 }
861 
862 static void
aucc_decode_slinear16_3ch(u_char ** dmap,u_char * p,int i)863 aucc_decode_slinear16_3ch(u_char **dmap, u_char *p, int i)
864 {
865           u_char *ch0;
866           u_char *ch1;
867           u_char *ch2;
868 
869           ch0 = dmap[0];
870           ch1 = dmap[1];
871           ch2 = dmap[2];
872           while (i--) {
873                     *ch0++ = *p++; p++;
874                     *ch1++ = *p++; p++;
875                     *ch2++ = *p++; p++;
876           }
877 }
878 
879 static void
aucc_decode_slinear16_4ch(u_char ** dmap,u_char * p,int i)880 aucc_decode_slinear16_4ch(u_char **dmap, u_char *p, int i)
881 {
882           u_char *ch0;
883           u_char *ch1;
884           u_char *ch2;
885           u_char *ch3;
886 
887           ch0 = dmap[0];
888           ch1 = dmap[1];
889           ch2 = dmap[2];
890           ch3 = dmap[3];
891           while (i--) {
892                     *ch0++ = *p++; p++;
893                     *ch1++ = *p++; p++;
894                     *ch2++ = *p++; p++;
895                     *ch3++ = *p++; p++;
896           }
897 }
898 
899 #endif /* NAUCC > 0 */
900