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