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