xref: /openbsd-src/sys/dev/pci/sv.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /*      $OpenBSD: sv.c,v 1.31 2014/07/12 18:48:52 tedu Exp $ */
2 
3 /*
4  * Copyright (c) 1998 Constantine Paul Sapuntzakis
5  * All rights reserved
6  *
7  * Author: Constantine Paul Sapuntzakis (csapuntz@cvs.openbsd.org)
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. The author's name or those of the contributors may be used to
18  *    endorse or promote products derived from this software without
19  *    specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /*
35  * S3 SonicVibes driver
36  *   Heavily based on the eap driver by Lennart Augustsson
37  */
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/malloc.h>
43 #include <sys/device.h>
44 
45 #include <dev/pci/pcireg.h>
46 #include <dev/pci/pcivar.h>
47 #include <dev/pci/pcidevs.h>
48 
49 #include <sys/audioio.h>
50 #include <dev/audio_if.h>
51 #include <dev/mulaw.h>
52 #include <dev/auconv.h>
53 
54 #include <dev/ic/i8237reg.h>
55 #include <dev/ic/s3_617.h>
56 
57 
58 #include <machine/bus.h>
59 
60 #ifdef __OpenBSD__
61 struct        cfdriver sv_cd = {
62       NULL, "sv", DV_DULL
63 };
64 #endif
65 
66 #ifdef AUDIO_DEBUG
67 #define DPRINTF(x)	if (svdebug) printf x
68 #define DPRINTFN(n,x)	if (svdebug>(n)) printf x
69 static int	svdebug = 100;
70 #else
71 #define DPRINTF(x)
72 #define DPRINTFN(n,x)
73 #endif
74 
75 int	sv_match(struct device *, void *, void *);
76 static void	sv_attach(struct device *, struct device *, void *);
77 int	sv_intr(void *);
78 
79 struct sv_dma {
80 	bus_dmamap_t map;
81         caddr_t addr;
82         bus_dma_segment_t segs[1];
83         int nsegs;
84         size_t size;
85         struct sv_dma *next;
86 };
87 #define DMAADDR(map) ((map)->segs[0].ds_addr)
88 #define KERNADDR(map) ((void *)((map)->addr))
89 
90 enum {
91   SV_DMAA_CONFIGURED = 1,
92   SV_DMAC_CONFIGURED = 2,
93   SV_DMAA_TRIED_CONFIGURE = 4,
94   SV_DMAC_TRIED_CONFIGURE = 8
95 };
96 
97 struct sv_softc {
98 	struct device sc_dev;		/* base device */
99 	void *sc_ih;			/* interrupt vectoring */
100 
101         pci_chipset_tag_t sc_pci_chipset_tag;
102         pcitag_t  sc_pci_tag;
103 
104 	bus_space_tag_t sc_iot;
105 	bus_space_handle_t sc_ioh;
106 	bus_space_handle_t sc_dmaa_ioh;
107 	bus_space_handle_t sc_dmac_ioh;
108 	bus_dma_tag_t sc_dmatag;	/* DMA tag */
109 
110         struct sv_dma *sc_dmas;
111 
112 	void	(*sc_pintr)(void *);	/* dma completion intr handler */
113 	void	*sc_parg;		/* arg for sc_intr() */
114 
115 	void	(*sc_rintr)(void *);	/* dma completion intr handler */
116 	void	*sc_rarg;		/* arg for sc_intr() */
117 	char	sc_enable;
118         char    sc_trd;
119 
120         char    sc_dma_configured;
121         u_int	sc_record_source;	/* recording source mask */
122 };
123 
124 
125 struct cfattach sv_ca = {
126 	sizeof(struct sv_softc), sv_match, sv_attach
127 };
128 
129 struct audio_device sv_device = {
130 	"S3 SonicVibes",
131 	"",
132 	"sv"
133 };
134 
135 #define ARRAY_SIZE(foo)  ((sizeof(foo)) / sizeof(foo[0]))
136 
137 int	sv_allocmem(struct sv_softc *, size_t, size_t, struct sv_dma *);
138 int	sv_freemem(struct sv_softc *, struct sv_dma *);
139 
140 int	sv_open(void *, int);
141 void	sv_close(void *);
142 int	sv_query_encoding(void *, struct audio_encoding *);
143 int	sv_set_params(void *, int, int, struct audio_params *, struct audio_params *);
144 int	sv_round_blocksize(void *, int);
145 int	sv_dma_init_output(void *, void *, int);
146 int	sv_dma_init_input(void *, void *, int);
147 int	sv_dma_output(void *, void *, int, void (*)(void *), void *);
148 int	sv_dma_input(void *, void *, int, void (*)(void *), void *);
149 int	sv_halt_in_dma(void *);
150 int	sv_halt_out_dma(void *);
151 int	sv_getdev(void *, struct audio_device *);
152 int	sv_mixer_set_port(void *, mixer_ctrl_t *);
153 int	sv_mixer_get_port(void *, mixer_ctrl_t *);
154 int	sv_query_devinfo(void *, mixer_devinfo_t *);
155 void   *sv_malloc(void *, int, size_t, int, int);
156 void	sv_free(void *, void *, int);
157 paddr_t	sv_mappage(void *, void *, off_t, int);
158 int	sv_get_props(void *);
159 
160 void    sv_dumpregs(struct sv_softc *sc);
161 
162 struct audio_hw_if sv_hw_if = {
163 	sv_open,
164 	sv_close,
165 	NULL,
166 	sv_query_encoding,
167 	sv_set_params,
168 	sv_round_blocksize,
169 	NULL,
170 	sv_dma_init_output,
171 	sv_dma_init_input,
172 	sv_dma_output,
173 	sv_dma_input,
174 	sv_halt_out_dma,
175 	sv_halt_in_dma,
176 	NULL,
177 	sv_getdev,
178 	NULL,
179 	sv_mixer_set_port,
180 	sv_mixer_get_port,
181 	sv_query_devinfo,
182 	sv_malloc,
183 	sv_free,
184 	NULL,
185 	sv_mappage,
186 	sv_get_props,
187 	NULL,
188 	NULL,
189 	NULL
190 };
191 
192 
193 static __inline__ u_int8_t sv_read(struct sv_softc *, u_int8_t);
194 static __inline__ u_int8_t sv_read_indirect(struct sv_softc *, u_int8_t);
195 static __inline__ void sv_write(struct sv_softc *, u_int8_t, u_int8_t );
196 static __inline__ void sv_write_indirect(struct sv_softc *, u_int8_t, u_int8_t );
197 static void sv_init_mixer(struct sv_softc *);
198 
199 static __inline__ void
200 sv_write (struct sv_softc *sc, u_int8_t reg, u_int8_t val)
201 {
202   bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, val);
203 }
204 
205 static __inline__ u_int8_t
206 sv_read (struct sv_softc *sc, u_int8_t reg)
207 {
208   return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, reg));
209 }
210 
211 static __inline__ u_int8_t
212 sv_read_indirect (struct sv_softc *sc, u_int8_t reg)
213 {
214     u_int8_t iaddr = 0;
215 
216     if (sc->sc_trd > 0)
217       iaddr |= SV_IADDR_TRD;
218 
219     iaddr |= (reg & SV_IADDR_MASK);
220     sv_write (sc, SV_CODEC_IADDR, iaddr);
221 
222     return (sv_read(sc, SV_CODEC_IDATA));
223 }
224 
225 static __inline__ void
226 sv_write_indirect (struct sv_softc *sc, u_int8_t reg, u_int8_t val)
227 {
228     u_int8_t iaddr = 0;
229 #ifdef DIAGNOSTIC
230     if (reg > 0x3f) {
231       printf ("Invalid register\n");
232       return;
233     }
234 #endif
235 
236     if (reg == SV_DMA_DATA_FORMAT)
237       iaddr |= SV_IADDR_MCE;
238 
239     if (sc->sc_trd > 0)
240       iaddr |= SV_IADDR_TRD;
241 
242     iaddr |= (reg & SV_IADDR_MASK);
243     sv_write (sc, SV_CODEC_IADDR, iaddr);
244     sv_write (sc, SV_CODEC_IDATA, val);
245 }
246 
247 int
248 sv_match(struct device *parent, void *match, void *aux)
249 {
250 	struct pci_attach_args *pa = aux;
251 
252 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_S3 &&
253 	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_S3_SONICVIBES)
254 	  return (1);
255 
256 	return (0);
257 }
258 
259 static void
260 sv_attach(struct device *parent, struct device *self, void *aux)
261 {
262   struct sv_softc *sc = (struct sv_softc *)self;
263   struct pci_attach_args *pa = aux;
264   pci_chipset_tag_t pc = pa->pa_pc;
265   pci_intr_handle_t ih;
266   bus_size_t iosize;
267   char const *intrstr;
268   u_int32_t  dmareg, dmaio;
269   u_int8_t   reg;
270 
271   sc->sc_pci_chipset_tag = pc;
272   sc->sc_pci_tag = pa->pa_tag;
273 
274   /* Map the enhanced port only */
275   if (pci_mapreg_map(pa, SV_ENHANCED_PORTBASE_SLOT, PCI_MAPREG_TYPE_IO, 0,
276       &sc->sc_iot, &sc->sc_ioh, NULL, &iosize, 0)) {
277     printf (": Couldn't map enhanced synth I/O range\n");
278     return;
279   }
280 
281   sc->sc_dmatag = pa->pa_dmat;
282 
283   dmareg = pci_conf_read(pa->pa_pc, pa->pa_tag, SV_DMAA_CONFIG_OFF);
284   iosize = 0x10;
285   dmaio =  dmareg & ~(iosize - 1);
286 
287   if (dmaio) {
288     dmareg &= 0xF;
289 
290     if (bus_space_map(sc->sc_iot, dmaio, iosize, 0, &sc->sc_dmaa_ioh)) {
291       /* The BIOS assigned us some bad I/O address! Make sure to clear
292          and disable this DMA before we enable the device */
293       pci_conf_write(pa->pa_pc, pa->pa_tag, SV_DMAA_CONFIG_OFF, 0);
294 
295       printf (": can't map DMA i/o space\n");
296       goto enable;
297     }
298 
299     pci_conf_write(pa->pa_pc, pa->pa_tag, SV_DMAA_CONFIG_OFF,
300 		   dmaio | dmareg |
301 		   SV_DMA_CHANNEL_ENABLE | SV_DMAA_EXTENDED_ADDR);
302     sc->sc_dma_configured |= SV_DMAA_CONFIGURED;
303   }
304 
305   dmareg = pci_conf_read(pa->pa_pc, pa->pa_tag, SV_DMAC_CONFIG_OFF);
306   dmaio = dmareg & ~(iosize - 1);
307   if (dmaio) {
308     dmareg &= 0xF;
309 
310     if (bus_space_map(sc->sc_iot, dmaio, iosize, 0, &sc->sc_dmac_ioh)) {
311       /* The BIOS assigned us some bad I/O address! Make sure to clear
312          and disable this DMA before we enable the device */
313       pci_conf_write (pa->pa_pc, pa->pa_tag, SV_DMAC_CONFIG_OFF,
314 		      dmareg & ~SV_DMA_CHANNEL_ENABLE);
315       printf (": can't map DMA i/o space\n");
316       goto enable;
317     }
318 
319     pci_conf_write(pa->pa_pc, pa->pa_tag, SV_DMAC_CONFIG_OFF,
320 		   dmaio | dmareg | SV_DMA_CHANNEL_ENABLE);
321     sc->sc_dma_configured |= SV_DMAC_CONFIGURED;
322   }
323 
324   /* Enable the device. */
325  enable:
326   sv_write_indirect(sc, SV_ANALOG_POWER_DOWN_CONTROL, 0);
327   sv_write_indirect(sc, SV_DIGITAL_POWER_DOWN_CONTROL, 0);
328 
329   /* initialize codec registers */
330   reg = sv_read(sc, SV_CODEC_CONTROL);
331   reg |= SV_CTL_RESET;
332   sv_write(sc, SV_CODEC_CONTROL, reg);
333   delay(50);
334 
335   reg = sv_read(sc, SV_CODEC_CONTROL);
336   reg &= ~SV_CTL_RESET;
337   reg |= SV_CTL_INTA | SV_CTL_ENHANCED;
338 
339   /* This write clears the reset */
340   sv_write(sc, SV_CODEC_CONTROL, reg);
341   delay(50);
342 
343   /* This write actually shoves the new values in */
344   sv_write(sc, SV_CODEC_CONTROL, reg);
345 
346   DPRINTF (("reg: %x\n", sv_read(sc, SV_CODEC_CONTROL)));
347 
348   /* Enable DMA interrupts */
349   reg = sv_read(sc, SV_CODEC_INTMASK);
350   reg &= ~(SV_INTMASK_DMAA | SV_INTMASK_DMAC);
351   reg |= SV_INTMASK_UD | SV_INTMASK_SINT | SV_INTMASK_MIDI;
352   sv_write(sc, SV_CODEC_INTMASK, reg);
353 
354   sv_read(sc, SV_CODEC_STATUS);
355 
356   sc->sc_trd = 0;
357   sc->sc_enable = 0;
358 
359   /* Map and establish the interrupt. */
360   if (pci_intr_map(pa, &ih)) {
361     printf(": couldn't map interrupt\n");
362     return;
363   }
364   intrstr = pci_intr_string(pc, ih);
365   sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE,
366       sv_intr, sc, sc->sc_dev.dv_xname);
367   if (sc->sc_ih == NULL) {
368     printf(": couldn't establish interrupt");
369     if (intrstr != NULL)
370       printf(" at %s", intrstr);
371     printf("\n");
372     return;
373   }
374   printf(": %s\n", intrstr);
375 
376   sv_init_mixer(sc);
377 
378   audio_attach_mi(&sv_hw_if, sc, &sc->sc_dev);
379 }
380 
381 #ifdef AUDIO_DEBUG
382 void
383 sv_dumpregs(struct sv_softc *sc)
384 {
385   int idx;
386 
387   { int idx;
388   for (idx = 0; idx < 0x50; idx += 4) {
389     printf ("%02x = %x\n", idx, pci_conf_read(sc->sc_pci_chipset_tag,
390             sc->sc_pci_tag, idx));
391   }
392   }
393 
394   for (idx = 0; idx < 6; idx++) {
395     printf ("REG %02x = %02x\n", idx, sv_read(sc, idx));
396   }
397 
398   for (idx = 0; idx < 0x32; idx++) {
399     printf ("IREG %02x = %02x\n", idx, sv_read_indirect(sc, idx));
400   }
401 
402   for (idx = 0; idx < 0x10; idx++) {
403     printf ("DMA %02x = %02x\n", idx,
404 	    bus_space_read_1(sc->sc_iot, sc->sc_dmaa_ioh, idx));
405   }
406 
407   return;
408 }
409 #endif
410 
411 int
412 sv_intr(void *p)
413 {
414   struct sv_softc *sc = p;
415   u_int8_t intr;
416 
417   mtx_enter(&audio_lock);
418   intr = sv_read(sc, SV_CODEC_STATUS);
419 
420   if (!(intr & (SV_INTSTATUS_DMAA | SV_INTSTATUS_DMAC))) {
421     mtx_leave(&audio_lock);
422     return (0);
423   }
424 
425   if (intr & SV_INTSTATUS_DMAA) {
426     if (sc->sc_pintr)
427       sc->sc_pintr(sc->sc_parg);
428   }
429 
430   if (intr & SV_INTSTATUS_DMAC) {
431     if (sc->sc_rintr)
432       sc->sc_rintr(sc->sc_rarg);
433   }
434   mtx_leave(&audio_lock);
435   return (1);
436 }
437 
438 int
439 sv_allocmem(struct sv_softc *sc, size_t size, size_t align, struct sv_dma *p)
440 {
441 	int error;
442 
443 	p->size = size;
444 	error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,
445 				 p->segs, ARRAY_SIZE(p->segs),
446 				 &p->nsegs, BUS_DMA_NOWAIT);
447 	if (error)
448 		return (error);
449 
450 	error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,
451 			       &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
452 	if (error)
453 		goto free;
454 
455 	error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,
456 				  0, BUS_DMA_NOWAIT, &p->map);
457 	if (error)
458 		goto unmap;
459 
460 	error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL,
461 				BUS_DMA_NOWAIT);
462 	if (error)
463 		goto destroy;
464 	return (0);
465 
466 destroy:
467 	bus_dmamap_destroy(sc->sc_dmatag, p->map);
468 unmap:
469 	bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
470 free:
471 	bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
472 	return (error);
473 }
474 
475 int
476 sv_freemem(struct sv_softc *sc, struct sv_dma *p)
477 {
478 	bus_dmamap_unload(sc->sc_dmatag, p->map);
479 	bus_dmamap_destroy(sc->sc_dmatag, p->map);
480 	bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
481 	bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
482 	return (0);
483 }
484 
485 int
486 sv_open(void *addr, int flags)
487 {
488 
489     struct sv_softc *sc = addr;
490     int  intr_mask = 0;
491     u_int8_t reg;
492 
493     /* Map the DMA channels, if necessary */
494     if (!(sc->sc_dma_configured & SV_DMAA_CONFIGURED)) {
495 	/* XXX - there seems to be no general way to find an
496 	   I/O range */
497 	int dmaio;
498 	int iosize = 0x10;
499 
500 	if (sc->sc_dma_configured & SV_DMAA_TRIED_CONFIGURE)
501 	    return (ENXIO);
502 
503 	for (dmaio = 0xa000; dmaio < 0xb000; dmaio += iosize) {
504 	    if (!bus_space_map(sc->sc_iot, dmaio, iosize, 0,
505 			      &sc->sc_dmaa_ioh)) {
506 		goto found_dmaa;
507 	    }
508 	}
509 
510 	sc->sc_dma_configured |= SV_DMAA_TRIED_CONFIGURE;
511 	return (ENXIO);
512     found_dmaa:
513 
514 	pci_conf_write(sc->sc_pci_chipset_tag, sc->sc_pci_tag,
515 		       SV_DMAA_CONFIG_OFF,
516 		       dmaio | SV_DMA_CHANNEL_ENABLE
517 		       | SV_DMAA_EXTENDED_ADDR);
518 
519 	sc->sc_dma_configured |= SV_DMAA_CONFIGURED;
520 	intr_mask = 1;
521     }
522 
523     if (!(sc->sc_dma_configured & SV_DMAC_CONFIGURED)) {
524 	/* XXX - there seems to be no general way to find an
525 	   I/O range */
526 	int dmaio;
527 	int iosize = 0x10;
528 
529 	if (sc->sc_dma_configured & SV_DMAC_TRIED_CONFIGURE)
530 	    return (ENXIO);
531 
532 	for (dmaio = 0xa000; dmaio < 0xb000; dmaio += iosize) {
533 	    if (!bus_space_map(sc->sc_iot, dmaio, iosize, 0,
534 			      &sc->sc_dmac_ioh)) {
535 		goto found_dmac;
536 	    }
537 	}
538 
539 	sc->sc_dma_configured |= SV_DMAC_TRIED_CONFIGURE;
540 	return (ENXIO);
541     found_dmac:
542 
543 	pci_conf_write(sc->sc_pci_chipset_tag, sc->sc_pci_tag,
544 		       SV_DMAC_CONFIG_OFF,
545 		       dmaio | SV_DMA_CHANNEL_ENABLE);
546 
547 	sc->sc_dma_configured |= SV_DMAC_CONFIGURED;
548 	intr_mask = 1;
549     }
550 
551     /* Make sure DMA interrupts are enabled */
552     if (intr_mask) {
553 	reg = sv_read(sc, SV_CODEC_INTMASK);
554 	reg &= ~(SV_INTMASK_DMAA | SV_INTMASK_DMAC);
555 	reg |= SV_INTMASK_UD | SV_INTMASK_SINT | SV_INTMASK_MIDI;
556 	sv_write(sc, SV_CODEC_INTMASK, reg);
557     }
558 
559     sc->sc_pintr = 0;
560     sc->sc_rintr = 0;
561 
562     return (0);
563 }
564 
565 /*
566  * Close function is called at splaudio().
567  */
568 void
569 sv_close(void *addr)
570 {
571 	struct sv_softc *sc = addr;
572 
573         sv_halt_in_dma(sc);
574         sv_halt_out_dma(sc);
575 
576         sc->sc_pintr = 0;
577         sc->sc_rintr = 0;
578 }
579 
580 int
581 sv_query_encoding(void *addr, struct audio_encoding *fp)
582 {
583 	switch (fp->index) {
584 	case 0:
585 		strlcpy(fp->name, AudioEulinear, sizeof fp->name);
586 		fp->encoding = AUDIO_ENCODING_ULINEAR;
587 		fp->precision = 8;
588 		fp->flags = 0;
589 		break;
590 	case 1:
591 		strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
592 		fp->encoding = AUDIO_ENCODING_ULAW;
593 		fp->precision = 8;
594 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
595 		break;
596 	case 2:
597 		strlcpy(fp->name, AudioEalaw, sizeof fp->name);
598 		fp->encoding = AUDIO_ENCODING_ALAW;
599 		fp->precision = 8;
600 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
601 		break;
602 	case 3:
603 		strlcpy(fp->name, AudioEslinear, sizeof fp->name);
604 		fp->encoding = AUDIO_ENCODING_SLINEAR;
605 		fp->precision = 8;
606 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
607 		break;
608         case 4:
609 		strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
610 		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
611 		fp->precision = 16;
612 		fp->flags = 0;
613 		break;
614 	case 5:
615 		strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
616 		fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
617 		fp->precision = 16;
618 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
619 		break;
620 	case 6:
621 		strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
622 		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
623 		fp->precision = 16;
624 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
625 		break;
626 	case 7:
627 		strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
628 		fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
629 		fp->precision = 16;
630 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
631 		break;
632 	default:
633 		return (EINVAL);
634 	}
635 	fp->bps = AUDIO_BPS(fp->precision);
636 	fp->msb = 1;
637 
638 	return (0);
639 }
640 
641 int
642 sv_set_params(void *addr, int setmode, int usemode,
643     struct audio_params *p, struct audio_params *r)
644 {
645 	struct sv_softc *sc = addr;
646 	void (*pswcode)(void *, u_char *buf, int cnt);
647 	void (*rswcode)(void *, u_char *buf, int cnt);
648         u_int32_t mode, val;
649         u_int8_t reg;
650 
651         pswcode = rswcode = 0;
652         switch (p->encoding) {
653         case AUDIO_ENCODING_SLINEAR_BE:
654         	if (p->precision == 16)
655                 	rswcode = pswcode = swap_bytes;
656 		else
657 			pswcode = rswcode = change_sign8;
658 		break;
659         case AUDIO_ENCODING_SLINEAR_LE:
660         	if (p->precision != 16)
661 			pswcode = rswcode = change_sign8;
662         	break;
663         case AUDIO_ENCODING_ULINEAR_BE:
664         	if (p->precision == 16) {
665 			pswcode = swap_bytes_change_sign16_le;
666 			rswcode = change_sign16_swap_bytes_le;
667 		}
668 		break;
669         case AUDIO_ENCODING_ULINEAR_LE:
670         	if (p->precision == 16)
671 			pswcode = rswcode = change_sign16_le;
672         	break;
673         case AUDIO_ENCODING_ULAW:
674         	pswcode = mulaw_to_ulinear8;
675                 rswcode = ulinear8_to_mulaw;
676                 break;
677         case AUDIO_ENCODING_ALAW:
678                 pswcode = alaw_to_ulinear8;
679                 rswcode = ulinear8_to_alaw;
680                 break;
681         default:
682         	return (EINVAL);
683         }
684 
685 	if (p->precision == 16)
686 		mode = SV_DMAA_FORMAT16 | SV_DMAC_FORMAT16;
687 	else
688 		mode = 0;
689 	if (p->channels > 2)
690 		p->channels = 2;
691         if (p->channels == 2)
692         	mode |= SV_DMAA_STEREO | SV_DMAC_STEREO;
693         if (p->sample_rate < 2000)
694 		p->sample_rate = 2000;
695 	if (p->sample_rate > 48000)
696 		p->sample_rate = 48000;
697 
698         p->sw_code = pswcode;
699         r->sw_code = rswcode;
700 	p->bps = AUDIO_BPS(p->precision);
701 	r->bps = AUDIO_BPS(r->precision);
702 	p->msb = r->msb = 1;
703 
704         /* Set the encoding */
705 	reg = sv_read_indirect(sc, SV_DMA_DATA_FORMAT);
706 	reg &= ~(SV_DMAA_FORMAT16 | SV_DMAC_FORMAT16 | SV_DMAA_STEREO |
707 		 SV_DMAC_STEREO);
708 	reg |= (mode);
709 	sv_write_indirect(sc, SV_DMA_DATA_FORMAT, reg);
710 
711 	val = p->sample_rate * 65536 / 48000;
712 
713 	sv_write_indirect(sc, SV_PCM_SAMPLE_RATE_0, (val & 0xff));
714 	sv_write_indirect(sc, SV_PCM_SAMPLE_RATE_1, (val >> 8));
715 
716 #define F_REF 24576000
717 
718 	if (setmode & AUMODE_RECORD)
719 	{
720 	  /* The ADC reference frequency (f_out) is 512 * the sample rate */
721 
722 	  /* f_out is dervied from the 24.576MHZ crystal by three values:
723 	     M & N & R. The equation is as follows:
724 
725 	     f_out = (m + 2) * f_ref / ((n + 2) * (2 ^ a))
726 
727 	     with the constraint that:
728 
729 	     80 MhZ < (m + 2) / (n + 2) * f_ref <= 150MHz
730 	     and n, m >= 1
731 	  */
732 
733 	  int  goal_f_out = 512 * r->sample_rate;
734 	  int  a, n, m, best_n, best_m, best_error = 10000000;
735 	  int  pll_sample;
736 
737 	  for (a = 0; a < 8; a++) {
738 	    if ((goal_f_out * (1 << a)) >= 80000000)
739 	      break;
740 	  }
741 
742 	  /* a != 8 because sample_rate >= 2000 */
743 
744 	  for (n = 33; n > 2; n--) {
745 	    int error;
746 
747 	    m = (goal_f_out * n * (1 << a)) / F_REF;
748 
749 	    if ((m > 257) || (m < 3)) continue;
750 
751 	    pll_sample = (m * F_REF) / (n * (1 << a));
752 	    pll_sample /= 512;
753 
754 	    /* Threshold might be good here */
755 	    error = pll_sample - r->sample_rate;
756 	    error = abs(error);
757 
758 	    if (error < best_error) {
759 	      best_error = error;
760 	      best_n = n;
761 	      best_m = m;
762 	      if (error == 0) break;
763 	    }
764 	  }
765 
766 
767 	  best_n -= 2;
768 	  best_m -= 2;
769 
770 	  sv_write_indirect(sc, SV_ADC_PLL_M, best_m);
771 	  sv_write_indirect(sc, SV_ADC_PLL_N, best_n | (a << SV_PLL_R_SHIFT));
772 	}
773         return (0);
774 }
775 
776 int
777 sv_round_blocksize(void *addr, int blk)
778 {
779 	return ((blk + 31) & -32);	/* keep good alignment */
780 }
781 
782 int
783 sv_dma_init_input(void *addr, void *buf, int cc)
784 {
785 	struct sv_softc *sc = addr;
786 	struct sv_dma *p;
787 	int dma_count;
788 
789 	DPRINTF(("sv_dma_init_input: dma start loop input addr=%p cc=%d\n",
790 		 buf, cc));
791         for (p = sc->sc_dmas; p && KERNADDR(p) != buf; p = p->next)
792 		;
793 	if (!p) {
794 		printf("sv_dma_init_input: bad addr %p\n", buf);
795 		return (EINVAL);
796 	}
797 
798 	dma_count = (cc >> 1) - 1;
799 
800 	bus_space_write_4(sc->sc_iot, sc->sc_dmac_ioh, SV_DMA_ADDR0,
801 			  DMAADDR(p));
802 	bus_space_write_4(sc->sc_iot, sc->sc_dmac_ioh, SV_DMA_COUNT0,
803 			  dma_count);
804 	bus_space_write_1(sc->sc_iot, sc->sc_dmac_ioh, SV_DMA_MODE,
805 			  DMA37MD_WRITE | DMA37MD_LOOP);
806 
807 	return (0);
808 }
809 
810 int
811 sv_dma_init_output(void *addr, void *buf, int cc)
812 {
813 	struct sv_softc *sc = addr;
814 	struct sv_dma *p;
815 	int dma_count;
816 
817 	DPRINTF(("sv: dma start loop output buf=%p cc=%d\n", buf, cc));
818         for (p = sc->sc_dmas; p && KERNADDR(p) != buf; p = p->next)
819 		;
820 	if (!p) {
821 		printf("sv_dma_init_output: bad addr %p\n", buf);
822 		return (EINVAL);
823 	}
824 
825 	dma_count = cc - 1;
826 
827 	bus_space_write_4(sc->sc_iot, sc->sc_dmaa_ioh, SV_DMA_ADDR0,
828 			  DMAADDR(p));
829 	bus_space_write_4(sc->sc_iot, sc->sc_dmaa_ioh, SV_DMA_COUNT0,
830 			  dma_count);
831 	bus_space_write_1(sc->sc_iot, sc->sc_dmaa_ioh, SV_DMA_MODE,
832 			  DMA37MD_READ | DMA37MD_LOOP);
833 
834 	return (0);
835 }
836 
837 int
838 sv_dma_output(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
839 {
840 	struct sv_softc *sc = addr;
841 	u_int8_t mode;
842 
843 	DPRINTFN(1,
844                  ("sv_dma_output: sc=%p buf=%p cc=%d intr=%p(%p)\n",
845                   addr, p, cc, intr, arg));
846 	sc->sc_pintr = intr;
847 	sc->sc_parg = arg;
848 	if (!(sc->sc_enable & SV_PLAY_ENABLE)) {
849 	        int dma_count = cc - 1;
850 
851 		sv_write_indirect(sc, SV_DMAA_COUNT1, dma_count >> 8);
852 		sv_write_indirect(sc, SV_DMAA_COUNT0, (dma_count & 0xFF));
853 
854 		mode = sv_read_indirect(sc, SV_PLAY_RECORD_ENABLE);
855 		mode |= SV_PLAY_ENABLE;
856 		sv_write_indirect(sc, SV_PLAY_RECORD_ENABLE, mode);
857 		sc->sc_enable |= SV_PLAY_ENABLE;
858 	}
859         return (0);
860 }
861 
862 int
863 sv_dma_input(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
864 {
865 	struct sv_softc *sc = addr;
866 	u_int8_t mode;
867 
868 	DPRINTFN(1, ("sv_dma_input: sc=%p buf=%p cc=%d intr=%p(%p)\n",
869 		     addr, p, cc, intr, arg));
870 	sc->sc_rintr = intr;
871 	sc->sc_rarg = arg;
872 	if (!(sc->sc_enable & SV_RECORD_ENABLE)) {
873 	        int dma_count = (cc >> 1) - 1;
874 
875 		sv_write_indirect(sc, SV_DMAC_COUNT1, dma_count >> 8);
876 		sv_write_indirect(sc, SV_DMAC_COUNT0, (dma_count & 0xFF));
877 
878 		mode = sv_read_indirect(sc, SV_PLAY_RECORD_ENABLE);
879 		mode |= SV_RECORD_ENABLE;
880 		sv_write_indirect(sc, SV_PLAY_RECORD_ENABLE, mode);
881 		sc->sc_enable |= SV_RECORD_ENABLE;
882 	}
883         return (0);
884 }
885 
886 int
887 sv_halt_out_dma(void *addr)
888 {
889 	struct sv_softc *sc = addr;
890 	u_int8_t mode;
891 
892         DPRINTF(("sv: sv_halt_out_dma\n"));
893 	mtx_enter(&audio_lock);
894 	mode = sv_read_indirect(sc, SV_PLAY_RECORD_ENABLE);
895 	mode &= ~SV_PLAY_ENABLE;
896 	sc->sc_enable &= ~SV_PLAY_ENABLE;
897 	sv_write_indirect(sc, SV_PLAY_RECORD_ENABLE, mode);
898 	mtx_leave(&audio_lock);
899         return (0);
900 }
901 
902 int
903 sv_halt_in_dma(void *addr)
904 {
905 	struct sv_softc *sc = addr;
906 	u_int8_t mode;
907 
908         DPRINTF(("sv: sv_halt_in_dma\n"));
909 	mtx_enter(&audio_lock);
910 	mode = sv_read_indirect(sc, SV_PLAY_RECORD_ENABLE);
911 	mode &= ~SV_RECORD_ENABLE;
912 	sc->sc_enable &= ~SV_RECORD_ENABLE;
913 	sv_write_indirect(sc, SV_PLAY_RECORD_ENABLE, mode);
914 	mtx_leave(&audio_lock);
915         return (0);
916 }
917 
918 int
919 sv_getdev(void *addr, struct audio_device *retp)
920 {
921 	*retp = sv_device;
922         return (0);
923 }
924 
925 
926 /*
927  * Mixer related code is here
928  *
929  */
930 
931 #define SV_INPUT_CLASS 0
932 #define SV_OUTPUT_CLASS 1
933 #define SV_RECORD_CLASS 2
934 
935 #define SV_LAST_CLASS 2
936 
937 static const char *mixer_classes[] = { AudioCinputs, AudioCoutputs, AudioCrecord };
938 
939 static const struct {
940   u_int8_t   l_port;
941   u_int8_t   r_port;
942   u_int8_t   mask;
943   u_int8_t   class;
944   const char *audio;
945 } ports[] = {
946   { SV_LEFT_AUX1_INPUT_CONTROL, SV_RIGHT_AUX1_INPUT_CONTROL, SV_AUX1_MASK,
947     SV_INPUT_CLASS, "aux1" },
948   { SV_LEFT_CD_INPUT_CONTROL, SV_RIGHT_CD_INPUT_CONTROL, SV_CD_MASK,
949     SV_INPUT_CLASS, AudioNcd },
950   { SV_LEFT_LINE_IN_INPUT_CONTROL, SV_RIGHT_LINE_IN_INPUT_CONTROL, SV_LINE_IN_MASK,
951     SV_INPUT_CLASS, AudioNline },
952   { SV_MIC_INPUT_CONTROL, 0, SV_MIC_MASK, SV_INPUT_CLASS, AudioNmicrophone },
953   { SV_LEFT_SYNTH_INPUT_CONTROL, SV_RIGHT_SYNTH_INPUT_CONTROL,
954     SV_SYNTH_MASK, SV_INPUT_CLASS, AudioNfmsynth },
955   { SV_LEFT_AUX2_INPUT_CONTROL, SV_RIGHT_AUX2_INPUT_CONTROL, SV_AUX2_MASK,
956     SV_INPUT_CLASS, "aux2" },
957   { SV_LEFT_PCM_INPUT_CONTROL, SV_RIGHT_PCM_INPUT_CONTROL, SV_PCM_MASK,
958     SV_INPUT_CLASS, AudioNdac },
959   { SV_LEFT_MIXER_OUTPUT_CONTROL, SV_RIGHT_MIXER_OUTPUT_CONTROL,
960     SV_MIXER_OUT_MASK, SV_OUTPUT_CLASS, AudioNmaster }
961 };
962 
963 
964 static const struct {
965   int idx;
966   const char *name;
967 } record_sources[] = {
968   { SV_REC_CD, AudioNcd },
969   { SV_REC_DAC, AudioNdac },
970   { SV_REC_AUX2, "aux2" },
971   { SV_REC_LINE, AudioNline },
972   { SV_REC_AUX1, "aux1" },
973   { SV_REC_MIC, AudioNmicrophone },
974   { SV_REC_MIXER, AudioNmixerout }
975 };
976 
977 
978 #define SV_DEVICES_PER_PORT 2
979 #define SV_FIRST_MIXER (SV_LAST_CLASS + 1)
980 #define SV_LAST_MIXER (SV_DEVICES_PER_PORT * (ARRAY_SIZE(ports)) + SV_LAST_CLASS)
981 #define SV_RECORD_SOURCE (SV_LAST_MIXER + 1)
982 #define SV_MIC_BOOST (SV_LAST_MIXER + 2)
983 #define SV_RECORD_GAIN (SV_LAST_MIXER + 3)
984 #define SV_SRS_MODE (SV_LAST_MIXER + 4)
985 
986 int
987 sv_query_devinfo(void *addr, mixer_devinfo_t *dip)
988 {
989 
990   if (dip->index < 0)
991     return (ENXIO);
992 
993   /* It's a class */
994   if (dip->index <= SV_LAST_CLASS) {
995     dip->type = AUDIO_MIXER_CLASS;
996     dip->mixer_class = dip->index;
997     dip->next = dip->prev = AUDIO_MIXER_LAST;
998     strlcpy(dip->label.name, mixer_classes[dip->index],
999 	    sizeof dip->label.name);
1000     return (0);
1001   }
1002 
1003   if (dip->index >= SV_FIRST_MIXER &&
1004       dip->index <= SV_LAST_MIXER) {
1005     int off = dip->index - SV_FIRST_MIXER;
1006     int mute = (off % SV_DEVICES_PER_PORT);
1007     int idx = off / SV_DEVICES_PER_PORT;
1008 
1009     dip->mixer_class = ports[idx].class;
1010     strlcpy(dip->label.name, ports[idx].audio, sizeof dip->label.name);
1011 
1012     if (!mute) {
1013       dip->type = AUDIO_MIXER_VALUE;
1014       dip->prev = AUDIO_MIXER_LAST;
1015       dip->next = dip->index + 1;
1016 
1017       if (ports[idx].r_port != 0)
1018 	dip->un.v.num_channels = 2;
1019       else
1020 	dip->un.v.num_channels = 1;
1021 
1022       strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1023 
1024     } else {
1025       dip->type = AUDIO_MIXER_ENUM;
1026       dip->prev = dip->index - 1;
1027       dip->next = AUDIO_MIXER_LAST;
1028 
1029       strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
1030       dip->un.e.num_mem = 2;
1031       strlcpy(dip->un.e.member[0].label.name, AudioNoff,
1032 	  sizeof dip->un.e.member[0].label.name);
1033       dip->un.e.member[0].ord = 0;
1034       strlcpy(dip->un.e.member[1].label.name, AudioNon,
1035 	  sizeof dip->un.e.member[1].label.name);
1036       dip->un.e.member[1].ord = 1;
1037 
1038     }
1039 
1040     return (0);
1041   }
1042 
1043   switch (dip->index) {
1044   case SV_RECORD_SOURCE:
1045     dip->mixer_class = SV_RECORD_CLASS;
1046     dip->prev = AUDIO_MIXER_LAST;
1047     dip->next = SV_RECORD_GAIN;
1048     strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
1049     dip->type = AUDIO_MIXER_ENUM;
1050 
1051     dip->un.e.num_mem = ARRAY_SIZE(record_sources);
1052 
1053     {
1054       int idx;
1055       for (idx = 0; idx < ARRAY_SIZE(record_sources); idx++) {
1056 	strlcpy(dip->un.e.member[idx].label.name, record_sources[idx].name,
1057 	    sizeof dip->un.e.member[idx].label.name);
1058 	dip->un.e.member[idx].ord = record_sources[idx].idx;
1059       }
1060     }
1061     return (0);
1062 
1063   case SV_RECORD_GAIN:
1064     dip->mixer_class = SV_RECORD_CLASS;
1065     dip->prev = SV_RECORD_SOURCE;
1066     dip->next = AUDIO_MIXER_LAST;
1067     strlcpy(dip->label.name, "gain", sizeof dip->label.name);
1068     dip->type = AUDIO_MIXER_VALUE;
1069     dip->un.v.num_channels = 1;
1070     strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
1071     return (0);
1072 
1073   case SV_MIC_BOOST:
1074     dip->mixer_class = SV_RECORD_CLASS;
1075     dip->prev = AUDIO_MIXER_LAST;
1076     dip->next = AUDIO_MIXER_LAST;
1077     strlcpy(dip->label.name, "micboost", sizeof dip->label.name);
1078     goto on_off;
1079 
1080   case SV_SRS_MODE:
1081     dip->mixer_class = SV_OUTPUT_CLASS;
1082     dip->prev = dip->next = AUDIO_MIXER_LAST;
1083     strlcpy(dip->label.name, AudioNspatial, sizeof dip->label.name);
1084 
1085 on_off:
1086     dip->type = AUDIO_MIXER_ENUM;
1087     dip->un.e.num_mem = 2;
1088     strlcpy(dip->un.e.member[0].label.name, AudioNoff,
1089 	sizeof dip->un.e.member[0].label.name);
1090     dip->un.e.member[0].ord = 0;
1091     strlcpy(dip->un.e.member[1].label.name, AudioNon,
1092 	sizeof dip->un.e.member[1].label.name);
1093     dip->un.e.member[1].ord = 1;
1094     return (0);
1095   }
1096 
1097   return (ENXIO);
1098 }
1099 
1100 int
1101 sv_mixer_set_port(void *addr, mixer_ctrl_t *cp)
1102 {
1103   struct sv_softc *sc = addr;
1104   u_int8_t reg;
1105   int idx;
1106 
1107   if (cp->dev >= SV_FIRST_MIXER &&
1108       cp->dev <= SV_LAST_MIXER) {
1109     int off = cp->dev - SV_FIRST_MIXER;
1110     int mute = (off % SV_DEVICES_PER_PORT);
1111     idx = off / SV_DEVICES_PER_PORT;
1112 
1113     if (mute) {
1114       if (cp->type != AUDIO_MIXER_ENUM)
1115 	return (EINVAL);
1116 
1117       reg = sv_read_indirect(sc, ports[idx].l_port);
1118       if (cp->un.ord)
1119 	reg |= SV_MUTE_BIT;
1120       else
1121 	reg &= ~SV_MUTE_BIT;
1122       sv_write_indirect(sc, ports[idx].l_port, reg);
1123 
1124       if (ports[idx].r_port) {
1125 	reg = sv_read_indirect(sc, ports[idx].r_port);
1126 	if (cp->un.ord)
1127 	  reg |= SV_MUTE_BIT;
1128 	else
1129 	  reg &= ~SV_MUTE_BIT;
1130 	sv_write_indirect(sc, ports[idx].r_port, reg);
1131       }
1132     } else {
1133       int  lval, rval;
1134 
1135       if (cp->type != AUDIO_MIXER_VALUE)
1136 	return (EINVAL);
1137 
1138       if (cp->un.value.num_channels != 1 &&
1139 	  cp->un.value.num_channels != 2)
1140 	return (EINVAL);
1141 
1142       if (ports[idx].r_port == 0) {
1143 	if (cp->un.value.num_channels != 1)
1144 	  return (EINVAL);
1145 	lval = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
1146       } else {
1147 	if (cp->un.value.num_channels != 2)
1148 	  return (EINVAL);
1149 
1150 	lval = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
1151 	rval = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
1152       }
1153 
1154       sc->sc_trd = 1;
1155 
1156       reg = sv_read_indirect(sc, ports[idx].l_port);
1157       reg &= ~(ports[idx].mask);
1158       lval = ((AUDIO_MAX_GAIN - lval) * ports[idx].mask) / AUDIO_MAX_GAIN;
1159       reg |= lval;
1160       sv_write_indirect(sc, ports[idx].l_port, reg);
1161 
1162       if (ports[idx].r_port != 0) {
1163 	reg = sv_read_indirect(sc, ports[idx].r_port);
1164 	reg &= ~(ports[idx].mask);
1165 
1166 	rval = ((AUDIO_MAX_GAIN - rval) * ports[idx].mask) / AUDIO_MAX_GAIN;
1167 	reg |= rval;
1168 
1169 	sv_write_indirect(sc, ports[idx].r_port, reg);
1170       }
1171 
1172       sc->sc_trd = 0;
1173       sv_read_indirect(sc, ports[idx].l_port);
1174     }
1175 
1176     return (0);
1177   }
1178 
1179 
1180   switch (cp->dev) {
1181   case SV_RECORD_SOURCE:
1182     if (cp->type != AUDIO_MIXER_ENUM)
1183       return (EINVAL);
1184 
1185     for (idx = 0; idx < ARRAY_SIZE(record_sources); idx++) {
1186       if (record_sources[idx].idx == cp->un.ord)
1187 	goto found;
1188     }
1189 
1190     return (EINVAL);
1191 
1192   found:
1193     reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL);
1194     reg &= ~SV_REC_SOURCE_MASK;
1195     reg |= (((cp->un.ord) << SV_REC_SOURCE_SHIFT) & SV_REC_SOURCE_MASK);
1196     sv_write_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL, reg);
1197 
1198     reg = sv_read_indirect(sc, SV_RIGHT_ADC_INPUT_CONTROL);
1199     reg &= ~SV_REC_SOURCE_MASK;
1200     reg |= (((cp->un.ord) << SV_REC_SOURCE_SHIFT) & SV_REC_SOURCE_MASK);
1201     sv_write_indirect(sc, SV_RIGHT_ADC_INPUT_CONTROL, reg);
1202     return (0);
1203 
1204   case SV_RECORD_GAIN:
1205     {
1206       int val;
1207 
1208       if (cp->type != AUDIO_MIXER_VALUE)
1209 	return (EINVAL);
1210 
1211       if (cp->un.value.num_channels != 1)
1212 	return (EINVAL);
1213 
1214       val = (cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] * SV_REC_GAIN_MASK)
1215 	/ AUDIO_MAX_GAIN;
1216 
1217       reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL);
1218       reg &= ~SV_REC_GAIN_MASK;
1219       reg |= val;
1220       sv_write_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL, reg);
1221 
1222       reg = sv_read_indirect(sc, SV_RIGHT_ADC_INPUT_CONTROL);
1223       reg &= ~SV_REC_GAIN_MASK;
1224       reg |= val;
1225       sv_write_indirect(sc, SV_RIGHT_ADC_INPUT_CONTROL, reg);
1226 
1227     }
1228 
1229     return (0);
1230 
1231   case SV_MIC_BOOST:
1232     if (cp->type != AUDIO_MIXER_ENUM)
1233       return (EINVAL);
1234 
1235     reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL);
1236     if (cp->un.ord) {
1237       reg |= SV_MIC_BOOST_BIT;
1238     } else {
1239       reg &= ~SV_MIC_BOOST_BIT;
1240     }
1241 
1242     sv_write_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL, reg);
1243     return (0);
1244 
1245   case SV_SRS_MODE:
1246     if (cp->type != AUDIO_MIXER_ENUM)
1247       return (EINVAL);
1248 
1249     reg = sv_read_indirect(sc, SV_SRS_SPACE_CONTROL);
1250     if (cp->un.ord) {
1251       reg &= ~SV_SRS_SPACE_ONOFF;
1252     } else {
1253       reg |= SV_SRS_SPACE_ONOFF;
1254     }
1255 
1256     sv_write_indirect(sc, SV_SRS_SPACE_CONTROL, reg);
1257     return (0);
1258   }
1259 
1260   return (EINVAL);
1261 }
1262 
1263 int
1264 sv_mixer_get_port(void *addr, mixer_ctrl_t *cp)
1265 {
1266   struct sv_softc *sc = addr;
1267   int val;
1268   u_int8_t reg;
1269 
1270   if (cp->dev >= SV_FIRST_MIXER &&
1271       cp->dev <= SV_LAST_MIXER) {
1272     int off = cp->dev - SV_FIRST_MIXER;
1273     int mute = (off % 2);
1274     int idx = off / 2;
1275 
1276     if (mute) {
1277       if (cp->type != AUDIO_MIXER_ENUM)
1278 	return (EINVAL);
1279 
1280       reg = sv_read_indirect(sc, ports[idx].l_port);
1281       cp->un.ord = ((reg & SV_MUTE_BIT) ? 1 : 0);
1282     } else {
1283       if (cp->type != AUDIO_MIXER_VALUE)
1284 	return (EINVAL);
1285 
1286       if (cp->un.value.num_channels != 1 &&
1287 	  cp->un.value.num_channels != 2)
1288 	return (EINVAL);
1289 
1290       if ((ports[idx].r_port == 0 &&
1291 	   cp->un.value.num_channels != 1) ||
1292 	  (ports[idx].r_port != 0 &&
1293 	   cp->un.value.num_channels != 2))
1294 	return (EINVAL);
1295 
1296       reg = sv_read_indirect(sc, ports[idx].l_port);
1297       reg &= ports[idx].mask;
1298 
1299       val = AUDIO_MAX_GAIN - ((reg * AUDIO_MAX_GAIN) / ports[idx].mask);
1300 
1301       if (ports[idx].r_port != 0) {
1302 	cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = val;
1303 
1304 	reg = sv_read_indirect(sc, ports[idx].r_port);
1305 	reg &= ports[idx].mask;
1306 
1307 	val = AUDIO_MAX_GAIN - ((reg * AUDIO_MAX_GAIN) / ports[idx].mask);
1308 	cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = val;
1309       } else
1310 	cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = val;
1311     }
1312 
1313     return (0);
1314   }
1315 
1316   switch (cp->dev) {
1317   case SV_RECORD_SOURCE:
1318     if (cp->type != AUDIO_MIXER_ENUM)
1319       return (EINVAL);
1320 
1321     reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL);
1322     cp->un.ord = ((reg & SV_REC_SOURCE_MASK) >> SV_REC_SOURCE_SHIFT);
1323 
1324     return (0);
1325 
1326   case SV_RECORD_GAIN:
1327     if (cp->type != AUDIO_MIXER_VALUE)
1328       return (EINVAL);
1329 
1330     if (cp->un.value.num_channels != 1)
1331       return (EINVAL);
1332 
1333     reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL) & SV_REC_GAIN_MASK;
1334     cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1335       (((unsigned int)reg) * AUDIO_MAX_GAIN) / SV_REC_GAIN_MASK;
1336 
1337     return (0);
1338 
1339   case SV_MIC_BOOST:
1340     if (cp->type != AUDIO_MIXER_ENUM)
1341       return (EINVAL);
1342 
1343     reg = sv_read_indirect(sc, SV_LEFT_ADC_INPUT_CONTROL);
1344     cp->un.ord = ((reg & SV_MIC_BOOST_BIT) ? 1 : 0);
1345 
1346     return (0);
1347 
1348 
1349   case SV_SRS_MODE:
1350     if (cp->type != AUDIO_MIXER_ENUM)
1351       return (EINVAL);
1352 
1353     reg = sv_read_indirect(sc, SV_SRS_SPACE_CONTROL);
1354 
1355     cp->un.ord = ((reg & SV_SRS_SPACE_ONOFF) ? 0 : 1);
1356     return (0);
1357   }
1358 
1359   return (EINVAL);
1360 }
1361 
1362 
1363 static void
1364 sv_init_mixer(struct sv_softc *sc)
1365 {
1366   mixer_ctrl_t cp;
1367   int idx;
1368 
1369   cp.type = AUDIO_MIXER_ENUM;
1370   cp.dev = SV_SRS_MODE;
1371   cp.un.ord = 0;
1372 
1373   sv_mixer_set_port(sc, &cp);
1374 
1375   for (idx = 0; idx < ARRAY_SIZE(ports); idx++) {
1376     if (strcmp(ports[idx].audio, AudioNdac) == 0) {
1377       cp.type = AUDIO_MIXER_ENUM;
1378       cp.dev = SV_FIRST_MIXER + idx * SV_DEVICES_PER_PORT + 1;
1379       cp.un.ord = 0;
1380       sv_mixer_set_port(sc, &cp);
1381       break;
1382     }
1383   }
1384 }
1385 
1386 void *
1387 sv_malloc(void *addr, int direction, size_t size, int pool, int flags)
1388 {
1389 	struct sv_softc *sc = addr;
1390         struct sv_dma *p;
1391         int error;
1392 
1393         p = malloc(sizeof(*p), pool, flags);
1394         if (!p)
1395                 return (0);
1396         error = sv_allocmem(sc, size, 16, p);
1397         if (error) {
1398                 free(p, pool, 0);
1399         	return (0);
1400         }
1401         p->next = sc->sc_dmas;
1402         sc->sc_dmas = p;
1403 	return (KERNADDR(p));
1404 }
1405 
1406 void
1407 sv_free(void *addr, void *ptr, int pool)
1408 {
1409 	struct sv_softc *sc = addr;
1410         struct sv_dma **p;
1411 
1412         for (p = &sc->sc_dmas; *p; p = &(*p)->next) {
1413                 if (KERNADDR(*p) == ptr) {
1414                         sv_freemem(sc, *p);
1415                         *p = (*p)->next;
1416                         free(*p, pool, 0);
1417                         return;
1418                 }
1419         }
1420 }
1421 
1422 paddr_t
1423 sv_mappage(void *addr, void *mem, off_t off, int prot)
1424 {
1425 	struct sv_softc *sc = addr;
1426         struct sv_dma *p;
1427 
1428         for (p = sc->sc_dmas; p && KERNADDR(p) != mem; p = p->next)
1429 		;
1430 	if (!p)
1431 		return (-1);
1432 	return (bus_dmamem_mmap(sc->sc_dmatag, p->segs, p->nsegs,
1433 				off, prot, BUS_DMA_WAITOK));
1434 }
1435 
1436 int
1437 sv_get_props(void *addr)
1438 {
1439 	return (AUDIO_PROP_MMAP | AUDIO_PROP_FULLDUPLEX);
1440 }
1441