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